JobService在满足条件的情况下,会在APP的主线程中执行任务。因此需要我们注意不能直接执行耗时的任务。
JobService的使用首先要先申请一个保护权限 "android.permission.BIND_JOB_SERVICE" ,否则系统将跳过这个JobService。
<service android:name="MyJobService"
android:permission="android.permission.BIND_JOB_SERVICE" >
JobService 继承自 Service,使用上也相对简单,涉及到的主要方法有以下几个:
public class JobSchedulerService extends JobService {
@Override
public boolean onStartJob(JobParameters params) {
return false;
}
@Override
public boolean onStopJob(JobParameters params) {
return false;
}
}
boolean onStartJob(JobParameters params)
第一个需要重写的方法,该方法在Job满足条件时,开始被调用。我们需要在该方法中实现我们自己的需求逻辑。需要特别注意的是,这个方法是执行在应用的主线程里面的,所以要避免直接使用耗时操作。
该方法返回一个布尔值,返回true表示该job需要继续运行,如果我们选择返回true,job会一直处于存活状态直到我们手动调用JobFinished告诉系统任务完成了或者job设定的条件不再满足了。比如:我们的jobschedule设定了setRequiresCharging(true),那么当我们不再充电的时候,该job就会被立即停止。这个时候 onStopJob(JobParameters)就会被调用。如果返回的是false,则表示该job在return的时候已经结束,并且onStopJob(JobParameters) 不会被调用。
该方法传入一个JobParameters参数,该参数表示Job的配置信息,用于标识正在运行中的job,比如在调用jobFinished(JobParameters, boolean)时传入。
boolean onStopJob (JobParameters params)
该方法会在系统决定停止该job时调用,不管你是否调用了jobFinished。
该方法传入JobParameters ,这个与onStartJob中的相同。该方法返回一个布尔值,返回true用来告诉JobManager你是否要重试该job,重试的条件在创建job的时候定义。返回false的话表示该job将完全结束。不管我们选择返回什么值,这一次的job将必定会被停止执行。
void jobFinished (JobParameters params, boolean wantsReschedule)
调用该方法用来手动停止某一个job,我们可以通过传入true给wantsReschedule来表示希望重新计划该job。我们可以通过setBackoffCriteria 来调整重试的策略。这里不展开。
看完JobService的主要方法,接下来看看如何构建并配置任务:
首先获取到schedule:
JobScheduler js = context.getSystemService(JobScheduler.class);
接下来我们使用builder模式创建一个JobInfo,设置相应的属性和配置项,这些配置项决定了Job什么时候会被触发。
JobInfo jobInfo = new JobInfo.Builder(OOBEConstant.JB_ID_SUPPORT_CHECK, new ComponentName(context.getPackageName(), OOBEQueryIfSupportJobService.class.getName()))
.setPersisted(true)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
.build();
完成配置之后我们就可以安排执行任务了:
js.schedule(jobInfo);
可以看到为了满足我们的条件,关键还是在构建JobInfo的时候设置符合我们要求的属性,这里我贴上一些常用的:
addTriggerContentUri(JobInfo.TriggerContentUri uri)
添加监听一个Uri,如果发生改变就会触发job
setBackoffCriteria(long initialBackoffMillis, int backoffPolicy)
设置重试策略
setMinimumLatency(long minLatencyMillis)
设置job延迟的最短时间
setPersisted(boolean isPersisted)
设置重启后是否生效
setRequiredNetworkType(int networkType)
设置job需要的网络类型
JobScheduler 用于整体的调度,它主要涉及以下几个方法:
schedule(JobInfo job)
安排执行一个job,它会返回一个int值,RESULT_SUCCESS表示成功安排,RESULT_FAILURE表示失败。
cancel(int jobId)
取消一个特定的job
cancelAll()
取消由该应用所有已经计划的job
值得注意的是,当job在运行的时候,系统会给APP一个wakelock,也就是它保证了我们的job在运行的时候设备会一直处于唤醒的状态。
下面贴主要代码:
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class ShowNotificationJobService extends JobService {
@Override
public boolean onStartJob(JobParameters params) {
Intent intent = new Intent(START_NOTIFICATION);
intent.setClass(this, FlowController.class);
sendBroadcast(intent);
return false;
}
@Override
public boolean onStopJob(JobParameters params) {
return false;
}
public static void schedule(Context context){
long startupTime = Utils.getPreferences(context).getLong(Constant.SP_PARAM_TIME,0);
long latency = Constant.NOTIFICATION_DELAY - (System.currentTimeMillis() - startupTime);
JobScheduler js = (JobScheduler) context.getSystemService(JOB_SCHEDULER_SERVICE);
JobInfo.Builder builder = new JobInfo.Builder(Constant.JB_ID_NOTIFICATION_CHECK, new ComponentName(context.getPackageName(), ShowNotificationJobService.class.getName()))
.setPersisted(true)
.setMinimumLatency(latency)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
if(latency > 0){
builder.setMinimumLatency(latency);
}
js.schedule(builder.build());
if( result == JobScheduler.RESULT_SUCCESS ){
Log.i(TAG, "scheduled success");
}
else {
Log.i(TAG, "scheduled failed");
}
}
}