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

Firebase onMessageReceived中Volley发消息锁屏失效,求解决办法

解决Firebase推送屏幕熄灭后onMessageReceived中任务失效的问题

我来帮你分析下这个问题:屏幕熄灭后设备会进入低功耗状态(比如Doze模式),Android系统会严格限制后台App的CPU、网络资源,再加上Firebase消息的类型差异,就会导致你在onMessageReceived里调用的send_message_via_volley()失效。下面是几个经过验证的可行方案:

1. 确保发送的是Firebase数据消息

首先要区分通知消息和数据消息:

  • 如果是通知消息:当App处于后台(包括屏幕熄灭)时,系统会直接接管并显示通知,不会触发onMessageReceived,只有用户点击通知时才会回调。
  • 如果是数据消息:无论App在前台还是后台,都会直接触发onMessageReceived。

所以你需要让推送服务器发送纯数据消息,示例格式如下(JSON):

{
  "to": "设备令牌",
  "data": {
    "title": "自定义标题",
    "content": "自定义内容",
    "other_key": "其他参数"
  }
}

2. 正确使用WakeLock维持CPU唤醒

你之前尝试的PowerManager思路是对的,但可能存在使用姿势错误。需要注意:

  • 必须在AndroidManifest.xml中添加权限:
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    
  • 在onMessageReceived中获取Partial WakeLock(不需要点亮屏幕,仅维持CPU运行),执行完Volley请求后必须释放:
public void onMessageReceived(RemoteMessage remoteMessage) {
    PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
    PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
            "MyApp::PushWakeLock");
    wakeLock.acquire(30*1000); // 最多持有30秒,防止忘记释放

    try {
        send_message_via_volley();
    } finally {
        if (wakeLock.isHeld()) {
            wakeLock.release();
        }
    }
}

3. 使用WorkManager执行后台任务

onMessageReceived的执行时间在后台场景下会被系统限制(通常只有几秒),Volley请求如果耗时较长可能被中断。推荐使用WorkManager来托管你的网络请求,它能保证任务在设备资源允许时完成,即使App被杀死或设备休眠:

步骤1:添加WorkManager依赖

在build.gradle中添加:

dependencies {
    implementation "androidx.work:work-runtime:2.8.1"
}

步骤2:创建Worker类

public class PushWorker extends Worker {
    public PushWorker(@NonNull Context context, @NonNull WorkerParameters params) {
        super(context, params);
    }

    @NonNull
    @Override
    public Result doWork() {
        // 在这里执行Volley请求
        send_message_via_volley();
        return Result.success();
    }
}

步骤3:在onMessageReceived中调度任务

public void onMessageReceived(RemoteMessage remoteMessage) {
    OneTimeWorkRequest workRequest = new OneTimeWorkRequest.Builder(PushWorker.class)
            .setConstraints(new Constraints.Builder()
                    .setRequiredNetworkType(NetworkType.CONNECTED) // 确保有网络时执行
                    .build())
            .build();
    WorkManager.getInstance(this).enqueue(workRequest);
}

4. 将App加入电池优化白名单

Android的Doze模式和App Standby会在设备休眠时限制后台App的网络和CPU。你可以引导用户将App加入电池优化白名单:

代码跳转设置页面

Intent intent = new Intent();
String packageName = getPackageName();
PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
if (!pm.isIgnoringBatteryOptimizations(packageName)) {
    intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
    intent.setData(Uri.parse("package:" + packageName));
    startActivity(intent);
}

注意事项

  • 需要在AndroidManifest.xml中添加权限:
    <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
    
  • 这个权限需要Google Play审核,仅在你的App属于“即时通讯”“导航”等必须后台运行的场景下才建议使用。

5. 维持Wifi连接(可选)

如果你的设备使用Wifi,可以通过WifiLock保持连接:

WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
WifiManager.WifiLock wifiLock = wifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "MyApp::PushWifiLock");
wifiLock.acquire(30*1000);
// 执行网络请求后释放
wifiLock.release();

同时需要添加权限:

<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:30:04