25

上下文

最近,我一直在寻找可靠的方法来控制安全的 Android Keyguard。主要是为了显示一个自定义的锁屏。我知道 Google 曾表示该平台不正式支持自定义锁屏,并且应该预料到事情会中断,但是,对于现有的 API,我相信必须有办法做到这一点。我已经做了大约一周的大量研究,但仍然到处都有问题。到目前为止,假设启用了安全的 Keyguard,我已经实施的是,

  • 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处理两件事的 a ,持有一个静态KeyguardManager对象和相关对象,并让它持有一个BroadcastReceiver接收Intent.ACTION_SCREEN_ONIntent.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_ONACTION_OFF可靠地收到。
    • LockScreenActivity 显示在 Keyguard 之前(尚未处理电话状态)
    • 通知不能被下拉,以任何方式退出活动都会显示锁屏。
  • 不起作用的东西

    • 在我禁用Keyguard并调用完成()后,我的应用程序退出并显示主屏幕或屏幕关闭前的最后一个活动。但是,每当我按下 Home 键时,Keyguard 都会闪烁到屏幕中,并立即快速自行关闭,并且不处理正常的 Home 键功能/事件(闪烁后不会返回主屏幕)。当我反复快速点击 Home 键时会观察到这种情况。

我什至查看了 Android 源代码以找出 Home Key 处理,但它永远不会发送到第三方应用程序,除非窗口类型是WindowManager.LayoutParams.TYPE_KEYGUARDor WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG,这将在 4.0+ 上抛出 SecurityException ,即使它在早期平台上工作。对于Keyguard,我已经声明DISABLE_KEYGUARD允许使用这不应该是问题。我的猜测是该标志FLAG_SHOW_WHEN_LOCKED会告诉系统以Keyguard某些与其他禁用调用冲突的方式进行处理。由于此标志主要用于警报/短信类型的应用程序,即向用户显示有限的信息,然后关闭自己并调出Keyguard. 但在我的情况下,让用户解锁我的锁屏然后解锁系统锁屏只会破坏我的应用程序的目的。

所以问题是为什么Keyguard在我禁用它后每当我按 Home 时都会闪烁?此问题是否有任何解决方法/解决方案?

PS 感谢您阅读这么长的问题。这是我第一次在这里提问,如果我做错了什么,请告诉我(即格式,语法,代码约定,标签等)。我也没有任何编程知识的经验,在我知道 Java 是什么之前,我就开始使用 Android。所以我还没有参加任何适当的课程/培训,这个社区很棒并且经常帮助像我这样的人,即使他们是简单的问题,当然观看谷歌 I/O 视频、阅读博客、阅读其他人的代码对我有很大帮助. 所以请容忍任何愚蠢的错误/明显的错误/愚蠢的问题。我才16岁。^_^"

4

5 回答 5

15

我在 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);
}
于 2013-03-12T17:05:42.480 回答
1

我在解锁设备时单击 HOME 按钮时遇到了同样的问题。这可以通过将密码重置为空白(即“”)来解决:

DevicePolicyManager devicePolicyManager;
ComponentName demoDeviceAdmin;


devicePolicyManager.setPasswordQuality(demoDeviceAdmin,DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
devicePolicyManager.setPasswordMinimumLength(demoDeviceAdmin, 0);

devicePolicyManager.resetPassword("",DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY);

然后禁用keygaurd:

this.keyGuardLock = ((KeyguardManager)getSystemService("keyguard")).newKeyguardLock("keyguard");
keyGuardLock.disableKeyguard();

希望这解决了你的问题。\m/ 继续编码!

于 2013-07-17T10:19:35.740 回答
0

finish();在您的 LockScreenActivity 中,通过杀死 LockscreenActivity 以及整个应用程序来结束验证代码。取而代之的是,您可以像这样重新启动您的主要活动(或任何其他活动):

startActivity(new Intent(LockScreenActivity.this, MainActivity.class));
于 2013-03-28T16:24:38.787 回答
0

WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED 允许在屏幕上显示活动(窗口),将 Keyguard 放在后面

我试图得到这个,但我的活动总是在系统锁定屏幕之前。isOrderdBroadcast() 表示 ACTION_SCREEN_NO 是有序广播。

我在活动中添加了标志:

getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);

在 onAttachedView() 中。但是系统锁定仍然优先于我的自定义屏幕锁定活动。

您是如何在系统锁定屏幕之前获得活动的?

编辑 事后看来,我认为我对锁屏概念的理解是错误的。我的广播接收器首先收到广播。但之前显示的是收到 SCREEN_OFF 时启动的系统锁定屏幕。截至目前已修复该问题。

但被主页按钮行为的模棱两可难住了。这在后 ICS 设备中不会成为问题,因为不鼓励使用所有硬按钮。

于 2012-08-31T05:22:59.543 回答
0

如果 AOSP 在您的控制范围内,那么您需要设置简单标志,并且 keyguard() 将永远消失。这是执行此操作的详细信息,进入文件“overlay/frameworks/base/packages/SystemUI/res/values/config.xml”并搜索“config_enableKeyguardService”,然后将标志设置为false。

没有更多的 keyGuard,唷

于 2016-06-24T21:46:37.787 回答