FCM高优先级消息触发启动Activity在华为/LG设备特定场景失效问题
解决华为/LG设备Doze/口袋模式下FCM无法启动AlarmActivity的问题
嘿,我之前也踩过华为和LG这类定制系统在Doze或口袋模式下限制后台Activity启动的坑,给你几个针对性的解决方案,应该能让你的AlarmActivity像系统闹钟/来电一样正常弹出:
1. 确保FCM消息是高优先级
首先要保证你的FCM payload明确设置了高优先级,Doze模式下只有高优先级消息能突破限制触发后续逻辑:
- 用Firebase控制台发送时,选择「高优先级」
- API调用时,在请求体中添加:
"priority": "high"
2. 用新的PowerManager API替代废弃的WakeLock
虽然SCREEN_BRIGHT_WAKE_LOCK被废弃,但我们可以用新方式获取唤醒锁,确保启动Activity前唤醒设备。修改你的FirebaseMessagingService:
@Override public void onMessageReceived(RemoteMessage remoteMessage) { // 获取PowerManager并创建唤醒锁 PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE); PowerManager.WakeLock wakeLock = powerManager.newWakeLock( PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "MyApp:AlarmWakeLockTag"); // 持有10秒足够完成Activity启动,避免长时间持有浪费资源 wakeLock.acquire(10 * 1000); Intent dialogIntent = new Intent(getBaseContext(), AlarmActivity.class); dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); dialogIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); // 移除无用的FLAG_RECEIVER_FOREGROUND(这个是给广播接收器用的) getApplication().startActivity(dialogIntent); // 释放唤醒锁 wakeLock.release(); }
3. 更新AlarmActivity的屏幕唤醒逻辑(适配Android 10+)
旧的WindowManager flags在Android 10及以上系统被部分废弃,改用官方推荐方法,同时处理华为口袋模式的锁屏限制:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Android 10+ 推荐用这些方法替代旧的Window Flags if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { setShowWhenLocked(true); setTurnScreenOn(true); } else { getWindow().addFlags( WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON); } // 处理华为口袋模式下的锁屏问题,尝试解锁Keyguard KeyguardManager keyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { keyguardManager.requestDismissKeyguard(this, null); } setContentView(R.layout.activity_alarm); // ... 你的其他业务逻辑 }
4. 申请必要权限并豁免电池优化
定制系统的电池优化会严格限制后台行为,必须申请权限并引导用户开启豁免:
第一步:在AndroidManifest.xml添加权限
<uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.DISABLE_KEYGUARD" /> <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
第二步:引导用户开启电池优化豁免
在App首次启动或收到FCM消息前,检查并申请豁免:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE); if (!powerManager.isIgnoringBatteryOptimizations(getPackageName())) { Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); intent.setData(Uri.parse("package:" + getPackageName())); startActivity(intent); } }
5. 华为/LG特殊系统权限引导
华为的「自启动管理」和LG的「后台限制」会额外拦截后台启动,代码无法自动获取权限,必须在App里添加引导页面,告诉用户:
- 华为:设置 > 应用和服务 > 应用启动管理 > 找到你的App > 关闭「自动管理」,开启「允许自启动」「允许后台活动」
- LG:设置 > 电池 > 电池优化 > 找到你的App > 设置为「不优化」
这些步骤组合起来,就能让你的AlarmActivity像系统闹钟或来电一样,在Doze模式、口袋模式下正常点亮屏幕并启动。
内容的提问来源于stack exchange,提问作者Kelib
相关产品推荐
相关产品推荐

