Android 后台任务Services、WorkManager总结

Android O对应用在后台运行时可以执行的操作施加了限制,称为后台执行限制(Background Execution Limits),这可以大大减少应用的内存使用和耗电量,提高用户体验。后台执行限制分为两个部分:后台服务限制(Background Service Limitations)、 广播限制(BroadcastLimitations)

后台服务限制

除了下面情况外都是后台应用:

  1. 具有可见的Activity
  2. 具有前台服务
  3. 另一个前台应用已关联到该应用(通过bindService或者使用该应用的ContentProvider)。

应用在后台期间保留其后台服务的能力将受到限制。如果应用处于后台时调用了startService()将会抛出IllegalStateException,除非:

  • 应用已经处于前台,则可以调用 startService(),不会抛出IllegalStateException,但一旦进入后台,后台应用将被置于一个临时白名单中,位于白名单中时,在这段时间内,应用可以无限制地启动服务,其后台服务也可以运行。但这个时间期一过(Nexus 5X 8.0 系统上测试不到1分钟),应用就会进入空闲状态,后台服务就会被销毁。

因此,通过startservices启动的服务有如下特点:

  1. 在后台运行的服务在几分钟内会被stop掉(模拟器测试在1分钟左右后被kill掉)。在这段时间内,应用仍可以创建和使用服务。
  2. 在应用处于后台几分钟后(模拟器测试1分钟左右),应用将不能再通过startService创建后台服务,如果创建则抛出以下异常
Caused by: java.lang.IllegalStateException: Not allowed to start service Intent { cmp=com.example.xxxx.test/.TestService }: app is in background

也就是说,当你的应用不在前台,时间窗结束后,会变成闲置状态,系统就杀死你的后台服务。网上一系列Service保活,创建永不停止Service,经过验证,都已失效。即你无法在使用后台服务在后台偷偷执行需要长时间的任务,例如监控GPS状态,记录步数等等。限制后台服务使用的原因是,当你的app使用服务在后台运行时,你的app消耗了宝贵的资源:- 内存 - 电池。最佳的做法是:操作完成后,服务应自行停止。许多应用程序具有长时间运行的后台服务,这些服务基本上运行无限时间以维持与服务器的Socket连接或监视某些任务或用户活动。这些服务会导致电池耗尽,并且还会不断消耗内存。鉴于以上原因:后台服务已经无法再在后台执行长时间任务。安卓推出了以下方案来解决此类问题:

  • 前台服务Android 8.0 引入了一种全新的方法,即Context.startForegroundService(),以在前台启动新服务。在系统创建服务后,应用有五秒的时间来调用该服务的startForeground() 方法以显示新服务的用户可见通知。如果应用在此时间限制内未调用
    startForeground(),则系统将停止服务并声明此应用为 ANR。

  • WorkManager:WorkManager适用于那些即使应用程序退出,系统也能够保证这个任务正常运行的场景,比如将应用程序数据上传到服务器。它不适用于应用进程内的后台工作,如果应用进程消失,就可以安全地终止。

  • JobScheduler: JobScheduler 作业替换后台服务。 例如,CoolPhotoApp需要检查用户是否已经从朋友那里收到共享的照片,即使该应用未在前台运行。

前台服务

对于需要立即运行并且必须执行完毕的由用户发起的工作,请使用前台服务。使用前台服务可告知系统应用正在执行重要任务,不应被终止。前台服务通过通知栏中的不可关闭通知向用户显示。

  1. 修改启动方式
Intent service = new Intent(this, MyBackgroundService.class);
service.putExtra("startType", 1);
if (Build.VERSION.SDK_INT >= 26) {
    startForegroundService(service);
} else {
    startService(service);
}
  1. 启动完前台service, 一定记得在5s以内要执行startForeground方法,不然就会出现ANR。
public class MyBackgroundServiceextends Service {

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

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            //适配安卓8.0
            String channelId = getChannelId() + "";
            String channelName = getChannelName();
            NotificationChannel channel = new NotificationChannel(channelId, channelName,
                    NotificationManager.IMPORTANCE_MIN);
            NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            manager.createNotificationChannel(channel);
            startForeground(getChannelId(), getNotification());
        }
    }
    ...
}

一样还是先判断系统版本, 如果高于26就调用startForeground方法好了, 使用startForegroundService 方法启动后台service这么使用即可。不过这样会在通知栏里面弹出弹出通知。

WorkManager

