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

Android监听手机解锁事件问题:静态广播接收器未触发

解决Android解锁手机时触发指定操作的问题

Hey there, let's work through this issue you're having with triggering actions when a user unlocks their Android device. I've looked at your two attempted solutions and I can see exactly why they're not working—Android's background restrictions in newer versions are the culprit. Let's break this down step by step, fix the existing issues, and get a working solution that works across all modern Android versions.

Why Your Current Attempts Aren't Working

1. Static Broadcast Receiver for USER_PRESENT

Starting with Android 8.0 (API 26), Google restricted most implicit broadcasts from being statically registered in the manifest—android.intent.action.USER_PRESENT falls right into this category. That's why your ScreenReceiver's onReceive method never gets called; the system simply ignores static registrations for this broadcast on newer OS versions.

2. Dynamic Registration in a Background Service

Your second approach using a background service works on older Android versions, but Android 8.0 introduced strict background execution limits. Once your app moves to the background (no visible activities), the system will quickly shut down your NoteService to save resources. When the service dies, the dynamically registered receiver goes with it, so it can't listen for unlock events anymore.

Working Solutions for All Android Versions

Option 1: Foreground Service + Dynamic Broadcast Registration

A foreground service stays alive because it shows a persistent notification (required on Android 8.0+), making it perfect for long-term event listening. Here's how to implement it:

  1. Update your NoteService to run as a foreground service and register the receiver dynamically:
class NoteService : Service() {
    private lateinit var screenReceiver: ScreenReceiver

    override fun onCreate() {
        super.onCreate()
        // Register the USER_PRESENT receiver dynamically
        screenReceiver = ScreenReceiver()
        val intentFilter = IntentFilter(Intent.ACTION_USER_PRESENT)
        registerReceiver(screenReceiver, intentFilter)

        // Set up foreground service (required for Android 8.0+)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            // Create a notification channel first
            val channel = NotificationChannel(
                "unlock_listener_channel",
                "Unlock Listener Service",
                NotificationManager.IMPORTANCE_LOW
            )
            val notificationManager = getSystemService(NotificationManager::class.java)
            notificationManager.createNotificationChannel(channel)
        }

        // Build the foreground notification
        val notification = NotificationCompat.Builder(this, "unlock_listener_channel")
            .setSmallIcon(R.drawable.ic_app_icon)
            .setContentTitle("Listening for unlock events")
            .setContentText("Service running in background")
            .setPriority(NotificationCompat.PRIORITY_LOW)
            .build()

        // Start the service in foreground mode
        startForeground(1001, notification)
    }

    override fun onDestroy() {
        super.onDestroy()
        // Always unregister the receiver to avoid memory leaks
        unregisterReceiver(screenReceiver)
    }

    override fun onBind(intent: Intent): IBinder? {
        return null // We don't need binding for this service
    }
}
  1. Add required permissions and service declaration to AndroidManifest.xml:
<!-- Foreground service permission (Android 8.0+) -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<!-- Notification permission (Android 13+) -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

<service
    android:name=".service.NoteService"
    android:foregroundServiceType="dataSync" /> <!-- Pick a type that matches your use case -->
  1. Update your MyApplication to start the service correctly for all Android versions:
class MyApplication : MultiDexApplication() {
    companion object {
        lateinit var instance: MyApplication
    }

    override fun onCreate() {
        super.onCreate()
        instance = this
        MultiDex.install(applicationContext)
        
        val serviceIntent = Intent(this, NoteService::class.java)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            // Use startForegroundService for Android 8.0+
            startForegroundService(serviceIntent)
        } else {
            // Legacy startService for older versions
            startService(serviceIntent)
        }
    }
}

Option 2: Activity-Based Dynamic Registration (For Non-Persistent Listening)

If you don't need to listen for unlock events when your app is completely closed, you can register the receiver only when your app is in the foreground (e.g., when an activity is visible):

  1. Fix your ScreenReceiver to actually call the clear note method:
class ScreenReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        if (Intent.ACTION_USER_PRESENT == intent.action) {
            // Call your clear note method here
            checkClearSavedNote(context)
        }
    }

    private fun checkClearSavedNote(context: Context) {
        AppPref.getInstance(context).putString(AppPref.KEY_ID_CURRENT_NOTE, "")
        Log.e("Quang", "clear note")
    }
}
  1. Register/unregister the receiver in your main activity's lifecycle methods:
class MainActivity : AppCompatActivity() {
    private lateinit var screenReceiver: ScreenReceiver

    override fun onResume() {
        super.onResume()
        // Register receiver when activity is visible
        screenReceiver = ScreenReceiver()
        val intentFilter = IntentFilter(Intent.ACTION_USER_PRESENT)
        registerReceiver(screenReceiver, intentFilter)
    }

    override fun onPause() {
        super.onPause()
        // Unregister when activity is hidden to avoid leaks
        unregisterReceiver(screenReceiver)
    }
}

This way, the receiver only exists while your app is in the foreground, avoiding background restrictions entirely.

Quick Fix for Your Original Receiver

Don't forget—your original ScreenReceiver had a bug: the checkClearSavedNote method was private and never called from onReceive. I fixed that in the code above, but make sure you always hook up your business logic to the broadcast trigger!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:53:07