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

Firebase Firestore在自定义Service类中无法正常执行的问题

问题根源分析

你遇到的核心问题是:Firestore的操作都是异步执行的,但你在调用execute()后立刻调用了stopSelf(),导致Service被快速终止,进程可能随即被系统回收,异步回调onComplete根本没机会执行。另外,你的代码也没处理任务失败的场景,没法排查是否存在权限、网络这类隐性问题。

解决方案

1. 等待所有异步操作完成后再停止Service

把stopSelf()移到所有Firestore操作的回调里,确保状态更新完成后再终止Service。修改后的代码如下:

@Override
public void onTaskRemoved(Intent rootIntent) {
    super.onTaskRemoved(rootIntent);
    execute();
    // 这里不再直接调用stopSelf(),交给异步回调处理
}

public void execute(){
    final FirebaseFirestore database=FirebaseFirestore.getInstance();
    final SharedPreferences shared = PreferenceManager.getDefaultSharedPreferences(this);
    database.collection("users").whereEqualTo("username",shared.getString("username",""))
            .get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
        @Override
        public void onComplete(@NonNull Task<QuerySnapshot> task) {
            if (task.isSuccessful()) {
                // 遍历查询结果更新状态
                for (QueryDocumentSnapshot document : task.getResult()) {
                    Map<String, Object> map = new HashMap<>();
                    map.put("online", false);
                    database.collection("users").document(document.getId())
                            .set(map, SetOptions.merge())
                            .addOnCompleteListener(new OnCompleteListener<Void>() {
                                @Override
                                public void onComplete(@NonNull Task<Void> updateTask) {
                                    // 不管更新成功失败,最后都停止Service
                                    if (updateTask.isSuccessful()) {
                                        Log.d("MyService", "用户在线状态更新成功");
                                    } else {
                                        Log.e("MyService", "状态更新失败", updateTask.getException());
                                    }
                                    stopSelf();
                                }
                            });
                }
                // 如果查询结果为空,也要及时停止Service
                if (task.getResult().isEmpty()) {
                    stopSelf();
                }
            } else {
                // 处理查询失败的情况,打印异常方便排查
                Log.e("MyService", "查询用户信息失败", task.getException());
                stopSelf();
            }
        }
    });
}

2. 提升Service优先级(应对Android后台限制)

从Android 8.0开始,普通后台Service很容易被系统回收,你可以把Service改成前台Service来获得更高的运行优先级。需要做这几步:

  • 在AndroidManifest.xml中添加权限:
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    
  • 在Service的onCreate()方法中启动前台服务(需要创建一个通知,这是系统强制要求):
    @Override
    public void onCreate() {
        super.onCreate();
        // 创建通知渠道(针对Android O及以上)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel("USER_STATUS_CHANNEL", "用户状态更新", NotificationManager.IMPORTANCE_LOW);
            NotificationManager manager = getSystemService(NotificationManager.class);
            manager.createNotificationChannel(channel);
        }
        // 构建前台通知
        Notification notification = new NotificationCompat.Builder(this, "USER_STATUS_CHANNEL")
                .setContentTitle("后台处理")
                .setContentText("正在更新用户在线状态")
                .setSmallIcon(R.drawable.ic_launcher_foreground) // 替换成你的应用图标
                .build();
        // 启动前台服务
        startForeground(1001, notification);
    }
    

3. 检查Firestore权限与网络

  • 确认Firestore安全规则允许当前用户修改users集合的online字段,比如可以设置这样的规则(根据你的业务需求调整):
    match /users/{userId} {
      allow read, update: if request.auth != null && request.auth.uid == userId;
    }
    
  • 确保设备有稳定的网络连接,Firestore在无网时会缓存操作,但如果Service被杀死,缓存的更新可能无法及时同步到云端。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 15:48:09