您的位置:首页 > 移动开发 > Android开发

Android 5.0新增任务调度作业jobScheduler

2016-01-19 16:06 393 查看

Android 5.0新增任务调度作业

Android 5.0新增了很多的特性,最典型的就是Material Design,中文名叫材料设计,当然本文不对这个作说明,今天我们要介绍的是另外一个强大的特性:任务调度。

JobScheduler任务调度介绍

5.0提供了一个新的 JobScheduler API,它允许我们通过此为系统定义要在以后的某个时间或在指定的条件下(例如,当设备在充电时)异步运行的作业来优化电池寿命。

作业调度使用场景:

应用具有您可以推迟的非面向用户的工作。

应用具有当插入设备时您希望优先执行的工作。

应用具有需要访问网络或 Wi-Fi 连接的任务。

应用具有您希望作为一个批次定期运行的许多任务(定时任务)。

总之一句话:就是你希望在某个特定时期或特定状态下定期执行某种任务或某些任务的的作业,如:在电量充足,连接wifi下自动更新应用的功能。

用法

它整体是由 JobScheduler 去执行一个 JobInfo,也即工作单元,工作单元由一个 JobInfo 对象进行封装,此对象指定了调度条件。

创建Job Service

需要注意的是:这个是需要你api版本必须在21以上,目前还没有兼容包。

创建一个WifiTaskService 继承 JobService:

public class WifiTaskService extends JobService {
/**
* 当任务开始时会执行onStartJob(JobParameters params)方法,因为这是系统用来触发已经被执行的任务。
* 这个方法返回一个boolean值。如果返回值是false,系统假设这个方法返回时任务已经执行完毕。如果返回值是true,
* 那么系统假定这个任务正要被执行,执行任务的重担就落在了你的肩上。
* 当任务执行完毕时你需要调用jobFinished(JobParameters params, boolean needsRescheduled)来通知系统。
*
* @param params
* @return
*/
@Override
public boolean onStartJob(final JobParameters params) {
Log.i(TAG, "onStartJob:" + params.getJobId());

return true;  //返回false,则系统认为你任务已经执行完毕,当你取消任务时,系统不会调用onStopJob方法,true,则系统认为你任务正要被执行
}

/**
* 当系统接收到一个取消请求时,系统会调用onStopJob(JobParameters params)方法取消正在等待执行的任务。
* 很重要的一点是如果onStartJob(JobParameters params)返回false,那么系统假定在接收到一个取消
* 请求时已经没有正在运行的任务。换句话说,onStopJob(JobParameters params)在这种情况下不会被调用
*
* @param params
* @return
*/
@Override
public boolean onStopJob(JobParameters params) {
Log.i(TAG, "onStopJob:" + params.getJobId());
return false;
}
}


创建一个JobScheduler对象

通过getSystemService( Context.JOB_SCHEDULER_SERVICE )初始化了一个叫做mJobScheduler的JobScheduler对象:

JobScheduler jobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);


当你想创建定时任务时,你可以使用JobInfo.Builder来构建一个JobInfo对象,然后传递给你的Service。JobInfo.Builder接收两个参数,第一个参数是你要运行的任务的标识符,第二个是这个Service组件的类名。

/**
* mJobId  -- 为这个任务提供一个唯一的id,可用于取消该任务,或是创建一个新的任务mJobId相同时,他会更新当前已存在的任务
* jobService --在接收到jobScheduler回调时执行,由我们实现,继承JobService
*/
JobInfo.Builder builder = new JobInfo.Builder( mJobId,
new ComponentName( getPackageName(),
WifiTaskService.class.getName() ) );
//如果schedule方法失败了,它会返回一个小于0的错误码。否则它会我们在JobInfo.Builder中定义的标识id。
int schedule = jobScheduler.schedule(builder);


其他方法说明

setPeriodic(long intervalMillis):设置每隔多少秒执行一次任务

setMinimumLatency(long minLatencyMillis): 这个函数能让你设置任务的延迟执行时间(单位是毫秒),这个函数与setPeriodic(long time)方法不兼容,如果这两个方法同时调用了就会引起异常;

* setOverrideDeadline(long maxExecutionDelayMillis):

这个方法让你可以设置任务最晚的延迟时间。如果到了规定的时间时其他条件还未满足,你的任务也会被启动。与setMinimumLatency(long time)一样,这个方法也会与setPeriodic(long time),同时调用这两个方法会引发异常。

setPersisted(boolean isPersisted):

这个方法告诉系统当你的设备重启之后你的任务是否还要继续执行。

setRequiredNetworkType(int networkType):

这个方法让你这个任务只有在满足指定的网络条件时才会被执行。默认条件是JobInfo.NETWORK_TYPE_NONE,这意味着不管是否有网络这个任务都会被执行。另外两个可选类型,一种是JobInfo.NETWORK_TYPE_ANY,它表明需要任意一种网络才使得任务可以执行。另一种是JobInfo.NETWORK_TYPE_UNMETERED,它表示设备不是蜂窝网络( 比如在WIFI连接时 )时任务才会被执行。

