You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Android 11开发闲置N秒后自动重现的锁屏应用?

Android 11(API 30)闲置锁屏原型实现方案

一、启动关系:前台服务作为核心主控

Android 11对后台组件限制严格,前台服务是唯一能稳定持续运行闲置检测的载体,具体启动逻辑如下:

  • 避免在Application.onCreate()中直接启动Activity:进程被杀后Application不会自动重启,无法保证检测逻辑持续运行。
  • 避免Activity绑定服务:Activity销毁后绑定关系解除,服务若为绑定模式会被系统回收,无法持续检测闲置状态。

推荐流程

  1. 应用首次启动时,直接启动前台服务(如IdleDetectionService),服务启动后立即检查当前用户状态:若处于未锁定状态,直接启动MainActivity(登录页)。
  2. MainActivity完成PIN输入后,通过Intent或Messenger通知前台服务重置闲置计时器,随后自行finish()。
  3. 前台服务独立于Activity生命周期,持续运行闲置检测逻辑,计时器到期后触发MainActivity的显示。

二、激活方式:绕过Android 11后台启动限制

Android 11禁止普通后台组件直接启动Activity,需通过以下合法方式实现强制显示:

1. 利用AlarmManager + PendingIntent(推荐)

系统允许通过AlarmManager触发的PendingIntent启动Activity,这属于合法后台启动场景:

// 前台服务中触发闲置逻辑的代码
fun triggerLockScreen() {
    val intent = Intent(this, MainActivity::class.java).apply {
        flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
    }
    val pendingIntent = PendingIntent.getActivity(
        this,
        0,
        intent,
        PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
    )
    val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
    alarmManager.setExactAndAllowWhileIdle(
        AlarmManager.RTC_WAKEUP,
        System.currentTimeMillis(),
        pendingIntent
    )
}

2. 复用已存在的任务栈(若MainActivity未被销毁)

如果MainActivity只是被退到后台,可直接将其任务栈移到前台:

fun bringLockScreenToFront() {
    val am = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
    am.getRunningTasks(Int.MAX_VALUE).forEach { taskInfo ->
        if (taskInfo.baseActivity?.packageName == packageName) {
            am.moveTaskToFront(taskInfo.id, 0)
            return
        }
    }
}

3. MainActivity的关键配置(必须)

在AndroidManifest.xml中配置属性,确保全屏覆盖且不受系统限制:

<activity
    android:name=".MainActivity"
    android:launchMode="singleInstance"
    android:excludeFromRecents="true"
    android:taskAffinity=""
    android:showOnLockScreen="true"
    android:showWhenLocked="true"
    android:turnScreenOn="true"
    android:windowSoftInputMode="stateHidden"
    android:theme="@style/Theme.App.LockScreen">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

对应的全屏主题样式:

<style name="Theme.App.LockScreen" parent="Theme.MaterialComponents.DayNight.NoActionBar">
    <item name="android:windowFullscreen">true</item>
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:windowIsTranslucent">false</item>
    <item name="android:windowBackground">@color/black</item>
</style>

4. 可靠的闲置检测实现

使用官方推荐的UsageStatsManager检测用户闲置,比监听触摸事件更稳定:

// 前台服务中检测闲置的方法
private fun isUserIdle(idleSeconds: Long): Boolean {
    val usageStatsManager = getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager
    val endTime = System.currentTimeMillis()
    val startTime = endTime - idleSeconds * 1000
    val usageStatsList = usageStatsManager.queryUsageStats(
        UsageStatsManager.INTERVAL_DAILY,
        startTime,
        endTime
    )
    if (usageStatsList.isEmpty()) return true
    val lastActiveTime = usageStatsList.maxByOrNull { it.lastTimeUsed }?.lastTimeUsed ?: 0
    return endTime - lastActiveTime >= idleSeconds * 1000
}

需在AndroidManifest.xml添加权限,并引导用户手动开启「使用情况访问权限」:

<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"
    tools:ignore="ProtectedPermissions" />

三、完整流程梳理

  1. 应用启动后立即启动前台服务(显示持续通知,避免被系统回收)。
  2. 服务启动后检查用户状态:若闲置则启动MainActivity,否则开始循环检测闲置。
  3. 用户在MainActivity输入PIN后,通知服务重置计时器并自行销毁。
  4. 服务检测到用户闲置N秒后,通过AlarmManager触发MainActivity显示。
  5. MainActivity全屏覆盖所有界面,等待用户输入PIN。

内容的提问来源于stack exchange,提问作者NKAT

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 15:52:49