WorkManager适用于那些即使应用程序退出,系统也能够保证这个任务正常运行的场景,比如将应用程序数据上传到服务器。它不适用于应用进程内的后台工作,如果应用进程消失,就可以安全地终止

WorkManager 不适用于需要在特定时间触发的任务,也不适用立即任务。针对特定时间触发的任务使用 AlarmManager,立即执行的任务使用 ForegroundService。

WorkManager适用于那些在应用退出之后任务还需要继续执行的需求(比如应用数据上报服务器的情况),对应那些在应用退出的之后任务也需要终止的情况就需要选择ThreadPool、AsyncTask来实现。

对于可延迟的工作以及预计即使您的设备或应用重启也会运行的工作,请使用 WorkManager。WorkManager 是一个 Android 库,可在满足工作的条件(例如网络可用性和电源)时妥善运行可延迟的后台工作。

WorkManager 提供向后兼容的 API(兼容 API 级别 14 及更高级别),利用 JobScheduler API(API 级别 23 及更高级别)帮助优化更低级别设备上的电池续航时间、批量作业以及 AlarmManagerBroadcastReceiver 的组合。

WorkManager是一个用于排队可延迟工作的库,保证在满足约束条件后的某个时间执行。 WorkManager允许观察工作状态和创建复杂工作链的能力。
WorkManager旨在通过为系统驱动的后台处理提供一流的API来简化开发人员体验。它适用于即使应用程序不再位于前台也应运行的后台作业。在可能的情况下,它使用JobScheduler或Firebase JobDispatcher来完成工作; 如果你的应用程序在前台,它甚至会尝试直接在你的过程中完成工作。
应用场景:每15分钟跟踪用户位置

WorkManager 和AsyncTask, ThreadPool, RxJava的区别:这三个和WorkManager并不是替代的关系. 这三个工具, 能帮助你在应用中开后台线程干活, 但是应用一被杀或被关闭, 这些工具就干不了活了. 而WorkManager不是, 它在应用被杀, 甚至设备重启后仍能保证你安排给他的任务能得到执行.

定义 Worker

咱们定义 MainWorker 继承 Worker,发现须要重写 doWork 方法,而且须要返回任务的状态 WorkerResult:

class MainWorker : Worker() {
    override fun doWork(): WorkerResult {
        // 要执行的任务
        return WorkerResult.SUCCESS
    }
}
定义 WorkRequest

在 MainActivity 中定义 WorkRequest:

val request = OneTimeWorkRequest.Builder(MainWorker::class.java).build()

OneTimeWorkRequest 意味着这个任务只需执行一遍。

加入任务队列

要让任务执行,须要将 WorkRequest 加入任务队列:

WorkManager.getInstance().enqueue(request)

AlarmManager

如果您需要在确切的时间运行某项作业,请使用 AlarmManagerAlarmManager 会在您指定的时间启动应用(如有必要),以便运行该作业。但是,如果您的作业不需要在确切的时间运行,则 WorkManager 是更好的选择;WorkManager 能更好地平衡系统资源。例如,如果您需要大约每小时运行一次某项作业,但不需要在特定时间运行该作业,则应使用 WorkManager 设置周期性作业。

DownloadManager

如果您的应用执行长时间运行的 HTTP 下载,请考虑使用 DownloadManager。客户端可能会请求将 URI 下载到位于应用进程之外的特定目标文件中。内容下载管理器会在后台执行下载操作,它负责处理 HTTP 互动,在下载失败或连接发生更改以及系统重新启动后重新尝试下载。

后台任务选择

场景 推荐
需系统触发,不必完成 ThreadPool + Broadcast
需系统触发,必须完成,可推迟 WorkManager
需系统触发,必须完成,立即 ForegroundService + Broadcast
不需系统触发,不必完成 ThreadPool
不需系统触发,必须完成,可推迟 WorkManager
不需系统触发,必须完成,立即 ForegroundService

Android Jetpack - 使用 WorkManager 管理后台任务
Android后台Service已死 WorkManager崛起
Android P后台服务被终止,创建永不终止的后台服务
Android后台任务
学习Android Jetpack? 实战和教程这里全都有!
Android Jetpack - 使用 WorkManager 管理后台任务

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,928评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,192评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,468评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,186评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,295评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,374评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,403评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,186评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,610评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,906评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,075评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,755评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,393评论 3 320
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,079评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,313评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,934评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,963评论 2 351