背景
最近,我一直在寻找可靠的方法来控制安全的Android Keyguard,主要是为了显示自定义锁屏。我知道Google已经声明自定义锁屏不受平台官方支持,并且应该预料到可能会有问题,但是通过现有的API,我相信必须有方法可以实现这一点。我进行了大量的研究约一周时间,但仍然偶尔遇到问题。截至目前,我的实现方式是假定启用了安全的Keyguard:
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED 允许一个Activity(窗口)显示在屏幕上,将Keyguard放在其后,所有不安全的操作都被防止了。通知面板被禁用,结束该Activity会带回Keyguard。这是我在我的锁屏Activity中实现的方式:
@Override
public void onAttachedToWindow() {
window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
}
KeyguardManager和KeyguardManager.KeyguardLock是已经被弃用的类,但它们仍然可以在Jelly Bean版本中使用。为了实现这个目的,我创建了一个Service来处理两件事情:保存一个静态的KeyguardManager和相关对象,并且让它持有一个BroadcastReceiver来接收Intent.ACTION_SCREEN_ON和Intent.ACTION_SCREEN_OFF。(所有对象都已经正确地初始化)
关于 ScreenReceiver
public static synchronized void disableKeyguard() {
if ( isLocked ) {
if ( keyguardLock == null ) {
keyguardLock = keyguardManager.newKeyguardLock(LOG_TAG);
}
keyguardLock.disableKeyguard();
isLocked = false;
}
}
public static synchronized void reenableKeyguard() {
if ( !isLocked ) {
if ( keyguardLock == null ) {
keyguardLock = keyguardManager.newKeyguardLock(LOG_TAG);
}
keyguardLock.reenableKeyguard();
keyguardLock = null;
isLocked = true;
}
}
关于 BroadcastReceiver:
@Override
public void onReceive( Context context, Intent intent ) {
if ( intent.getAction().equals(Intent.ACTION_SCREEN_ON) ) {
Intent start = new Intent(context, LockScreen.class);
start.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
context.startActivity(start);
} else if ( intent.getAction().equals(Intent.ACTION_SCREEN_OFF) ) {
ScreenReceiverService.reenableKeyguard();
}
}
当用户输入正确的密码时,对于 LockScreenActivity,window.clearFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
ScreenReceiverService.disableKeyguard();
finish();
问题
已经实现的功能
ACTION_ON和ACTION_OFF可靠地接收。
在未处理电话状态的情况下,显示LockScreenActivity,然后再显示解锁界面。
无法拉下通知栏,在任何退出活动的方式下都会显示锁屏。
未能实现的功能
我已禁用Keyguard并调用了finish()方法之后,我的应用程序退出并显示到主屏幕或屏幕关闭之前的最后一个活动。但是,每当我按Home键时,Keyguard会刷入屏幕,立即快速消失,并且正常的Home键功能/事件不被处理(闪烁后不会返回到主屏幕)。这种情况是在我快速重复点击Home键时观察到的。
我甚至看了Android源代码以找出Home键的处理方式,但除非窗口类型为WindowManager.LayoutParams.TYPE_KEYGUARD或WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG,否则不会将其发送给第三方应用程序,在4.0+上甚至会抛出SecurityException异常,尽管它在早期平台上运行正常。对于Keyguard,我已声明了DISABLE_KEYGUARD权限,因此这不应该是问题。我猜测标志FLAG_SHOW_WHEN_LOCKED会告诉系统以某种方式处理Keyguard,可能与其他禁用调用冲突。由于此标志通常用于Alarm/SMS类型的应用程序,即向用户显示有限信息,然后将其关闭并显示Keyguard。但在我的情况下,让用户解锁我的锁屏然后解锁系统锁屏就完全失去了我应用的意义。
所以问题是,为什么我禁用Keyguard后按Home键时Keyguard会闪现?是否有任何解决此问题的变通方法/解决方案?
P.S. 谢谢您阅读这么长的问题。这是我第一次在这里提问,如果我做错了什么,请告诉我(例如格式、语法、代码约定、标签等)。而且我没有任何编程知识的经验,在了解Java之前就开始接触Android。所以我还没有接受任何适当的课程/培训,这个社区非常棒,经常帮助像我这样的人解决简单的问题,当然还有观看Google I/O视频、阅读博客、阅读其他人的代码。这些都帮助了我很多。所以请容忍任何愚蠢的错误/显而易见的错误/愚蠢的问题。我只有16岁。^_^"