已弃用SCREEN_DIM_WAKE_LOCK的替代方案:通知唤醒屏幕问题
解决通知到达时唤醒屏幕的替代方案
首先明确:你没法直接修改系统通知悬浮窗的WindowManager参数,因为系统通知的Window由SystemUI负责管理,第三方应用没有权限操作它。官方推荐的WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON是用于控制自己应用内的窗口/Activity的屏幕常亮,不适用于系统通知场景。
下面提供两种可行的替代实现方式:
方案一:使用兼容的WakeLock类型(快速适配)
虽然SCREEN_DIM_WAKE_LOCK被弃用,但你可以使用其他未被弃用的WakeLock组合来实现相同效果,同时保证版本兼容性。需要先在AndroidManifest中声明WAKE_LOCK权限:
<uses-permission android:name="android.permission.WAKE_LOCK" />
修改后的代码示例:
override fun onMessageReceived(remoteMessage: RemoteMessage) { val pm = getSystemService(POWER_SERVICE) as PowerManager val isScreenOn = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) { pm.isInteractive } else { @Suppress("DEPRECATION") pm.isScreenOn } if (!isScreenOn) { // 用SCREEN_BRIGHT_WAKE_LOCK替代弃用的SCREEN_DIM_WAKE_LOCK val wakeLock = pm.newWakeLock( PowerManager.SCREEN_BRIGHT_WAKE_LOCK or PowerManager.ACQUIRE_CAUSES_WAKEUP or PowerManager.ON_AFTER_RELEASE, "irfAuroraAlert:newNotificationWakeLock" ) wakeLock.acquire(3000) // 自动3秒后释放锁 } // 原有通知发送逻辑保持不变 remoteMessage.data.let { it["new_alert"]?.let { body -> sendNotification(body) } } remoteMessage.notification?.let { it.body?.let { body -> sendNotification(body) } } }
SCREEN_BRIGHT_WAKE_LOCK:保持屏幕高亮唤醒(若需低亮度,SCREEN_DIM_WAKE_LOCK虽已弃用但仍能在旧版本正常工作,不过优先推荐未弃用的类型)ACQUIRE_CAUSES_WAKEUP:强制唤醒休眠状态的设备ON_AFTER_RELEASE:释放锁后保持屏幕亮一段时间,优化用户体验
方案二:使用Notification的FullScreenIntent(合规推荐)
对于Android 10及以上版本,后台唤醒限制更严格,推荐使用通知的setFullScreenIntent方法,通过启动透明Activity实现屏幕唤醒,这种方式更符合系统规范,无需依赖弃用的WakeLock API。
步骤1:创建透明唤醒Activity
在AndroidManifest中声明透明Activity并配置主题:
<activity android:name=".WakeScreenActivity" android:theme="@style/TransparentActivityTheme" android:excludeFromRecents="true" android:launchMode="singleInstance" android:taskAffinity="" />
对应的透明主题:
<style name="TransparentActivityTheme" parent="Theme.AppCompat.Light.NoActionBar"> <item name="android:windowBackground">@android:color/transparent</item> <item name="android:windowIsTranslucent">true</item> <item name="android:windowAnimationStyle">@android:style/Animation.Translucent</item> <item name="android:windowDisablePreview">true</item> </style>
Activity实现代码:
class WakeScreenActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 设置屏幕常亮和锁屏显示标志 window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON or WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED) // 延迟1秒后自动关闭Activity,用户无感知 Handler(Looper.getMainLooper()).postDelayed({ finish() }, 1000) } }
步骤2:修改通知发送逻辑
在sendNotification方法中为通知设置FullScreenIntent:
private fun sendNotification(body: String) { val wakeIntent = Intent(this, WakeScreenActivity::class.java) val pendingWakeIntent = PendingIntent.getActivity( this, 0, wakeIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) val notificationBuilder = NotificationCompat.Builder(this, "your_channel_id") .setSmallIcon(R.drawable.ic_notification) .setContentTitle("新通知") .setContentText(body) .setPriority(NotificationCompat.PRIORITY_HIGH) // 设置FullScreenIntent,通知到达时触发唤醒 .setFullScreenIntent(pendingWakeIntent, true) val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager notificationManager.notify(System.currentTimeMillis().toInt(), notificationBuilder.build()) }
setFullScreenIntent第二个参数设为true,表示设备锁定时也会启动Activity- 透明Activity会快速启动并关闭,用户几乎无感知,但能有效触发屏幕唤醒
- 该方式无需申请
WAKE_LOCK权限,更符合Android后台权限规范
内容的提问来源于stack exchange,提问作者orbital_mechanic
相关产品推荐
相关产品推荐