setRequiresCharging(boolean requiresCharging):

这个方法告诉你的应用,只有当设备在充电时这个任务才会被执行。

setRequiresDeviceIdle(boolean requiresDeviceIdle):

这个方法告诉你的任务只有当用户没有在使用该设备且有一段时间没有使用时才会启动该任务。

案例

WifiTaskService.java: 一个简单的循环答应的逻辑

import android.app.job.JobParameters;
import android.app.job.JobService;
import android.content.Intent;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.util.Log;
import android.widget.Toast;

/**
* @author liaojh
* @Description:
* @Date: 2016/1/19 11:46
*/
public class WifiTaskService extends JobService {
private static final String TAG = WifiTaskService.class.getSimpleName();
public static final int MSG_SERVICE_OBJ = 0;

private Handler mJobHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Toast.makeText(getApplicationContext(), "WifiTaskService task running", Toast.LENGTH_SHORT)
.show();
//needsRescheduled参数是让系统知道这个任务是否应该在最处的条件下被重复执行
jobFinished((JobParameters) msg.obj, false);
}
};

/**
* 当任务开始时会执行onStartJob(JobParameters params)方法,因为这是系统用来触发已经被执行的任务。
* 这个方法返回一个boolean值。如果返回值是false,系统假设这个方法返回时任务已经执行完毕。如果返回值是true,
* 那么系统假定这个任务正要被执行,执行任务的重担就落在了你的肩上。
* 当任务执行完毕时你需要调用jobFinished(JobParameters params, boolean needsRescheduled)来通知系统。
*
* @param params
* @return
*/
@Override
public boolean onStartJob(final JobParameters params) {
Log.i(TAG, "onStartJob:" + params.getJobId());

new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 30; i++) {
Log.i(TAG, "excute .... " + i);
SystemClock.sleep(1000);
if (i == 29) {
//                        jobFinished(params, false);
Message message = Message.obtain();
message.obj = params;
message.what = MSG_SERVICE_OBJ;
mJobHandler.sendMessage(message);
}
}
}
}).start();

return true;  //返回false,则系统认为你任务已经执行完毕,当你取消任务时,系统不会调用onStopJob方法,true,则系统认为你任务正要被执行
}

/**
* 当系统接收到一个取消请求时,系统会调用onStopJob(JobParameters params)方法取消正在等待执行的任务。
* 很重要的一点是如果onStartJob(JobParameters params)返回false,那么系统假定在接收到一个取消
* 请求时已经没有正在运行的任务。换句话说,onStopJob(JobParameters params)在这种情况下不会被调用
*
* @param params
* @return
*/
@Override
public boolean onStopJob(JobParameters params) {
Log.i(TAG, "onStopJob:" + params.getJobId());
mJobHandler.removeMessages(MSG_SERVICE_OBJ);
return false;
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommand");
return START_NOT_STICKY;
}
}


MainActivity.java

public class MainActivity extends AppCompatActivity {
private int mJobId = 100;
JobScheduler jobScheduler;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

doSomething();

FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//取消任务
jobScheduler.cancel(mJobId);
}
});
}

private void doSomething() {
/**
* mJobId  -- 为这个任务提供一个唯一的id,可用于取消该任务,或是创建一个新的任务mJobId相同时,他会更新当前已存在的任务
* jobService --在接收到jobScheduler回调时执行,有我们实现
*/
JobInfo uploadTask = new JobInfo.Builder(mJobId,
new ComponentName(getPackageName(), WifiTaskService.class.getName()))
//                  .setPeriodic(60 * 1000)  //每隔一分钟运行一次
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED) //不是蜂窝网络时执行
.setOverrideDeadline(3000) //最多延迟3秒,3秒后执行
.build();

jobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
//如果schedule方法失败了,它会返回一个小于0的错误码。否则它会我们在JobInfo.Builder中定义的标识id。
int schedule = jobScheduler.schedule(uploadTask);
if (schedule < 0 ) {
Toast.makeText(MainActivity.this, "任务执行失败", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(MainActivity.this, "任务执行成功", Toast.LENGTH_SHORT).show();
}
}
}


最后,你需要到AndroidManifest.xml中添加一个service节点让你的应用拥有绑定和使用这个JobService的权限:

<service android:name=".WifiTaskService"
android:permission="android.permission.BIND_JOB_SERVICE"/>


需要注意的是:当任务执行完毕之后,你需要调用jobFinished(JobParameters params, boolean needsRescheduled)来让系统知道这个任务已经结束,系统可以将下一个任务添加到队列中。如果你没有调用jobFinished(JobParameters params, boolean needsRescheduled),你的任务只会执行一次,而应用中的其他任务就不会被执行。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android 任务调度