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

关于手机进入深度睡眠时无法接收FCM通知的技术问询

解决FCM深度睡眠下无法即时接收Data通知的问题

首先得明确:虽然FCM的高优先级Data消息官方宣称可以唤醒设备,但国内安卓厂商的定制省电策略是这个问题的核心元凶,咱们从几个维度来排查和解决:

  • 检查厂商系统的电池优化设置
    几乎所有国内品牌(小米、华为、OPPO、vivo等)都有严格的后台省电机制,深度睡眠时会切断非白名单应用的网络和唤醒权限。你需要引导用户:

    1. 进入系统设置 → 电池 → 电池优化
    2. 找到你的应用,设置为不允许优化
    3. 同时确保应用的“后台活动权限”“自启动权限”已经开启(不同厂商路径略有不同)
  • 确认FCM消息的推送参数是否正确
    你提到设置了"priority":"high",但要注意:

    • 对于Data类型消息,这个参数必须在服务器端的推送请求中设置,而不是客户端代码里
    • 另外,Android 8.0+ 还需要配合"content_available": true参数,确保系统会唤醒应用处理消息
      正确的推送 payload 示例:
    {
      "to": "DEVICE_TOKEN",
      "priority": "high",
      "content_available": true,
      "data": {
        "title": "紧急通知",
        "body": "这是一条高优先级Data消息",
        "key1": "value1"
      }
    }
    
  • 优化FCM回调服务的代码逻辑
    你的FCMCallbackService应该继承自FirebaseMessagingService,重写onMessageReceived方法时,建议添加临时唤醒锁来确保消息处理完成:

    public class FCMCallbackService extends FirebaseMessagingService {
        private static final String TAG = "FCMCallbackService";
        private PowerManager.WakeLock wakeLock;
    
        @Override
        public void onMessageReceived(RemoteMessage remoteMessage) {
            // 获取唤醒锁,确保设备在处理消息时保持清醒
            PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
            wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG + ":WakeLock");
            wakeLock.acquire(3000); // 锁定3秒,足够处理消息和弹出通知
    
            try {
                // 处理Data消息,构建并显示通知
                if (remoteMessage.getData().size() > 0) {
                    String title = remoteMessage.getData().get("title");
                    String body = remoteMessage.getData().get("body");
                    showNotification(title, body);
                }
            } finally {
                // 释放唤醒锁
                if (wakeLock != null && wakeLock.isHeld()) {
                    wakeLock.release();
                }
            }
        }
    
        private void showNotification(String title, String body) {
            // 构建通知的逻辑,注意Android 8.0+需要创建通知渠道
            NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                NotificationChannel channel = new NotificationChannel("high_priority_channel", "高优先级通知", NotificationManager.IMPORTANCE_HIGH);
                notificationManager.createNotificationChannel(channel);
            }
    
            NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "high_priority_channel")
                    .setSmallIcon(R.drawable.ic_notification)
                    .setContentTitle(title)
                    .setContentText(body)
                    .setPriority(NotificationCompat.PRIORITY_HIGH)
                    .setAutoCancel(true);
    
            notificationManager.notify(1, builder.build());
        }
    }
    

    这里的唤醒锁是临时的,不会长期占用设备资源,只是确保消息处理和通知展示的过程中设备不会立刻回到睡眠。

  • 额外注意事项

    • 避免使用已废弃的FirebaseInstanceIdService,确保使用最新的FirebaseMessagingService
    • 测试时一定要用真实设备的深度睡眠状态,不要用模拟器,模拟器的睡眠机制和真实设备差异很大
    • 某些厂商的“极致省电模式”会完全切断所有后台应用,这种情况下即使设置了白名单也可能无效,需要引导用户关闭该模式或者把应用加入例外

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:12:49