Note: Beginning with API 19 (Build.VERSION_CODES.KITKAT) alarm delivery is inexact: the OS will shift alarms in order to minimize wakeups and battery use. There are new APIs to support applications which need strict delivery guarantees; see setWindow(int, long, long, android.app.PendingIntent) and setExact(int, long, android.app.PendingIntent).
可以看到在 API 19以后,使用 AlarmManager 不会像以前那样精确了。
再来看看 Service:
A Service is an application component that can perform long-running operations in the background, and it does not provide a user interface.
不恰当的使用 Service 和 AlarmManager,除了会对设备的续航时间有影响外,从 Android Oreo (API 26) 开始,如果一个应用的 targeting SDK 为 Android 8.0,那么当它在某些不被允许创建后台服务的场景下,调用 Service 的startService() 方法,会抛出IllegalStateException。
ComponentName service = new ComponentName(this, MyJobService.class);
JobScheduler mJobScheduler = (JobScheduler)getSystemService(Context.JOB_SCHEDULER_SERVICE);
JobInfo.Builder builder = new JobInfo.Builder(jobId, serviceComponent)
.setRequiredNetworkType(jobInfoNetworkType)
.setRequiresCharging(false)
.setRequiresDeviceIdle(false)
.setExtras(extras).build();
mJobScheduler.schedule(jobInfo);
复制代码
但是 JobScheduler 只能在 API 23 及其以上才能使用,在 API 23 以下可以用 JobDispatcher。而 JobDispatcher 是 FireBase 中的类,需要 Google Play Services 的支持。
综上,WorkManager 应运而生。
WorkManager 为后台任务提供了一套统一的解决方案,它可以根据 Android 电量优化以及设备的 API 等级,选择合适的方式执行。WorkManager 向后兼容到 API 14,并且对无论集成 Google Play Service 服务与否的设备都予以支持。使用 WorkManager 管理任务,
允许任务延迟,并且保证任务能够执行到,即使应用关闭或设备重启。
classUploadWorker(appContext: Context, workerParams: WorkerParameters)
: Worker(appContext, workerParams) {
overridefundoWork(): Result {
try {
// Get the inputval imageUriInput = inputData.getString(Constants.KEY_IMAGE_URI)
// Do the workval response = upload(imageUriInput)
// Create the output of the workval imageResponse = response.body()
val imgLink = imageResponse.data.link
// workDataOf (part of KTX) converts a list of pairs to a [Data] object.val outputData = workDataOf(Constants.KEY_IMAGE_URI to imgLink)
return Result.success(outputData)
} catch (e: Exception) {
return Result.failure()
funupload(imageUri: String): Response {
TODO(“Webservice request code here”)
// Webservice request code here; note this would need to be run// synchronously for reasons explained below.复制代码
// Create the Constraints
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build()
// Define the input
val imageData = workDataOf(Constants.KEY_IMAGE_URI to imageUriString)
// Bring it all together by creating the WorkRequest; this also sets the back off criteria
val uploadWorkRequest = OneTimeWorkRequestBuilder<UploadWorker>()
.setInputData(imageData)
.setConstraints(constraints)
.setBackoffCriteria(
BackoffPolicy.LINEAR,
OneTimeWorkRequest.MIN_BACKOFF_MILLIS,
TimeUnit.MILLISECONDS)
.build()
复制代码
WorkContinuation left = workManager.beginWith(A).then(B);
WorkContinuation right = workManager.beginWith(C).then(D);
WorkContinuation final = WorkContinuation.combine(Arrays.asList(left, right)).then(E);
final.enqueue();复制代码
// In your UI (activity, fragment, etc)
WorkManager.getInstance().getWorkInfoByIdLiveData(uploadWorkRequest.id)
.observe(lifecycleOwner, Observer { workInfo ->
// Check if the current work's state is "successfully finished"
if (workInfo != null && workInfo.state == WorkInfo.State.SUCCEEDED) {
displayImage(workInfo.outputData.getString(KEY_IMAGE_URI))
复制代码