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

Android Studio自定义锁屏APP无法每次唤醒设备时显示的问题求助

解决自定义锁屏APP无法每次唤醒设备时自动显示的问题

核心问题分析

你当前的代码仅在APP已启动的情况下能响应唤醒,但没有监听系统的锁屏/唤醒事件,也没有持久化的后台逻辑触发锁屏Activity启动。要实现每次唤醒都显示,需要后台监听系统屏幕事件+前台保活服务,同时适配Android新版本的权限和API限制。


步骤1:补充Manifest权限

在AndroidManifest.xml中添加必要权限及组件注册:

<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />

<!-- 注册前台服务 -->
<service
    android:name=".ScreenLockService"
    android:foregroundServiceType="specialUse" /> <!-- Android 12+必填 -->

<!-- 注册开机自启接收器 -->
<receiver
    android:name=".BootReceiver"
    android:enabled="true"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>

步骤2:创建前台保活服务(监听屏幕事件)

创建ScreenLockService.kt,用前台服务保活并动态注册屏幕事件接收器:

import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.Service
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Build
import android.os.IBinder
import androidx.core.app.NotificationCompat

class ScreenLockService : Service() {

    private val screenEventReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            intent?.let {
                // 屏幕点亮或用户解锁时启动锁屏Activity
                if (it.action == Intent.ACTION_SCREEN_ON || it.action == Intent.ACTION_USER_PRESENT) {
                    val lockIntent = Intent(context, MainActivity::class.java).apply {
                        addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP)
                    }
                    context?.startActivity(lockIntent)
                }
            }
        }
    }

    override fun onCreate() {
        super.onCreate()
        // 动态注册屏幕事件接收器(Android 8.0+静态注册失效)
        val intentFilter = IntentFilter().apply {
            addAction(Intent.ACTION_SCREEN_ON)
            addAction(Intent.ACTION_USER_PRESENT)
        }
        registerReceiver(screenEventReceiver, intentFilter)

        // 启动前台服务,避免被系统杀死
        createNotificationChannel()
        val notification = NotificationCompat.Builder(this, "LOCK_SCREEN_CHANNEL")
            .setContentTitle("自定义锁屏服务")
            .setContentText("服务运行中")
            .setSmallIcon(R.drawable.ic_notification) // 替换为你的通知图标
            .build()
        startForeground(1, notification)
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        return START_STICKY // 服务被杀死后自动重启
    }

    override fun onDestroy() {
        super.onDestroy()
        unregisterReceiver(screenEventReceiver)
    }

    override fun onBind(intent: Intent?): IBinder? = null

    private fun createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel = NotificationChannel(
                "LOCK_SCREEN_CHANNEL",
                "锁屏服务通知",
                NotificationManager.IMPORTANCE_LOW
            )
            getSystemService(NotificationManager::class.java).createNotificationChannel(channel)
        }
    }
}

步骤3:更新MainActivity适配新API

替换旧的WindowManager flags,适配Android 10+的锁屏显示规则,并添加权限请求逻辑:

import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.provider.Settings
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // 适配Android 10+的锁屏显示API
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
            setShowWhenLocked(true)
            setTurnScreenOn(true)
        } else {
            window.addFlags(
                android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON or
                        android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD or
                        android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
                        android.view.WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
            )
        }

        // 启动前台服务(首次打开APP时触发)
        startLockService()

        // 请求必要权限(悬浮窗+电池优化忽略)
        requestRequiredPermissions()
    }

    override fun onBackPressed() {
        // 禁用返回键,防止用户回到系统锁屏(按需调整)
        // super.onBackPressed()
    }

    private fun startLockService() {
        val serviceIntent = Intent(this, ScreenLockService::class.java)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            startForegroundService(serviceIntent)
        } else {
            startService(serviceIntent)
        }
    }

    private fun requestRequiredPermissions() {
        // 请求悬浮窗权限
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(this)) {
            val overlayIntent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION).apply {
                data = android.net.Uri.parse("package:$packageName")
            }
            startActivity(overlayIntent)
        }

        // 请求忽略电池优化
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            val batteryIntent = Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS).apply {
                data = android.net.Uri.parse("package:$packageName")
            }
            startActivity(batteryIntent)
        }
    }
}

步骤4:添加开机自启接收器

创建BootReceiver.kt,实现设备开机后自动启动服务:

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.os.Build

class BootReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        if (intent?.action == Intent.ACTION_BOOT_COMPLETED) {
            val serviceIntent = Intent(context, ScreenLockService::class.java)
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                context?.startForegroundService(serviceIntent)
            } else {
                context?.startService(serviceIntent)
            }
        }
    }
}

关键注意事项

  1. 权限授予:必须手动授予悬浮窗权限和电池优化忽略权限,否则服务会被系统限制。
  2. 前台服务通知:Android 8.0+要求前台服务必须显示通知,不能隐藏。
  3. API适配:旧的TYPE_SYSTEM_ERROR等WindowManager类型已被弃用,改用Android 10+提供的setShowWhenLocked和setTurnScreenOn方法。
  4. 系统杀进程:即使使用前台服务,部分厂商的定制ROM仍可能杀死服务,需要引导用户将APP加入白名单。

内容的提问来源于stack exchange,提问作者R.T.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 00:11:09