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

如何在BroadcastReceiver中唤醒设备?API兼容问题求助

解决BroadcastReceiver中无法唤醒设备的问题

错误根源

你遇到的java.lang.IllegalArgumentException: Must specify a valid wake lock level.是因为**WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON根本不是PowerManager WakeLock的合法级别**。这个Flag是用来给Activity或View设置"保持屏幕常亮"的,完全不能传递给PowerManager.newWakeLock()方法。

同时PowerManager.SCREEN_BRIGHT_WAKE_LOCK确实已被废弃,我们需要根据Android版本选择正确的唤醒方案:

正确实现方案

1. Android 12(API 31)及以上版本

从API 31开始,Google推荐使用更简洁的PowerManager.wakeUp()方法直接唤醒设备,无需创建WakeLock:

private fun wakeDevice(context: Context) {
    val powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager
    // 先判断设备是否处于非交互状态(屏幕熄灭/锁屏)
    if (!powerManager.isInteractive) {
        // 唤醒设备,参数传当前时间戳即可,第二个参数是唤醒原因的标签
        powerManager.wakeUp(System.currentTimeMillis(), "MyApp:NotificationWakeup")
    }
}

2. Android 11(API 30)及以下版本

对于旧版本,我们可以使用未完全废弃的WakeLock级别,配合ACQUIRE_CAUSES_WAKEUP标志强制唤醒设备:

private fun wakeDevice(context: Context) {
    val powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager
    // 用SCREEN_DIM_WAKE_LOCK(未废弃)加上ACQUIRE_CAUSES_WAKEUP标志,实现主动唤醒
    val wakeLockLevel = PowerManager.SCREEN_DIM_WAKE_LOCK or PowerManager.ACQUIRE_CAUSES_WAKEUP
    val myWakeLock = powerManager.newWakeLock(wakeLockLevel, "MyApp:NotificationWakelockTag")
    
    // 持有WakeLock 5秒,确保用户能看到通知
    myWakeLock.acquire(5 * 1000L)
    // 注意:带超时参数的acquire()会自动释放WakeLock,这里不用手动调用release()
}

3. 兼容所有版本的整合写法

通过版本判断把两种方案结合起来:

private fun wakeDevice(context: Context) {
    val powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        if (!powerManager.isInteractive) {
            powerManager.wakeUp(System.currentTimeMillis(), "MyApp:NotificationWakeup")
        }
    } else {
        val wakeLockLevel = PowerManager.SCREEN_DIM_WAKE_LOCK or PowerManager.ACQUIRE_CAUSES_WAKEUP
        val myWakeLock = powerManager.newWakeLock(wakeLockLevel, "MyApp:NotificationWakelockTag")
        myWakeLock.acquire(5 * 1000L)
    }
}

关键注意事项

  • 权限确认:确保Manifest中已添加WAKE_LOCK权限:
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    
    若你的应用需要在Android 13及以上显示通知,还需添加:
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
    
  • WakeLock释放逻辑:使用acquire(long timeout)时,系统会自动在超时后释放锁,不要提前调用release(),否则设备会立刻熄灭。
  • 唤醒标志的必要性:ACQUIRE_CAUSES_WAKEUP是主动唤醒熄灭设备的核心,没有这个标志,WakeLock只会保持屏幕常亮,无法唤醒已熄灭的设备。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:05:44