Android 5.0的排程作業JobScheduler
Android 5.0 提供了一個新的 JobScheduler
API,它允許您通過為系統定義要在以後的某個時間或在指定的條件下(例如,當裝置在充電時)非同步執行的作業來優化電池壽命。
首先看一下官方JobScheduler的API https://developer.android.com/reference/android/app/job/JobScheduler.html
This is an API for scheduling various types of jobs against the framework that will be executed in your application's own process.
這是一個API排程框架,將在您的應用程式的程式中執行的工作。
See JobInfo
for
more description of the types of jobs that can be run and how to construct them. You will construct these JobInfo objects and pass them to the JobScheduler with schedule(JobInfo)
.
When the criteria declared are met, the system will execute this job on your application's JobService
.
You identify which JobService is meant to execute the logic for your job when you create the JobInfo with JobInfo.Builder(int,
android.content.ComponentName)
.
看到Jobinfo的更多的描述型別的工作,可以執行,以及如何構建。你可以構造這些JobInfo物件,並且使用schedule(JobInfo)在JobScheduler。
當符合標準宣告,系統將執行排程在你的應用程式Jobservice。
The framework will be intelligent about when you receive your callbacks, and attempt to batch and defer them as much as possible. Typically if you don't specify a deadline on your job, it can be run at any moment depending on the current state of the JobScheduler's internal queue, however it might be deferred as long as until the next time the device is connected to a power source.
You do not instantiate this class directly; instead, retrieve it through Context.getSystemService(Context.JOB_SCHEDULER_SERVICE)
.
作業排程在下列情況下非常有用:
- 應用具有您可以推遲的非面向使用者的工作。
- 應用具有當插入裝置時您希望優先執行的工作。
- 應用具有需要訪問網路或 Wi-Fi 連線的任務。
- 應用具有您希望作為一個批次定期執行的許多工。
工作單元由一個 JobInfo
物件進行封裝。此物件指定了排程條件。官方的API如下
Public Methods | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
int |
describeContents() Describe the kinds of special objects contained in this Parcelable's marshalled representation.
|
||||||||||
int |
getBackoffPolicy() One of either
BACKOFF_POLICY_EXPONENTIAL ,
or BACKOFF_POLICY_LINEAR ,
depending on which criteria you set when creating this job. |
||||||||||
PersistableBundle |
getExtras() Bundle of extras which are returned to your application at execution time.
|
||||||||||
int |
getId() Unique job id associated with this class.
|
||||||||||
long |
getInitialBackoffMillis() The amount of time the JobScheduler will wait before rescheduling a failed job.
|
||||||||||
long |
getIntervalMillis() Set to the interval between occurrences of this job.
|
||||||||||
long | getMaxExecutionDelayMillis() | ||||||||||
long |
getMinLatencyMillis() Set for a job that does not recur periodically, to specify a delay after which the job will be eligible for execution.
|
||||||||||
int | getNetworkType() | ||||||||||
ComponentName |
getService() Name of the service endpoint that will be called back into by the JobScheduler.
|
||||||||||
boolean |
isPeriodic() Track whether this job will repeat with a given period.
|
||||||||||
boolean | isPersisted() | ||||||||||
boolean |
isRequireCharging() Whether this job needs the device to be plugged in.
|
||||||||||
boolean |
isRequireDeviceIdle() Whether this job needs the device to be in an Idle maintenance window.
|
||||||||||
String |
toString() Returns a string containing a concise, human-readable description of this object.
|
||||||||||
void |
writeToParcel(Parcel out,
int flags) Flatten this object in to a Parcel.
|
使用 JobInfo.Builder
類配置排程的任務應當如何執行。您可以將任務排程為在特定的條件下執行,例如:
- 當裝置充電時啟動
- 當裝置連線到不限流量網路時啟動
- 當裝置空閒時啟動
- 在特定的截止期限之前或以最小的延遲完成
例如,您可以新增如下程式碼以在不限流量網路上執行您的任務:
JobInfo uploadTask = new JobInfo.Builder(mJobId,
mServiceComponent /* JobService component */)
.setRequiredNetworkCapabilities(JobInfo.NetworkType.UNMETERED)
.build();
JobScheduler jobScheduler =
(JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
jobScheduler.schedule(uploadTask);
如果裝置具有穩定的電源(也就是說,它已插入了 2 分鐘以上並且電池處於健康水平),則系統將執行任何已就緒可執行的已排程作業,即使作業的截止期限尚未到期也是如此。
這裡可以在看一下官方給出的 JobService API
Entry point for the callback from the JobScheduler
.
This is the base class that handles asynchronous requests that were previously scheduled. You are responsible for overriding onStartJob(JobParameters)
,
which is where you will implement your job logic.
This service executes each incoming job on a Handler
running
on your application's main thread. This means that you must offload your execution logic to another thread/handler/AsyncTask
of
your choosing. Not doing so will result in blocking any future callbacks from the JobManager - specifically onStopJob(android.app.job.JobParameters)
,
which is meant to inform you that the scheduling requirements are no longer being met.
所提供的方法如下
final void |
jobFinished(JobParameters params,
boolean needsReschedule) Callback to inform the JobManager you've finished executing. 當完成執行後,通知排程管理器
|
abstract boolean |
onStartJob(JobParameters params) Override this method with the callback logic for your job.
|
abstract boolean |
onStopJob(JobParameters params) This method is called if the system has determined that you must stop execution of your job even before you've had a chance to call
jobFinished(JobParameters,
boolean) . |
下面可以看一下官方給出的一個sample
執行效果如下
Activity如下
/*
* Copyright 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.jobscheduler;
import android.app.Activity;
import android.app.job.JobInfo;
import android.app.job.JobParameters;
import android.app.job.JobScheduler;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import android.text.TextUtils;
import android.view.View;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.TextView;
import android.widget.Toast;
import com.example.android.jobscheduler.service.TestJobService;
public class MainActivity extends Activity {
private static final String TAG = "MainActivity";
public static final int MSG_UNCOLOUR_START = 0;
public static final int MSG_UNCOLOUR_STOP = 1;
public static final int MSG_SERVICE_OBJ = 2;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.sample_main);
Resources res = getResources();
defaultColor = res.getColor(R.color.none_received);
startJobColor = res.getColor(R.color.start_received);
stopJobColor = res.getColor(R.color.stop_received);
// Set up UI.
mShowStartView = (TextView) findViewById(R.id.onstart_textview);
mShowStopView = (TextView) findViewById(R.id.onstop_textview);
mParamsTextView = (TextView) findViewById(R.id.task_params);
mDelayEditText = (EditText) findViewById(R.id.delay_time);
mDeadlineEditText = (EditText) findViewById(R.id.deadline_time);
mWiFiConnectivityRadioButton = (RadioButton) findViewById(R.id.checkbox_unmetered);
mAnyConnectivityRadioButton = (RadioButton) findViewById(R.id.checkbox_any);
mRequiresChargingCheckBox = (CheckBox) findViewById(R.id.checkbox_charging);
mRequiresIdleCheckbox = (CheckBox) findViewById(R.id.checkbox_idle);
mServiceComponent = new ComponentName(this, TestJobService.class);
// Start service and provide it a way to communicate with us.
Intent startServiceIntent = new Intent(this, TestJobService.class);
startServiceIntent.putExtra("messenger", new Messenger(mHandler));
startService(startServiceIntent);
}
// UI fields.
int defaultColor;
int startJobColor;
int stopJobColor;
private TextView mShowStartView;
private TextView mShowStopView;
private TextView mParamsTextView;
private EditText mDelayEditText;
private EditText mDeadlineEditText;
private RadioButton mWiFiConnectivityRadioButton;
private RadioButton mAnyConnectivityRadioButton;
private CheckBox mRequiresChargingCheckBox;
private CheckBox mRequiresIdleCheckbox;
ComponentName mServiceComponent;
/** Service object to interact scheduled jobs. */
TestJobService mTestService;
private static int kJobId = 0;
Handler mHandler = new Handler(/* default looper */) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_UNCOLOUR_START:
mShowStartView.setBackgroundColor(defaultColor);
break;
case MSG_UNCOLOUR_STOP:
mShowStopView.setBackgroundColor(defaultColor);
break;
case MSG_SERVICE_OBJ:
mTestService = (TestJobService) msg.obj;
mTestService.setUiCallback(MainActivity.this);
}
}
};
private boolean ensureTestService() {
if (mTestService == null) {
Toast.makeText(MainActivity.this, "Service null, never got callback?",
Toast.LENGTH_SHORT).show();
return false;
}
return true;
}
/**
* UI onclick listener to schedule a job. What this job is is defined in
* TestJobService#scheduleJob().
*/
public void scheduleJob(View v) {
if (!ensureTestService()) {
return;
}
JobInfo.Builder builder = new JobInfo.Builder(kJobId++, mServiceComponent);
String delay = mDelayEditText.getText().toString();
if (delay != null && !TextUtils.isEmpty(delay)) {
builder.setMinimumLatency(Long.valueOf(delay) * 1000);
}
String deadline = mDeadlineEditText.getText().toString();
if (deadline != null && !TextUtils.isEmpty(deadline)) {
builder.setOverrideDeadline(Long.valueOf(deadline) * 1000);
}
boolean requiresUnmetered = mWiFiConnectivityRadioButton.isChecked();
boolean requiresAnyConnectivity = mAnyConnectivityRadioButton.isChecked();
if (requiresUnmetered) {
builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED);
} else if (requiresAnyConnectivity) {
builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
}
builder.setRequiresDeviceIdle(mRequiresIdleCheckbox.isChecked());
builder.setRequiresCharging(mRequiresChargingCheckBox.isChecked());
mTestService.scheduleJob(builder.build());
}
/**
* cancel All jobs
* @param v
*/
public void cancelAllJobs(View v) {
JobScheduler tm =
(JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
tm.cancelAll();
}
/**
* UI onclick listener to call jobFinished() in our service.
*/
public void finishJob(View v) {
if (!ensureTestService()) {
return;
}
mTestService.callJobFinished();
mParamsTextView.setText("");
}
/**
* Receives callback from the service when a job has landed
* on the app. Colours the UI and post a message to
* uncolour it after a second.
*/
public void onReceivedStartJob(JobParameters params) {
mShowStartView.setBackgroundColor(startJobColor);
Message m = Message.obtain(mHandler, MSG_UNCOLOUR_START);
mHandler.sendMessageDelayed(m, 1000L); // uncolour in 1 second.
mParamsTextView.setText("Executing: " + params.getJobId() + " " + params.getExtras());
}
/**
* Receives callback from the service when a job that
* previously landed on the app must stop executing.
* Colours the UI and post a message to uncolour it after a
* second.
*/
public void onReceivedStopJob() {
mShowStopView.setBackgroundColor(stopJobColor);
Message m = Message.obtain(mHandler, MSG_UNCOLOUR_STOP);
mHandler.sendMessageDelayed(m, 2000L); // uncolour in 1 second.
mParamsTextView.setText("");
}
}
然後新建一個類繼承JobService
/*
* Copyright 2014 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.jobscheduler.service;
import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.app.job.JobParameters;
import android.app.job.JobService;
import android.content.Context;
import android.content.Intent;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import com.example.android.jobscheduler.MainActivity;
import java.util.LinkedList;
/**
* Service to handle callbacks from the JobScheduler. Requests scheduled with the JobScheduler
* ultimately land on this service's "onStartJob" method. Currently all this does is post a message
* to the app's main activity to change the state of the UI.
*/
public class TestJobService extends JobService {
private static final String TAG = "SyncService";
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "Service created");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i(TAG, "Service destroyed");
}
/**
* When the app's MainActivity is created, it starts this service. This is so that the
* activity and this service can communicate back and forth. See "setUiCalback()"
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Messenger callback = intent.getParcelableExtra("messenger");
Message m = Message.obtain();
m.what = MainActivity.MSG_SERVICE_OBJ;
m.obj = this;
try {
callback.send(m);
} catch (RemoteException e) {
Log.e(TAG, "Error passing service object back to activity.");
}
return START_NOT_STICKY;
}
@Override
public boolean onStartJob(JobParameters params) {
// We don't do any real 'work' in this sample app. All we'll
// do is track which jobs have landed on our service, and
// update the UI accordingly.
jobParamsMap.add(params);
if (mActivity != null) {
mActivity.onReceivedStartJob(params);
}
Log.i(TAG, "on start job: " + params.getJobId());
return true;
}
@Override
public boolean onStopJob(JobParameters params) {
// Stop tracking these job parameters, as we've 'finished' executing.
jobParamsMap.remove(params);
if (mActivity != null) {
mActivity.onReceivedStopJob();
}
Log.i(TAG, "on stop job: " + params.getJobId());
return true;
}
MainActivity mActivity;
private final LinkedList<JobParameters> jobParamsMap = new LinkedList<JobParameters>();
public void setUiCallback(MainActivity activity) {
mActivity = activity;
}
/** Send job to the JobScheduler. */
public void scheduleJob(JobInfo t) {
Log.d(TAG, "Scheduling job");
JobScheduler tm =
(JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
tm.schedule(t);
}
/**
* Not currently used, but as an exercise you can hook this
* up to a button in the UI to finish a job that has landed
* in onStartJob().
*/
public boolean callJobFinished() {
JobParameters params = jobParamsMap.poll();
if (params == null) {
return false;
} else {
jobFinished(params, false);
return true;
}
}
}
轉自:http://blog.csdn.net/cuiran/article/details/42805057
相關文章
- 實現Quartz.NET的HTTP作業排程quartzHTTP
- oracle排程程式作業dbms_schedulerOracle
- oracle使用DBMS_SCHEDULER排程作業Oracle
- Apache Oozie 教程:使用 Oozie 排程 Hadoop 作業ApacheHadoop
- 批處理作業排程-分支界限法
- 作業系統之排程演算法作業系統演算法
- async-await:協作排程 vs 搶佔排程AI
- 作業系統精髓設計原理 程式排程作業系統
- Android 中的定時任務排程Android
- Elastic-job實戰(分散式作業排程框架)AST分散式框架
- .NET Core Hangfire週期性作業排程問題
- 【作業系統】4.程序排程演算法作業系統演算法
- 作業系統4——處理機排程與死鎖作業系統
- 使用持續整合工具Jenkins進行Kettle作業排程Jenkins
- 分散式後臺作業排程器JobRunr介紹 - JAXenter分散式
- Android系統“資源排程框架”Android框架
- 作業系統綜合題之“採用實時排程,可排程的限制條件和可排程的最大X值是是多少ms的CPU時間”作業系統
- 使用 K8s 進行作業排程實戰分享K8S
- 課程排課系統:智慧排課+線上約課+直播上課+作業打卡!
- Flink排程之排程器、排程策略、排程模式模式
- 使用FUTURE 中的訊息避免計劃排程的批處理作業 - CodeOpinion
- Oracle排程作業引起的空間驟增問題處理記錄Oracle
- ORA-27492 無法執行作業,排程程式不可用
- Volcano:在離線作業混部管理平臺,實現智慧資源管理和作業排程
- 【作業系統】磁碟的四種基本排程演算法(圖表說明)作業系統演算法
- 多機器人協作排程問題機器人
- 作業排程中介軟體 Elastic-Job-Cloud 原始碼分析 —— 高可用ASTCloud原始碼
- 排程器簡介,以及Linux的排程策略Linux
- Pod的排程是由排程器(kube-scheduler)
- ASP.NET Core託管執行Quartz.NET作業排程詳解ASP.NETquartz
- TKE 使用者故事 | 作業幫 Kubernetes 原生排程器優化實踐優化
- 系統設計:如何設計一個分散式作業排程器 ?- Rakshesh分散式
- Yarn的排程器Yarn
- ucore作業系統學習(六) ucore lab6執行緒排程器作業系統執行緒
- 行業分析| 排程行業未來趨勢行業
- 作業系統啟動的過程作業系統
- 程式排程之最短作業優先
- kubernetes 排程
- Ubuntu系統定時作業無效果的排錯Ubuntu