Android,如何在锁屏界面上启动Activity

18

我想在锁屏推送通知上启动我的活动而不改变锁屏。

那个活动需要特殊权限吗?


你有没有任何可以像你所说的那样工作的示例应用程序? - Ravi Vaghela
Hangouts可以做到这一点。 - trampster
微信在接到电话时也会这样做,即使手机处于睡眠和锁定状态,应用程序也会显示出来。 - BabyishTank
5个回答

33
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1)
    {
        setShowWhenLocked(true);
        setTurnScreenOn(true);
        KeyguardManager keyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
        if(keyguardManager!=null)
            keyguardManager.requestDismissKeyguard(this, null);
    }
    else 
    {
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
                WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
                WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
    }

1
实际上,这段代码看起来是最好的、版本兼容的解决方案。应该被接受为答案。 - Grisgram
1
这段代码应该放在哪里?我把它放在了onCreate方法中,但是当我关闭屏幕时,onCreate方法就不会被调用,所以这段代码也就无法运行。 - trampster
1
为什么我们需要 keyguardManager.requestDismissKeyguard(this, null);?它实际上会导致内存泄漏。 - beginner
@初学者 Keyguard 处理解锁手机并提示您输入 PIN 码或图案,无论您采用哪种安全措施。当您在锁定屏幕上显示信息时,这是您的选择。关于方法本身,在 android.com 上有一个描述:https://developer.android.com/reference/android/app/KeyguardManager#requestDismissKeyguard(android.app.Activity,%20android.app.KeyguardManager.KeyguardDismissCallback) - Vladimir Demirev
@VladimirDemirev 你能否确认在这种情况下这是否适用于Android 8:应用程序已打开,然后手机被锁定,接着它是否会唤醒并显示在锁屏屏幕顶部?对我而言,在我打开应用程序时,它不会在推送消息时唤醒。在Android 10中,此代码将有效。 - Waleed
显示剩余2条评论

9
在API级别17及以上,这将起作用。
<activity
    android:name=".yourActivityName"
    android:showOnLockScreen="true"
    android:screenOrientation="sensorPortrait" >

或者在调用setContentView()之前,在onCreate()方法中编写以下代码:

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

点击通知时,锁屏对话框显示不出来。在我的手机上无法工作。 - Rabindra Acharya
@Ravi,你能否确认在这种情况下它是否适用于Android 8:应用程序已打开,然后手机被锁定,那么它会唤醒以显示在锁屏的顶部吗?对我来说,在我打开应用程序时,它不会在推送时唤醒。在Android 10中,此代码将起作用。 - Waleed
android:showOnLockScreen已被弃用。 - Michał Dobi Dobrzański

4

其他答案可能包含您可能需要或不需要的额外功能。

允许您的活动在锁定屏幕上显示的最少代码是:

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if (Build.VERSION.SDK_INT >= 27)
        setShowWhenLocked(true);
    else
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);

    // setContentView etc
}

如果您希望您的活动可以打开屏幕(因为它可能会关闭)或解锁键盘,那么请参阅Vladimir Demirev的回答


1
请问您能否确认在以下情况下,此程序是否适用于Android 8:应用程序已打开,然后手机被锁定,接着它是否会唤醒以显示在锁屏界面的顶部? - Waleed
如果您使用常量(如27)而不是硬编码的值来表示构建号,您的代码将更易读。 - Peter Chaula

3
在onCreate(Bundle savedInstanceState)方法中,您应该添加一些窗口标志:
Window window = this.getWindow();
window.addFlags(LayoutParams.FLAG_DISMISS_KEYGUARD);
window.addFlags(LayoutParams.FLAG_SHOW_WHEN_LOCKED);
window.addFlags(LayoutParams.FLAG_TURN_SCREEN_ON);

1

显示锁定屏幕上的活动:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
        
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
        setShowWhenLocked(true)
        setTurnScreenOn(true)
    } else {
        window.addFlags(
            WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
            or WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
        )
    }

    setContentView(binding.root)
    ...
}

请注意,小米手机需要从制造商那里获得额外的权限。 您可以在此处了解有关此问题的更多信息: https://dev59.com/I67la4cB1Zd3GeqPhK1n#52590297 另外,如果您想请求解锁屏幕保护并在解锁后执行操作:
private fun handleButtonClickWhenLocked(clickAction: () -> Unit) {
    val keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
    if (!keyguardManager.isKeyguardLocked) {
        clickAction.invoke()
    } else {
        val keyguardDismissCallback = object : KeyguardManager.KeyguardDismissCallback() {

             override fun onDismissSucceeded() {
                 clickAction.invoke()
             }
         }
         keyguardManager.requestDismissKeyguard(this, keyguardDismissCallback)
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接