在安全的 Android 锁屏中使用 FLAG_SHOW_WHEN_LOCKED 和 disableKeyguard()
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11823259/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using FLAG_SHOW_WHEN_LOCKED with disableKeyguard() in secured Android lock screen
提问by Edmond C
The Context
上下文
Recently, I have been looking for reliable ways to control a secured Android Keyguard. Mainly to display a custom lock screen. I know that Google had stated custom lock screens are not officially supported by the platform and should expect things to break, however, with the existing APIs, I believe there must be ways to do this. I have done tons of research for about a week but still having problem here and there. What I have implemented, assuming a secured Keyguard is enabled, so far are,
最近,我一直在寻找可靠的方法来控制安全的 Android Keyguard。主要是为了显示自定义锁屏。我知道谷歌已经声明平台不正式支持自定义锁屏,应该预料事情会出现问题,但是,对于现有的 API,我相信一定有办法做到这一点。我已经做了大约一个星期的大量研究,但仍然有问题。到目前为止,假设启用了安全的 Keyguard,我已经实现了,
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED allows an activity(a window) to be displayed on screen on, putting the Keyguard behind, and all unsafe actions are prevented. Notification panel is disabled, finishing the activity will bring up the Keyguard. I implemented as following in my lock screen activity.
@Override public void onAttachedToWindow() { window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED); }
KeyguardManager
,KeyguardManager.KeyguardLock
are deprecated classes, but they still work all the way to Jelly Bean. To do this, I have aService
that handles two things, holding a staticKeyguardManager
and the related objects, and have it hold aBroadcastReceiver
to receiveIntent.ACTION_SCREEN_ON
andIntent.ACTION_SCREEN_OFF
. (all the objects are initialized properly)
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED 允许在屏幕上显示一个活动(一个窗口),将 Keyguard 放在后面,并防止所有不安全的操作。通知面板已禁用,完成活动将调出 Keyguard。我在我的锁屏活动中实现如下。
@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
。(所有对象都正确初始化)
For ScreenReceiver
为了 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;
}
}
For BroadcastReceiver
为了 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();
}
}
For LockScreenActivity
, when the user had input the correct passcode,
对于LockScreenActivity
,当用户输入正确的密码时,
window.clearFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
ScreenReceiverService.disableKeyguard();
finish();
The Problem
问题
Things that works
ACTION_ON
andACTION_OFF
are received reliably.- LockScreenActivity is shown before the Keyguard (without telephone state handling yet)
- Notification cannot be pulled down, exiting the activity in any way would display the lockscreen.
Things that does not work
- After I disable
Keyguard
and call finish(), my app exits and homescreen or the last activity before the screen went off is shown. However, whenever I press the Home Key, the Keyguard will flash into the screen, quickly dismissing itself immediately, and the normal Home Key function/event is not handled (will not return to homescreen after flashing). This is observed when I rapidly tapped the Home Key repeatedly.
- After I disable
有用的东西
ACTION_ON
并ACTION_OFF
可靠地接收。- LockScreenActivity 显示在 Keyguard 之前(还没有电话状态处理)
- 通知不能下拉,以任何方式退出活动都会显示锁屏。
行不通的事情
- 在我禁用
Keyguard
并调用完成()后,我的应用程序退出并显示主屏幕或屏幕关闭前的最后一个活动。但是,每当我按下 Home Key 时,Keyguard 都会闪入屏幕,立即快速自行关闭,并且不会处理正常的 Home Key 功能/事件(闪后不会返回主屏幕)。当我反复快速点击 Home 键时会观察到这一点。
- 在我禁用
I even looked into the Android source code to find out the Home Key handling, but it is never sent to third-party applications unless the window type is WindowManager.LayoutParams.TYPE_KEYGUARD
or WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG
, which will throw SecurityException on 4.0+ even it worked on earlier platforms. And for the Keyguard
, I have declared DISABLE_KEYGUARD
permission use this shouldn't be the problem. My guess is the flag FLAG_SHOW_WHEN_LOCKED
will tell the system to handle to Keyguard
in some ways that would conflict with other disable calls. Since this flag is mostly used for Alarm/SMS type application, which is to show limited information to the user, then dismiss themselves and bring up the Keyguard
. But in my case, having the user unlock my lock screen then unlock the system lockscreen simply defeats the purpose of my app.
我什至查看了 Android 源代码以找出 Home Key 处理,但它永远不会发送到第三方应用程序,除非窗口类型是WindowManager.LayoutParams.TYPE_KEYGUARD
or WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG
,即使它在早期平台上工作,也会在 4.0+ 上抛出 SecurityException。对于Keyguard
,我已经声明DISABLE_KEYGUARD
许可使用这不应该是问题。我的猜测是该标志FLAG_SHOW_WHEN_LOCKED
会告诉系统以Keyguard
与其他禁用调用冲突的某些方式进行处理。由于此标志主要用于警报/短信类型的应用程序,即向用户显示有限的信息,然后自行关闭并显示Keyguard
. 但就我而言,让用户解锁我的锁屏然后解锁系统锁屏只会违背我的应用程序的目的。
So the question is why would the Keyguard
flashes whenever I press Home after I disabled it? Is there any workaround/solution for this issue?
所以问题是为什么Keyguard
在我禁用它后每次按 Home都会闪烁?是否有针对此问题的解决方法/解决方案?
P.S. Thank you for reading such a long question. This is my first time asking a question here, if there is anything that I did wrong, please tell me (i.e. format, grammar, code convention, tags, etc.). Also I had no experience with any programming knowledge, I started with Android before I know what Java is. So I have not taken any proper course/training yet, this community is awesome and often help people like I even if they are simple questions, and of course watching Google I/O videos, reading blogs, read others' code help me a lot. So please tolerate any dumb mistakes/obvious bugs/stupid questions. I am only 16. ^_^"
PS 感谢您阅读这么长的问题。这是我第一次在这里提问,如果我做错了什么,请告诉我(即格式、语法、代码约定、标签等)。此外,我没有任何编程知识的经验,在我知道 Java 是什么之前我就开始使用 Android。所以我还没有参加任何适当的课程/培训,这个社区很棒,经常帮助像我这样的人,即使他们是简单的问题,当然看谷歌 I/O 视频,阅读博客,阅读别人的代码对我有很大帮助. 所以请容忍任何愚蠢的错误/明显的错误/愚蠢的问题。我才16岁。^_^”
回答by droideckar
I have used this with some success in both Gingerbread and ICS to open my activity (via a background service which is starting it). In the activity being started:
我已经在 Gingerbread 和 ICS 中成功使用它来打开我的活动(通过启动它的后台服务)。在开始的活动中:
@Override
public void onAttachedToWindow() {
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN |
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON,
WindowManager.LayoutParams.FLAG_FULLSCREEN |
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
}
回答by Aditya Nikhade
I had the same problem for the click of HOME button while unlocking the device. This can be solved by reseting the password to blank (ie "") :
我在解锁设备时单击 HOME 按钮也遇到了同样的问题。这可以通过将密码重置为空白(即“”)来解决:
DevicePolicyManager devicePolicyManager;
ComponentName demoDeviceAdmin;
devicePolicyManager.setPasswordQuality(demoDeviceAdmin,DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
devicePolicyManager.setPasswordMinimumLength(demoDeviceAdmin, 0);
devicePolicyManager.resetPassword("",DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY);
and then disabling the keygaurd :
然后禁用键盘锁:
this.keyGuardLock = ((KeyguardManager)getSystemService("keyguard")).newKeyguardLock("keyguard");
keyGuardLock.disableKeyguard();
Hope this solved your problem. \m/ keep coding!
希望这解决了您的问题。\m/ 继续编码!
回答by mask
If AOSP is in your control then you need to set the simple flag and keyguard() is gone for good. Here is the details to do that, get into the file "overlay/frameworks/base/packages/SystemUI/res/values/config.xml" and search for "config_enableKeyguardService" then set the flag to false.
如果 AOSP 在您的控制之下,那么您需要设置简单的标志并且 keyguard() 已经一去不复返了。这是执行此操作的详细信息,进入文件“overlay/frameworks/base/packages/SystemUI/res/values/config.xml”并搜索“config_enableKeyguardService”,然后将标志设置为 false。
NO MORE keyGuard, pheww
没有更多的keyGuard,呸
回答by elgui
In your LockScreenActivity, ending the validation code by finish();
kills the LockscreenActivity and thus the whole app. Instead of that, you could just launch back your main activity (or any other) like this :
在您的 LockScreenActivity 中,通过finish();
杀死 LockscreenActivity 从而终止整个应用程序来结束验证代码。取而代之的是,您可以像这样启动您的主要活动(或任何其他活动):
startActivity(new Intent(LockScreenActivity.this, MainActivity.class));
回答by Supreethks
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED allows an activity(a window) to be displayed on screen on, putting the Keyguard behind
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED 允许活动(一个窗口)显示在屏幕上,将 Keyguard 放在后面
I tried to get this but my activity always preceded by the system lock screen. isOrderdBroadcast() says that ACTION_SCREEN_NO is an ordered broadcast.
我试图得到这个,但我的活动总是在系统锁定屏幕之前。isOrderdBroadcast() 表示 ACTION_SCREEN_NO 是有序广播。
I added flag to the activity :
我在活动中添加了标志:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
in onAttachedView(). But still the system lock is getting the preference over my Custom screen lock activity.
在 onAttachedView() 中。但是系统锁定仍然优先于我的自定义屏幕锁定活动。
How did you get your activity before the system lock screen?
你是如何在系统锁屏之前获得你的活动的?
EDITOn a hindsight, I think my understanding of the lock screen concept was wrong. My broadcast receiver was getting the broadcast first. But what was showing before that was the system lock screen launched when SCREEN_OFF is received. Fixed that problem as of now.
编辑事后看来,我认为我对锁屏概念的理解是错误的。我的广播接收器首先接收广播。但在此之前显示的是收到 SCREEN_OFF 时启动的系统锁定屏幕。到此为止已经解决了这个问题。
But stumped by the ambiguity of home button behavior. This won't be a problem in post ICS devices as all hard buttons are discouraged.
但被主页按钮行为的模棱两可所难倒。这在后 ICS 设备中不会成为问题,因为不鼓励使用所有硬按钮。