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) } } } }
关键注意事项
- 权限授予:必须手动授予悬浮窗权限和电池优化忽略权限,否则服务会被系统限制。
- 前台服务通知:Android 8.0+要求前台服务必须显示通知,不能隐藏。
- API适配:旧的
TYPE_SYSTEM_ERROR等WindowManager类型已被弃用,改用Android 10+提供的setShowWhenLocked和setTurnScreenOn方法。 - 系统杀进程:即使使用前台服务,部分厂商的定制ROM仍可能杀死服务,需要引导用户将APP加入白名单。
内容的提问来源于stack exchange,提问作者R.T.
相关产品推荐
相关产品推荐

