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

后台服务中获取FCM Token时回调未执行,该如何解决?

问题原因及修复方案

核心原因

  1. 线程Looper缺失:Firebase的addOnCompleteListener默认会使用当前线程的Looper调度回调。如果你的后台服务运行在没有Looper的线程(比如默认的IntentService工作线程),回调就无法触发——因为Handler需要Looper来处理消息队列。而MainActivity的主线程自带Looper,所以能正常执行回调。
  2. 服务生命周期过早结束:如果后台服务在getToken的异步任务完成前就被销毁(比如任务执行完毕后自行停止),回调所属的对象可能被回收,导致回调无法执行。

修复方案

方案一:指定主线程Executor执行回调

直接让回调在主线程运行,避开后台线程的Looper问题,这是最简单的解决方式:

public static void getFcmToken(Context context) {
    FirebaseMessaging
      .getInstance()
      .getToken()
      .addOnCompleteListener(
        // 指定使用主线程的Executor
        ContextCompat.getMainExecutor(context),
        new OnCompleteListener<String>() {
          @Override
          public void onComplete(Task<String> task) {
            if (!task.isSuccessful()) {
              Log.w(
                "ERROR",
                "Fetching FCM registration token failed",
                task.getException()
              );
              return;
            }
            String token = task.getResult();
            // 在这里处理获取到的Token
          }
        }
      );
}

方案二:给后台服务配置带Looper的线程

如果必须在后台线程处理回调,可以给服务创建带Looper的工作线程(比如用HandlerThread):

public class MyBackgroundService extends Service {
    private HandlerThread handlerThread;
    private ServiceHandler serviceHandler;

    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            // 在带Looper的线程中调用getFcmToken
            getFcmToken(MyBackgroundService.this);
            // 任务完成后停止服务(按需调整)
            stopSelf(msg.arg1);
        }
    }

    @Override
    public void onCreate() {
        handlerThread = new HandlerThread("FcmTokenServiceThread");
        handlerThread.start();
        Looper looper = handlerThread.getLooper();
        serviceHandler = new ServiceHandler(looper);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Message msg = serviceHandler.obtainMessage();
        msg.arg1 = startId;
        serviceHandler.sendMessage(msg);
        // 服务被杀死后自动重启(按需调整)
        return START_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onDestroy() {
        handlerThread.quit();
    }
}

额外注意事项

  • 确保应用已正确配置FCM:包含google-services.json文件,依赖项版本匹配。
  • Android 8.0及以上系统中,后台服务容易被系统回收,建议将服务设为前台服务(需申请FOREGROUND_SERVICE权限),保证异步任务能完成。

内容的提问来源于stack exchange,提问作者Ивелин Иванов

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 10:47:03