在这篇文章中,我们将学习Android Lollipop(后面简称为Android L)提供的API——JobScheduler。JobScheduler允许开发者在遇到特殊情况时创建一些在后台执行的任务。
介绍:
在使用Android的过程中,我们一定遇到过这种情况:希望某个任务在稍后某个时间点执行或者在某些特定条件下执行,例如设备插上电源时或者连接到Wi-Fi时。非常感谢Android L提供的API 21,很多人已经知道Google提供了新的组件JobScheduler API来处理这种特殊场景。
当应用程序预定的条件满足时,JobScheduler API就会执行特定的操作。不像AlarmManager,它执行的时间不是确定的。再者,JobScheduler可以批量运行不同的任务。这就允许应用在使用设备电池时间太长时执行给定的任务。
在这篇文章中,为了深入了解JobScheduler API和JobService Class,我们将在Android应用中使用它们完成一些简单的后台任务。文章中涉及到的代码请参考GitHub(https://github.com/tutsplus/Android-JobSchedulerAPI)。
1.创建Job Service
在开始之前,我们需要创建一个新的Android project,使用最简化API 21,因为JobScheduler API是在最新的Android版本里面新增的,并且在写这篇文章时,它不是通过支持库向后兼容的。
假定我们使用的是Android Studio,当新建一个项目并点击完成按钮后,会有一个原生态的“Hello World”应用。第一步就是使用这个应用创建一个新的类,简单期间,我们命名为JobSchedulerService,继承于JobService,需要创建两个方法:onStartJob(JobParameters params) 和 onStopJob(JobParameters params)。
public class JobSchedulerService extends JobService {
@Override
public boolean onStartJob(JobParameters params) {
return false;
}
@Override
public boolean onStopJob(JobParameters params) {
return false;
}
}
onStartJob(JobParameters params)是开始任务时必须要使用的方法,因为它是系统用来触发已经调度好的任务的。如我们看到的,这个方法返回了一个布尔值。当返回为false时,系统就认为无论做的什么任务都没有花费太长时间,而且截止这个方法返回时,此任务已结束;当返回为ture时,系统会认为此任务需要花费一定的时间,此时压力就落在了开发者身上,系统需要开发者通过调用jobFinished(JobParameters params, boolean needsRescheduled)来告诉它任务何时完成。
onStopJob(JobParameters params)是当系统收到Cancel请求时,通过此方法来结束挂起的任务。值得一提的是,在onStartJob返回false的情况下,系统在收到Cancel请求时会认为当前没有执行的任务,不会调用onStopJob。
需要注意的是Job Service运行在我们应用的主线程中。这意味着我们需要创建另外一个线程,Handler或者其他异步任务来完成运行时间较长的任务,以免阻塞主线程。由于多线程技术超出了本文的范畴,简单期间我们在类JobSchedulerService中通过实现一个handler来执行我们的任务。
private Handler mJobHandler = new Handler( new Handler.Callback() {
@Override
public boolean handleMessage( Message msg ) {
Toast.makeText( getApplicationContext(),
"JobService task running", Toast.LENGTH_SHORT )
.show();
jobFinished( (JobParameters) msg.obj, false );
return true;
}
} );
在这个handler中,我们实现了handleMessage(Message msg)方法,它是Handler实例的一部分,用来完成任务。秉承尽量简便的原则,此任务只是通过应用弹出一条Toast消息,这样我们就可以把精力放在主要逻辑上面,如数据同步等。
当任务完成之后,需要调用jobFinished告诉系统应用的任务已完成,这样系统就可以开始下次任务调度。如果不这样做的话,应用只能完成一个任务,不能再申请其他任务。
jobFinished(JobParameters params, boolean needsRescheduled)的两个参数是这样的:JobParameters是通过onStartJob(JobParameters params)传给JobService的;另外一个布尔值needsRescheduled是告诉系统此任务是否需要进行重新调度,这取决于任务本身需求。布尔值needsRescheduled是非常有用的,它告诉系统由于一些原因没有完成任务时该如何处理,比如网络呼叫失败。
创建完Handler实例后,就可以来实现控制任务的onStartJob(JobParameters params) 和 onStopJob(JobParameters params)方法。通过下面的代码片段可以看到onStartJob返回值为true,因为我们需要通过Handler实例来控制我们的操作,这意味着此操作比onStartJob需要花费更长时间。通过返回true让应用知道我们需要调用方法jobFinished(JobParameters params, boolean needsRescheduled)。我们还注意到数字1传给了Handler实例,这是我们用了代表此任务的标示符。
@Override
public boolean onStartJob(JobParameters params) {
mJobHandler.sendMessage( Message.obtain( mJobHandler, 1, params ) );
return true;
}
@Override
public boolean onStopJob(JobParameters params) {
mJobHandler.removeMessages( 1 );
return false;
}
一旦定义了Java类JobSchedulerService,我们还需要在AndroidManifest.xml 里面为此服务添加说明,以便我们的应用有绑定和使用此类作为JobService的权限。
<service android:name=".JobSchedulerService"
android:permission="android.permission.BIND_JOB_SERVICE" />
2.创建Job Scheduler
类JobSchedulerService创建完成后,我们就需要关注应用如何JobScheduler API进行交互。我们需要做的第一件事是创建一个JobScheduler对象,样例代码中取名为mJobScheduler,它是通过获取系统服务JOB_SCHEDULER_SERVICE的一个实例进行初始化的,此应用是在类MainActivity中实现的。
mJobScheduler = (JobScheduler)
getSystemService( Context.JOB_SCHEDULER_SERVICE );
当需要创建调度任务时,我们可以使用JobInfo.Builder来构建JobInfo对象,它会传给服务。在创建JobInfo对象时,JobInfo.Builder接收两个参数。第一个是将要执行任务的标示符,第二个是将要在JobScheduler API中使用的服务的组件名称。
JobInfo.Builder builder = new JobInfo.Builder( 1,
new ComponentName( getPackageName(),
JobSchedulerService.class.getName() ) );
这个build允许应用设置很多不同的选项来控制任务的执行。比如下面的代码片段意味着每三秒钟执行一次任务。
builder.setPeriodic( 3000 );
其他的方法:
- setMinimumLatency(long minLatencyMillis):这个即经过minLatencyMillis时间再开始执行任务,此方法不能和setPeriodic(long time)同时使用,否则会引起异常。
- setOverrideDeadline(long maxExecutionDelayMillis):设置最长等待时间,即使其他条件未满足,经过maxExecutionDelayMillis后任务都会执行。此方法不能和setPeriodic(long time)同时使用,否则会引起异常。
- setPersisted(boolean isPersisted):此方法告诉系统,当设备重启时此任务是否需要退出。
- setRequiredNetworkType(int networkType):此方法说明设备在特定网络条件下才能运行此任务。默认是JobInfo.NETWORK_TYPE_NONE,即此任务不需要网络环境即可运行;另外还有JobInfo.NETWORK_TYPE_ANY表示完成此任务需要连接网路;第三种是JobInfo.NETWORK_TYPE_UNMETERED,即此任务需要设备在非窝蜂网络条件下。
- setRequiresCharging(boolean requiresCharging):只有在设备充电时才执行此任务。
- setRequiresDeviceIdle(boolean requiresDeviceIdle):只有在用户当前没有使用手机且有一段时间没有使用手机时才执行此任务。
//If something goes wrong
}
翻译源文件:http://code.tutsplus.com/tutorials/using-the-jobscheduler-api-on-android-lollipop--cms-23562