官方 DEMO
路径如下
sdk\sources\android-22\com\android\demo\jobSchedulerApp\
Demo 需求
JobShedule的出发点是提供省电场景给用户进行任务完成,目前主要场景如下
1.网络数据场景
2.充电场景
3.idle待机场景
4.固定周期场景
接下来我们已
充电下且网络为连接时的场景为例进行JobShedule的使用说明。
Demo中的源代码都是Google SDK自带的
核心设置参数代码如下
// 设置最小的延迟时间
builder.setMinimumLatency(1*1000);
// 设置最大的延迟时间,一旦设置了这个属性,不管其他条件怎么样,jobinfo到了时间就一定会执行。
builder.setOverrideDeadline(5*1000);
// 设置在什么样的网络下启动jobinfo
builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED);
// 设置设备需要在空闲的时候,是否启动job
builder.setRequiresDeviceIdle(false);
// 设置是否充电情况下调度
builder.setRequiresCharging(true);
备注:上述的关系是与的关系,不是或的关系
场景条件达成回调接口如下
public class MyJobSchedulerService extends JobService{
/**
* 满足Job预设置条件下回调
*/
@Override
public boolean onStartJob(JobParameters jobParameters) {
Log.d(Constant.TAG, "onStartJob: " + jobParameters.getJobId());
}
/**
* 1.被CancleAll的时候回调
* 2.不满足预设置条件的情况下回调
*/
@Override
public boolean onStopJob(JobParameters jobParameters) {
}
}
重要权限
<service android:name=".service.MyJobSchedulerService"
android:permission="android.permission.BIND_JOB_SERVICE"/>
/**
* Job services must be protected with this permission:
*
* <pre class="prettyprint">
* <service android:name="MyJobService"
* android:permission="android.permission.BIND_JOB_SERVICE" >
* ...
* </service>
* </pre>
*
* <p>If a job service is declared in the manifest but not protected with this
* permission, that service will be ignored by the OS.
*/
public static final String PERMISSION_BIND =
"android.permission.BIND_JOB_SERVICE";
JobScheduler参数设置指令
public void scheduleJob(View v) {
if (!ensureJobSchedulerService()) {
return;
}
JobInfo.Builder builder = new JobInfo.Builder(kJobId++, mServiceComponent);
/**
* Specify that this job should be delayed by the provided amount of time.
* Because it doesn't make sense setting this property on a periodic job, doing so will
* throw an {@link java.lang.IllegalArgumentException} when
* {@link android.app.job.JobInfo.Builder#build()} is called.
* @param minLatencyMillis Milliseconds before which this job will not be considered for
* execution.
*/
// 设置最小的延迟时间
// builder.setMinimumLatency(1*1000);
/**
* Set deadline which is the maximum scheduling latency. The job will be run by this
* deadline even if other requirements are not met. Because it doesn't make sense setting
* this property on a periodic job, doing so will throw an
* {@link java.lang.IllegalArgumentException} when
* {@link android.app.job.JobInfo.Builder#build()} is called.
*/
// 设置最大的延迟时间,一旦设置了这个属性,不管其他条件怎么样,jobinfo到了时间就一定会执行。
// builder.setOverrideDeadline(5*1000);
/** Default. 任意网络都可以*/
// public static final int NETWORK_TYPE_NONE = 0;
/** This job requires network connectivity. 任意网络都可以*/
// public static final int NETWORK_TYPE_ANY = 1;
/** This job requires network connectivity that is unmetered. 无线网络接入*/
// public static final int NETWORK_TYPE_UNMETERED = 2;
/** This job requires network connectivity that is not roaming. 非漫游*/
// public static final int NETWORK_TYPE_NOT_ROAMING = 3;
/** This job requires metered connectivity such as most cellular data networks. 移动数据网络 */
// public static final int NETWORK_TYPE_METERED = 4;
// 设置在什么样的网络下启动jobinfo
builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED);
/**
* Specify that to run, the job needs the device to be in idle mode. This defaults to
* false.
* <p>Idle mode is a loose definition provided by the system, which means that the device
* is not in use, and has not been in use for some time. As such, it is a good time to
* perform resource heavy jobs. Bear in mind that battery usage will still be attributed
* to your application, and surfaced to the user in battery stats.</p>
* @param requiresDeviceIdle Whether or not the device need be within an idle maintenance
* window.
*/
// 设置设备需要在空闲的时候,是否启动job
builder.setRequiresDeviceIdle(false);
/**
* Specify that to run this job, the device needs to be plugged in. This defaults to
* false.
* @param requiresCharging Whether or not the device is plugged in.
*/
// 设置是否充电情况下调度
builder.setRequiresCharging(true);
/**
* Set whether or not to persist this job across device reboots.
*
* @param isPersisted True to indicate that the job will be written to
* disk and loaded at boot.
*/
// 设置是否重启后继续调度,注意设置true是需要添加重启权限
builder.setPersisted(false);
/**
* 我设置了充电下且网络连接时才触发onJobStart()的条件
* 注意:上述的条件是与的关系,不是或
*/
Log.d(Constant.TAG, "设置充电下且网络连接的条件");
tv_info.setText("设置充电下且网络连接的条件");
myJobSchedulerService.schedulejob(builder.build());
}
结束Job任务指令
结束所有JOB
/**
* 杀死在这个包里注册的所有的jobinfo
* @param v
*/
public void cancelAllJobs(View v) {
JobScheduler tm = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
/**
* Cancel all jobs that have been registered with the JobScheduler by this package.
*
* 备注:这里会回调onStopJob();
*/
tm.cancelAll();
tv_info.setText("杀死在这个包里注册的所有的jobinfo");
}
结束指定JOB
public void callJobFinished() {
if (mJobParametersMap.size() == 0) {
return ;
}
JobParameters params = mJobParametersMap.valueAt(0);
if (params == null) {
return;
} else {
/**
* Call this to inform the JobManager you've finished executing. This can be called from any
* thread, as it will ultimately be run on your application's main thread. When the system
* receives this message it will release the wakelock being held.
* <p>
* You can specify post-execution behaviour to the scheduler here with
* <code>needsReschedule </code>. This will apply a back-off timer to your job based on
* the default, or what was set with
* {@link android.app.job.JobInfo.Builder#setBackoffCriteria(long, int)}. The original
* requirements are always honoured even for a backed-off job. Note that a job running in
* idle mode will not be backed-off. Instead what will happen is the job will be re-added
* to the queue and re-executed within a future idle maintenance window.
* </p>
*
* @param params Parameters specifying system-provided info about this job, this was given to
* your application in {@link #onStartJob(JobParameters)}.
* @param needsReschedule True if this job should be rescheduled according to the back-off
* criteria specified at schedule-time. False otherwise.
*/
/**
* 告诉JobManager 已经完成了工作,如果第二个参数为false,就是不需要重试这个jobinfo,
* 第二个参数为true,相当于告诉系统任务失败,需要重试,而且与要遵守之前的jobinfo.
*
* 备注:这里不会回调onStopJob();
*/
jobFinished(params, false);
String result = "callJobFinished getJobId = " + params.getJobId();
Log.d(Constant.TAG, result);
if (null != mainActivity) {
mainActivity.onReceivedJobFinished(result);
}
mJobParametersMap.removeAt(0);
}
}
Job回调事件
预设置条件满足事件回调
/**
* 满足Job预设置条件下回调
*/
@Override
public boolean onStartJob(JobParameters jobParameters) {
Log.d(Constant.TAG, "当前满足预设置条件,故触发 onStartJob: " + jobParameters.getJobId());
mCurrentId ++;
mJobParametersMap.put(mCurrentId, jobParameters);
if (null != mainActivity) {
mainActivity.onReceivedStartJob(jobParameters);
}
return true;
}
预设置条件不满足事件回调
/**
* 1.被CancleAll的时候回调
* 2.不满足预设置条件的情况下回调
*/
@Override
public boolean onStopJob(JobParameters jobParameters) {
Log.d(Constant.TAG, "不满足预设置条件, onStopJob : " + jobParameters.getJobId());
int id = mJobParametersMap.indexOfValue(jobParameters);
mJobParametersMap.remove(id);
if (null != mainActivity) {
mainActivity.onReceivedStopJob(jobParameters);
}
return false;
}
结语
个人任务Job本质提供合适的省电场景,让应用执行一些费时且优先级不是很高的事情,比如备份,数据上传等等,当然不建议利用这个特性进行保活,即利用该机制完成应用的频繁启动,这样就违背Google的初衷了