You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android 8.1.0后台服务自动停止问题求助(附相关代码)

排查Android 8.1.0后台服务自动停止及活动更新被移除的问题

根据你提供的代码和日志信息,核心问题出在Android 8.0+的后台服务限制政策,加上代码里的几个小疏漏,导致服务启动后很快被系统销毁,进而触发了onDestroy()里的removeActivityUpdatesButtonHandler(),所以你看到了Removed activity updates successfully!的日志。下面一步步分析原因并给出修复方案:

核心原因:Android 8.0+后台服务限制

从Android 8.0(API 26)开始,系统严格限制后台应用创建后台服务:

  • 如果应用处于后台状态(没有可见Activity),调用startService()启动的服务会在几秒内被系统强制停止
  • 必须使用startForegroundService()替代startService(),并且在服务启动后5秒内调用startForeground()显示一个前台通知,否则系统会直接终止服务并抛出ForegroundServiceStartNotAllowedException

你的代码里用的是startService(),完全符合这个被系统终止的场景,这是服务自动停止的主要原因。

次要问题:WakeLock使用不当

你的WakeLockonCreate()里的局部变量,方法执行完毕后这个变量会被GC回收,导致唤醒锁可能被系统提前释放,起不到保持服务唤醒的作用;而且没有在onDestroy()里释放,还可能造成内存泄漏。

修复方案

1. 改用前台服务启动方式

修改MainClass里的startTracking()方法,根据系统版本选择启动方式:

private void startTracking() {
    if (!isMyServiceRunning()) {
        Intent intent = new Intent(MainActivity.this, BackgroundDetectedActivitiesService.class);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            // Android 8.0+必须用前台服务启动
            startForegroundService(intent);
        } else {
            startService(intent);
        }
    }
}

2. 在服务中实现前台通知逻辑

修改BackgroundDetectedActivitiesService,添加前台通知代码,并修复WakeLock的使用:

public class BackgroundDetectedActivitiesService extends Service {
    private static final String TAG = BackgroundDetectedActivitiesService.class.getSimpleName();
    private Intent mIntentService;
    private PendingIntent mPendingIntent;
    private ActivityRecognitionClient mActivityRecognitionClient;
    private PowerManager.WakeLock wakeLock; // 改为成员变量
    IBinder mBinder = new BackgroundDetectedActivitiesService.LocalBinder();

    // ... 其他原有代码保持不变

    @Override
    public void onCreate() {
        super.onCreate();
        // 修复WakeLock:保存为成员变量,添加超时时间
        PowerManager mgr = (PowerManager) getSystemService(Context.POWER_SERVICE);
        wakeLock = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakeLock:BackgroundTracking");
        wakeLock.acquire(10 * 60 * 1000L); // 10分钟超时,避免长期持有

        // 创建前台通知(Android 8.0+必须)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(
                    "tracking_channel", 
                    "Activity Tracking", 
                    NotificationManager.IMPORTANCE_LOW // 低优先级,避免打扰用户
            );
            NotificationManager notificationManager = getSystemService(NotificationManager.class);
            notificationManager.createNotificationChannel(channel);
        }

        Notification notification = new NotificationCompat.Builder(this, "tracking_channel")
                .setContentTitle("Activity Tracking")
                .setContentText("Running in background")
                .setSmallIcon(R.mipmap.ic_launcher) // 必须设置小图标
                .build();

        // 启动前台服务,通知ID要唯一
        startForeground(1, notification);

        // 原有初始化代码
        mActivityRecognitionClient = new ActivityRecognitionClient(this);
        mIntentService = new Intent(this, DetectedActivitiesIntentService.class);
        // 适配Android 8.0+的PendingIntent Flag
        int pendingIntentFlag = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M 
                ? PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE 
                : PendingIntent.FLAG_UPDATE_CURRENT;
        mPendingIntent = PendingIntent.getService(this, 1, mIntentService, pendingIntentFlag);
        requestActivityUpdatesButtonHandler();
    }

    // ... 其他原有代码保持不变

    @Override
    public void onDestroy() {
        super.onDestroy();
        // 释放WakeLock
        if (wakeLock != null && wakeLock.isHeld()) {
            wakeLock.release();
        }
        removeActivityUpdatesButtonHandler();
    }
}

3. 额外优化建议

  • 关闭电池优化:引导用户在系统设置中关闭你的应用的电池优化(路径:设置 > 电池 > 电池优化 > 找到你的应用 > 选择“不优化”),避免系统在后台杀死服务。
  • 检查权限:虽然Android 8.1不需要动态申请ACTIVITY_RECOGNITION权限,但要确保Manifest里的权限声明正确,并且应用已经被授予该权限。
  • 避免长期持有WakeLock:WakeLock会增加耗电,尽量只在必要时持有,或者设置合理的超时时间。

验证修复

修改后重新测试:

  1. 启动应用,调用startTracking()
  2. 查看日志,应该会看到Successfully requested activity updates,而不会很快出现Removed activity updates successfully!
  3. 切换到后台,服务应该会保持运行,前台通知栏会显示你设置的通知。

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

火山引擎 最新活动