安卓应用后台发送消息及Firebase推送退后台接收问题咨询
安卓后台消息发送与Firebase推送后台接收问题解决方案
嘿,我来帮你搞定这两个安卓开发的问题!
一、如何在安卓应用后台发送消息?
安卓系统对后台任务的限制越来越严格(尤其是Android 8.0及以上),普通Service很容易被系统回收,所以得选合适的方案:
- 即时消息发送:推荐用
WorkManager来调度一次性任务,它会自动适配系统版本,保证任务能执行:- 写一个继承自
Worker的类,在doWork()方法里实现消息发送的逻辑(比如调用API发消息) - 构建
OneTimeWorkRequest,然后通过WorkManager.getInstance(context).enqueue(request)来启动任务
- 写一个继承自
- 定时/周期性消息发送:用
PeriodicWorkRequest,注意系统要求最短间隔不能少于15分钟 - 发送本地通知:不管前台后台,只要有
POST_NOTIFICATIONS权限(Android 13+需要),直接调用NotificationManager就能发送,不需要额外的后台服务
二、Firebase推送后台接收异常的解决方案
你提到前台接收正常,后台不行,还考虑用IntentService——其实IntentService在Android 8.0之后后台启动会被系统限制,Firebase官方推荐用FirebaseMessagingService来处理推送,这才是正确的姿势,我给你一步步说:
1. 正确配置FirebaseMessagingService
首先在AndroidManifest.xml里注册服务:
<service android:name=".MyFirebaseMessagingService" android:exported="false"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT" /> </intent-filter> </service>
2. 实现自定义的FirebaseMessagingService
重写onMessageReceived()方法,这里可以处理两种推送消息:
- 数据消息:不管应用在前台还是后台,只要没被完全杀死,都会触发这个方法,适合自定义处理
- 通知消息:后台时系统会自动显示通知,前台时才会走到这个方法
给你补全你的服务类代码:
package com.example.kai.msgtest; import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; import android.content.Context; import android.media.RingtoneManager; import android.net.Uri; import android.os.Build; import androidx.core.app.NotificationCompat; import com.google.firebase.messaging.FirebaseMessagingService; import com.google.firebase.messaging.RemoteMessage; public class MyFirebaseMessagingService extends FirebaseMessagingService { @Override public void onMessageReceived(RemoteMessage remoteMessage) { // 处理数据消息(后台也会触发) if (!remoteMessage.getData().isEmpty()) { String title = remoteMessage.getData().get("title"); String body = remoteMessage.getData().get("body"); sendCustomNotification(title, body); } // 处理通知消息(前台时自定义显示,后台系统自动处理) if (remoteMessage.getNotification() != null) { String title = remoteMessage.getNotification().getTitle(); String body = remoteMessage.getNotification().getBody(); if (isAppInForeground()) { sendCustomNotification(title, body); } } } // 发送自定义通知 private void sendCustomNotification(String title, String body) { String channelId = "msgtest_default_channel"; NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); // Android O及以上需要创建通知渠道 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationChannel channel = new NotificationChannel( channelId, "消息通知渠道", NotificationManager.IMPORTANCE_DEFAULT ); notificationManager.createNotificationChannel(channel); } Uri defaultSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); NotificationCompat.Builder builder = new NotificationCompat.Builder(this, channelId) .setSmallIcon(R.drawable.ic_notification) // 替换成你的应用图标 .setContentTitle(title) .setContentText(body) .setAutoCancel(true) .setSound(defaultSound); notificationManager.notify(1001, builder.build()); } // 判断应用是否在前台 private boolean isAppInForeground() { // 这里可以用ActivityManager来判断,示例代码: /* ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); List<ActivityManager.RunningAppProcessInfo> runningProcesses = am.getRunningAppProcesses(); if (runningProcesses != null) { for (ActivityManager.RunningAppProcessInfo process : runningProcesses) { if (process.processName.equals(getPackageName()) && process.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) { return true; } } } return false; */ return false; // 替换成实际的判断逻辑 } }
3. 关键注意事项
- 别再用IntentService处理推送了!它在后台启动会被系统拦截,FirebaseMessagingService是专门为推送设计的,系统会在收到推送时唤醒它
- 很多厂商的定制系统(比如小米、华为)会把后台应用加入电池优化,导致推送收不到——一定要引导用户把你的应用加入电池优化白名单
- 如果用Firebase控制台发送通知,后台时系统会自动显示,如果你想自己处理后台推送,要发送数据消息(在控制台的「高级选项」里选择数据消息,或者用API发送
data字段)
内容的提问来源于stack exchange,提问作者webbymaster




