Android前台服务锁屏模式检测:无需Kastri库实现方案咨询
Android锁屏/亮屏检测与Service前台状态控制(无Kastri库依赖)
核心思路
通过动态注册系统广播接收器监听屏幕熄灭(ACTION_SCREEN_OFF)和亮屏(ACTION_SCREEN_ON)事件,在事件回调中触发Service的startForeground()和stopForeground()方法,确保位置传感器在锁屏/亮屏状态下持续运行。
1. 实现屏幕状态广播接收器
创建一个继承自BroadcastReceiver的类,专门处理屏幕状态变化:
class ScreenStateReceiver : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { intent?.action?.let { action -> val serviceIntent = Intent(context, LocationService::class.java) when (action) { Intent.ACTION_SCREEN_OFF -> { // 锁屏时触发前台服务启动 serviceIntent.putExtra("COMMAND", "START_FOREGROUND") context?.startService(serviceIntent) } Intent.ACTION_SCREEN_ON -> { // 亮屏时退出前台状态 serviceIntent.putExtra("COMMAND", "STOP_FOREGROUND") context?.startService(serviceIntent) } } } } }
2. 实现带前台状态控制的Service
在Service中处理前台服务的启动与停止逻辑,同时创建适配Android 8.0+的通知渠道:
class LocationService : Service() { private lateinit var screenReceiver: ScreenStateReceiver private val NOTIFICATION_ID = 1001 private val CHANNEL_ID = "LOCATION_SERVICE_CHANNEL" override fun onCreate() { super.onCreate() // 创建通知渠道(Android O及以上必需) createNotificationChannel() // 动态注册屏幕状态接收器 screenReceiver = ScreenStateReceiver() val filter = IntentFilter().apply { addAction(Intent.ACTION_SCREEN_OFF) addAction(Intent.ACTION_SCREEN_ON) } registerReceiver(screenReceiver, filter) } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { intent?.getStringExtra("COMMAND")?.let { command -> when (command) { "START_FOREGROUND" -> { val notification = createForegroundNotification() startForeground(NOTIFICATION_ID, notification) // 此处添加位置传感器启动逻辑 } "STOP_FOREGROUND" -> { // 参数true:移除通知;false:保留通知但退出前台状态 stopForeground(true) // 位置传感器可继续运行,无需停止 } } } return START_STICKY } private fun createNotificationChannel() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channel = NotificationChannel( CHANNEL_ID, "位置服务", NotificationManager.IMPORTANCE_LOW ).apply { description = "保持位置传感器持续运行" } val notificationManager = getSystemService(NotificationManager::class.java) notificationManager.createNotificationChannel(channel) } } private fun createForegroundNotification(): Notification { val pendingIntent = PendingIntent.getActivity( this, 0, Intent(this, MainActivity::class.java), PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT ) return NotificationCompat.Builder(this, CHANNEL_ID) .setContentTitle("位置服务运行中") .setContentText("屏幕已锁定,服务保持活跃") .setSmallIcon(R.drawable.ic_notification) .setContentIntent(pendingIntent) .build() } override fun onDestroy() { super.onDestroy() // 注销接收器,避免内存泄漏 unregisterReceiver(screenReceiver) } override fun onBind(intent: Intent?): IBinder? = null }
3. 启动Service并适配配置
- 在
AndroidManifest.xml中声明Service:
<service android:name=".LocationService" android:foregroundServiceType="location" /> <!-- Android 12+ 需指定前台服务类型 -->
- 在Activity中启动Service(适配Android 8.0+):
// 启动服务 val serviceIntent = Intent(this, LocationService::class.java) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { startForegroundService(serviceIntent) } else { startService(serviceIntent) }
关键注意事项
- Android 8.0及以上,静态注册广播接收器无法监听屏幕状态事件,必须动态注册(在Service或Activity生命周期内完成注册/注销)。
- 调用
startForeground()必须传入有效通知,否则会抛出异常;通知渠道需提前创建。 - Android 12+需在Service声明中添加
android:foregroundServiceType="location",确保位置权限正常生效。
内容的提问来源于stack exchange,提问作者Valerio
相关产品推荐
相关产品推荐

