在 Android 4.1 ~ 5.1.1 应用程序被终止时,前台服务会立即被终止

Foreground Service is getting killed immediately in Android 4.1 ~ 5.1.1 when app is killed

我有一个正在前台下载文件的服务

@Override
    public int onStartCommand(Intent intent, int flags, int sid){
        this.sid = sid;
        PendingIntent mainIntent = PendingIntent.getActivity(this, 0, MyApplication.mainIntent, 0);
        Notification notification = new NotificationCompat.Builder(VuclipPrime.getInstance())
                .setSmallIcon(R.drawable.ic_launcher)
                .setContentTitle("Downloading Video")
                .setContentText("Initiating...")
                .setContentIntent(mainIntent)
                .setAutoCancel(false)
                .setOngoing(true)
                .build();
        startForeground(mNotificationId, notification);
        if (VideoDownloadManager.currentVideoDownloadTask != null) {
            VideoDownloadManager.currentVideoDownloadTask.start();
        } else {
            stopSelf();
        }
        return START_NOT_STICKY;
    }

当我滑动关闭应用程序时,服务也被停止了。 我尝试了 Whosebug 上的所有现有解决方案,但 none 有效。 我尝试了 YouTube 应用程序,但它并没有终止其服务。我该如何实现?谢谢

您正在使用 NOT_STICKY 参数启动服务。 你应该 return START_STICKY 在 onStartCommand()

@Override
    public int onStartCommand(Intent intent, int flags, int sid){
        this.sid = sid;
        PendingIntent mainIntent = PendingIntent.getActivity(this, 0, VuclipPrime.mainIntent, 0);
        Notification notification = new NotificationCompat.Builder(VuclipPrime.getInstance())
                .setSmallIcon(R.drawable.ic_launcher)
                .setContentTitle("Downloading Video")
                .setContentText("Initiating...")
                .setContentIntent(mainIntent)
                .setAutoCancel(false)
                .setOngoing(true)
                .build();
        startForeground(mNotificationId, notification);
        if (VideoDownloadManager.currentVideoDownloadTask != null) {
            VideoDownloadManager.currentVideoDownloadTask.start();
        } else {
            stopSelf();
        }
        return START_STICKY;
    }

来自文档:

https://developer.android.com/reference/android/app/Service.html#START_STICKY

  • START_STICKY:系统会尝试重新启动服务 它被杀了。
  • START_NO_STICKY:系统不会关心是否 服务被杀死。

解决方案是在服务的 onTaskRemoved() 方法中启动虚拟 activity 以防止服务被终止。 启动后立即完成 DummyActivity。

检查以下代码:-

package com.your.application.services;

import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Build;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;


public class DownloadService extends Service {
    int mNotificationId = 001;
    Notification notification;
    private int sid;

    public DownloadService() {
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int sid) {
        this.sid = sid;
        PendingIntent mainIntent = PendingIntent.getActivity(this, 0, YourApplication.getInstance().downloadService.mainIntent, 0);
        notification = new NotificationCompat.Builder(YourApplication.getInstance())
                .setSmallIcon(R.drawable.ic_launcher)
                .setContentTitle("Starting Service")
                .setContentText("Initiating...")
                .setContentIntent(mainIntent)
                .setAutoCancel(true)
                .setOngoing(true)
                .build();
        startForeground(mNotificationId, notification);
        if (YourApplication.getInstance().downloadService.videoDownloader != null) {
            YourApplication.getInstance().downloadService.startDonwloadThread(YourApplication.getInstance().downloadService.videoDownloader);
        } else {
            stopSelf();
        }
        return START_NOT_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

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

    @Override
    public void onTaskRemoved(Intent rootIntent) {
        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP_MR1 && Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR2) {
            Intent intent = new Intent(this, DummyActivity.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(intent);
        }
    }
}

虚拟活动:-

public class DummyActivity extends Activity {
    @Override
    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        finish();
    }
}

DummyActivity 的 AndroidManifest 条目:-

            <activity
            android:name=".downloader.DummyActivity"
            android:allowTaskReparenting="true"
            android:alwaysRetainTaskState="false"
            android:clearTaskOnLaunch="true"
            android:enabled="true"
            android:excludeFromRecents="true"
            android:finishOnTaskLaunch="true"
            android:noHistory="true"
            android:stateNotNeeded="true"
            android:theme="@android:style/Theme.NoDisplay" />

Android 如果在进程处于睡眠模式时未将其列为受保护的应用程序,则停止进程。转到设置->受保护的应用程序->Select 您的应用程序并将其启用为受保护的应用程序。