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

Android 8设备使用FCM 11.8.0启动服务触发IllegalStateException异常求助

解决Android 8设备上Firebase Messaging启动Service的IllegalStateException问题

这个问题我之前帮不少开发者排查过,核心原因很清晰:Android 8.0(API 26)开始引入了严格的后台执行限制,禁止应用在无可见Activity的后台状态下直接启动传统Service;而你使用的com.google.firebase:firebase-messaging:11.8.0是比较早期的版本,还没针对这个系统规则做适配,所以才会抛出java.lang.IllegalStateException: Not allowed to start service Intent错误。

下面给你两种可行的解决方案,优先推荐第一种:

方案一:升级Firebase Messaging依赖版本

这是最简单也最稳妥的方式,Google在后续的Firebase Messaging版本中已经完全适配了Android 8+的后台限制,内部会自动处理服务启动的逻辑,不需要你修改业务代码。

只需要把依赖替换为较新的稳定版本(建议直接用最新稳定版,比如23.x系列,你可以根据项目其他依赖的兼容性调整):

implementation 'com.google.firebase:firebase-messaging:23.0.0'

升级后,原来的FirebaseMessagesService代码不需要做任何修改,就能在Android 8设备上正常工作。

方案二:手动适配Android 8+的后台限制(不升级依赖时使用)

如果因为项目兼容性问题暂时无法升级依赖,可以通过以下两种方式手动适配:

方式1:用JobIntentService替代传统Service

JobIntentService是Android官方推荐的适配方案,它会根据系统版本自动选择用JobScheduler(Android O+)或传统Service(低于O版本)来执行后台任务,完美避开后台启动限制。

步骤如下:

  1. 创建继承JobIntentService的消息处理类:
public class FCMJobIntentService extends JobIntentService {
    public static final String FCM_ACTION_MESSAGE = "com.project.services.fcm.ACTION_MESSAGE";
    public static final String EXTRA_MESSAGE = "VALUE";
    private static final int JOB_ID = 1001; // 唯一的Job ID,自己定义即可

    // 静态方法,用于启动任务,自动适配系统版本
    public static void enqueueWork(Context context, Intent intent) {
        enqueueWork(context, FCMJobIntentService.class, JOB_ID, intent);
    }

    @Override
    protected void onHandleWork(@NonNull Intent intent) {
        // 这里写你原来在FirebaseMessagesService中处理消息的逻辑
        if (FCM_ACTION_MESSAGE.equals(intent.getAction())) {
            String message = intent.getStringExtra(EXTRA_MESSAGE);
            // 处理消息的业务代码...
        }
    }
}
  1. 修改原FirebaseMessagesService的onMessageReceived方法,改用JobIntentService处理任务:
public class FirebaseMessagesService extends FirebaseMessagingService {
    @Override
    public void onMessageReceived(@NonNull RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);
        
        Intent intent = new Intent(FCMJobIntentService.FCM_ACTION_MESSAGE);
        intent.putExtra(FCMJobIntentService.EXTRA_MESSAGE, remoteMessage.getData().toString());
        // 用JobIntentService的方式启动任务
        FCMJobIntentService.enqueueWork(this, intent);
    }
}
  1. 在AndroidManifest.xml中注册FCMJobIntentService:
<service
    android:name=".FCMJobIntentService"
    android:permission="android.permission.BIND_JOB_SERVICE" />

方式2:启动前台Service(不推荐,会显示通知)

如果你必须使用传统Service,那么在Android 8+设备上需要调用startForegroundService,并且在Service的onCreate方法中调用startForeground显示一个前台通知,否则系统会在几秒后强制停止服务并抛出异常。

示例代码:

  • 启动Service时的版本判断:
Intent intent = new Intent(this, YourService.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    startForegroundService(intent);
} else {
    startService(intent);
}
  • 在Service的onCreate中创建前台通知:
@Override
public void onCreate() {
    super.onCreate();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        // 创建通知渠道(Android O+必须)
        NotificationChannel channel = new NotificationChannel("fcm_service_channel", "FCM消息处理", NotificationManager.IMPORTANCE_LOW);
        NotificationManager notificationManager = getSystemService(NotificationManager.class);
        if (notificationManager != null) {
            notificationManager.createNotificationChannel(channel);
        }
        // 构建前台通知
        Notification notification = new NotificationCompat.Builder(this, "fcm_service_channel")
                .setSmallIcon(R.drawable.ic_notification) // 替换成你的通知图标
                .setContentTitle("处理FCM消息")
                .setContentText("正在后台处理消息")
                .build();
        startForeground(1, notification); // 启动前台服务,传入唯一的通知ID和通知实例
    }
}

内容的提问来源于stack exchange,提问作者Alejandro Uribe Sánchez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 02:29:03