Android --- Android 8.0之后不允许在后台启动一个服务的解决方案

从Android 8.0(API级别26)开始,Google 引入了后台服务限制,目的是为了改善系统资源管理和用户体验。这些限制导致在后台运行的服务可能会被系统认为是无效的,从而限制或者终止这些服务。针对这个问题,可以考虑以下几种解决方案:

  1. 使用 JobIntentService

JobIntentService 是 Android 提供的一个服务类,专门用于处理那些需要长时间运行的后台任务,它能够利用系统的 JobScheduler API,在适当的时候执行任务,而不会像普通服务那样直接在后台无限期运行。

如何使用 JobIntentService:

创建一个继承自 JobIntentService 的类,并实现 onHandleWork() 方法来处理任务。
将任务逻辑放在 onHandleWork() 方法中。
调用 enqueueWork() 方法启动服务。

示例代码:

kotlin 复制代码
public class MyJobIntentService extends JobIntentService {

    static final int JOB_ID = 1000;

    public static void enqueueWork(Context context, Intent work) {
        enqueueWork(context, MyJobIntentService.class, JOB_ID, work);
    }

    @Override
    protected void onHandleWork(@NonNull Intent intent) {
        // 处理后台任务逻辑
    }
}

在你的应用中,通过调用 enqueueWork() 方法来启动 JobIntentService,系统会负责调度适当的时机执行任务。

kotlin 复制代码
Intent workIntent = new Intent(context, MyJobIntentService.class);
MyJobIntentService.enqueueWork(context, workIntent);
  1. 使用 Foreground Service

如果你的应用确实需要在后台长时间运行,并且需要执行一些重要的任务,可以将服务设置为前台服务(Foreground Service)。前台服务会在状态栏显示一个持续的通知,用户可以随时看到服务正在运行。

如何使用 Foreground Service:

将服务设置为前台服务,使用 startForeground() 方法,在通知栏显示一个通知。
在适当的时候,调用 stopForeground() 方法取消前台状态。

示例代码:

kotlin 复制代码
public class MyForegroundService extends Service {

    private static final int NOTIFICATION_ID = 1;
    private static final String CHANNEL_ID = "ForegroundServiceChannel";

    @Override
    public void onCreate() {
        super.onCreate();
        createNotificationChannel();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // 在服务中执行耗时操作

        // 设置为前台服务
        startForeground(NOTIFICATION_ID, getNotification());

        // 返回 START_NOT_STICKY 以便服务被终止后不会自动重启
        return START_NOT_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        // 停止前台服务
        stopForeground(true);
    }

    private void createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
                    "Foreground Service Channel",
                    NotificationManager.IMPORTANCE_DEFAULT);
            NotificationManager manager = getSystemService(NotificationManager.class);
            manager.createNotificationChannel(channel);
        }
    }

    private Notification getNotification() {
        Intent notificationIntent = new Intent(this, MainActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this,
                0, notificationIntent, 0);

        NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
                .setContentTitle("Foreground Service")
                .setContentText("Service is running in foreground")
                .setSmallIcon(R.drawable.ic_notification)
                .setContentIntent(pendingIntent);

        return builder.build();
    }

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

在 AndroidManifest.xml 文件中声明服务:

kotlin 复制代码
<service
    android:name=".MyForegroundService"
    android:enabled="true"
    android:exported="false" />

总结

选择适当的解决方案取决于你的应用需求和任务的性质。对于后台需要长时间运行的任务,推荐使用 JobIntentService 或者 Foreground Service。这些方法都能在一定程度上规避 Android 8.0 引入的后台服务限制,并提供了更好的用户体验和系统资源管理。

相关推荐
帅得不敢出门8 小时前
安卓设备adb执行AT指令控制电话卡
android·adb·sim卡·at指令·电话卡
我又来搬代码了10 小时前
【Android】使用productFlavors构建多个变体
android
德育处主任11 小时前
Mac和安卓手机互传文件(ADB)
android·macos
芦半山11 小时前
Android“引用们”的底层原理
android·java
迃-幵12 小时前
力扣:225 用队列实现栈
android·javascript·leetcode
大风起兮云飞扬丶12 小时前
Android——从相机/相册获取图片
android
Rverdoser12 小时前
Android Studio 多工程公用module引用
android·ide·android studio
aaajj13 小时前
[Android]从FLAG_SECURE禁止截屏看surface
android
@OuYang13 小时前
android10 蓝牙(二)配对源码解析
android
Liknana13 小时前
Android 网易游戏面经
android·面试