The official document of JobInfo.Builder explain not so clear!
Here is my exercise to test it, with various combination of requirements. You can try it and correct me if I'm wrong.
MainActivity.java
package com.example.androidjobscheduler;
import java.util.List;
import android.support.v7.app.ActionBarActivity;
import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.content.ComponentName;
import android.os.Bundle;
import android.os.SystemClock;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.Chronometer;
import android.widget.RadioButton;
import android.widget.Toast;
public class MainActivity extends ActionBarActivity {
Chronometer chronometer;
Button btnStartJob, btnCancelJobs;
JobScheduler jobScheduler;
private static final int MYJOBID = 1;
RadioButton optDeadline;
RadioButton optPeriodic;
CheckBox optIsPersisted;
RadioButton optNetworkTypeANY;
RadioButton optNetworkTypeNONE;
RadioButton optNetworkTypeUNMETERED;
CheckBox optRequiresCharging;
CheckBox optRequiresDeviceIdle;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
optDeadline = (RadioButton)findViewById(R.id.optDeadline);
optPeriodic = (RadioButton)findViewById(R.id.optPeriodic);
optIsPersisted = (CheckBox)findViewById(R.id.isPersisted);
optNetworkTypeANY = (RadioButton)findViewById(R.id.optNETWORK_TYPE_ANY);
optNetworkTypeNONE = (RadioButton)findViewById(R.id.optNETWORK_TYPE_NONE);
optNetworkTypeUNMETERED = (RadioButton)findViewById(R.id.optNETWORK_TYPE_UNMETERED);
optRequiresCharging = (CheckBox)findViewById(R.id.requiresCharging);
optRequiresDeviceIdle = (CheckBox)findViewById(R.id.requiresDeviceIdle);
chronometer = (Chronometer)findViewById(R.id.chronometer);
btnStartJob = (Button)findViewById(R.id.startjob);
btnCancelJobs = (Button)findViewById(R.id.canceljobs);
jobScheduler = (JobScheduler)getSystemService(JOB_SCHEDULER_SERVICE);
btnStartJob.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
chronometer.setBase(SystemClock.elapsedRealtime());
chronometer.start();
ComponentName jobService =
new ComponentName(getPackageName(), MyJobService.class.getName());
JobInfo.Builder builder = new JobInfo.Builder(MYJOBID, jobService);
if(optDeadline.isChecked()){
builder.setMinimumLatency(5000);
builder.setOverrideDeadline(7000);
}else{
builder.setPeriodic(10000);
}
/*setPersisted only have an effect if your application
* holds the permission RECEIVE_BOOT_COMPLETED.
* Otherwise an exception will be thrown.
*/
builder.setPersisted(optIsPersisted.isChecked());
if(optNetworkTypeANY.isChecked()){
builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
}else if(optNetworkTypeUNMETERED.isChecked()){
builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED);
}else{
//can skip, it's default
builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_NONE);
}
builder.setRequiresCharging(optRequiresCharging.isChecked());
builder.setRequiresDeviceIdle(optRequiresDeviceIdle.isChecked());
JobInfo jobInfo = builder.build();
int jobId = jobScheduler.schedule(jobInfo);
if(jobScheduler.schedule(jobInfo)>0){
Toast.makeText(MainActivity.this,
"Successfully scheduled job: " + jobId +
"\ngetId(): " + jobInfo.getId() +
"\nisPeriodic(): " + jobInfo.isPeriodic() +
"\nisPersisted(): " + jobInfo.isPersisted() +
"\ngetNetworkType(): " + jobInfo.getNetworkType() +
"\nisRequireCharging(): " + jobInfo.isRequireCharging() +
"\nisRequireDeviceIdle(): " + jobInfo.isRequireDeviceIdle(),
Toast.LENGTH_LONG).show();
}else{
Toast.makeText(MainActivity.this,
"RESULT_FAILURE: " + jobId,
Toast.LENGTH_SHORT).show();
}
}});
btnCancelJobs.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
chronometer.stop();
List<JobInfo> allPendingJobs = jobScheduler.getAllPendingJobs();
String s = "";
for(JobInfo j : allPendingJobs){
int jId = j.getId();
jobScheduler.cancel(jId);
s += "jobScheduler.cancel(" + jId + " )";
}
Toast.makeText(MainActivity.this,
s,
Toast.LENGTH_SHORT).show();
//or
//jobScheduler.cancelAll();
}});
}
}
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.androidjobscheduler.MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://android-er.blogspot.com/"
android:textStyle="bold" />
<Chronometer
android:id="@+id/chronometer"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" />
<RadioGroup
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#A0A0A0" >
<RadioButton
android:id="@+id/optDeadline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="setMinimumLatency(5000ms)/setOverrideDeadline(7000ms)" />
<RadioButton
android:id="@+id/optPeriodic"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="setPeriodic(10000)"
android:checked="true" />
</RadioGroup>
<CheckBox
android:id="@+id/isPersisted"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="isPersisted across device reboots" />
<RadioGroup
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#C0C0C0" >
<RadioButton
android:id="@+id/optNETWORK_TYPE_NONE"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="NETWORK_TYPE_NONE"
android:checked="true" />
<RadioButton
android:id="@+id/optNETWORK_TYPE_ANY"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="NETWORK_TYPE_ANY" />
<RadioButton
android:id="@+id/optNETWORK_TYPE_UNMETERED"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="NETWORK_TYPE_UNMETERED" />
</RadioGroup>
<CheckBox
android:id="@+id/requiresCharging"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="requiresCharging" />
<CheckBox
android:id="@+id/requiresDeviceIdle"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="requiresDeviceIdle" />
<Button
android:id="@+id/startjob"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Start a Job" />
<Button
android:id="@+id/canceljobs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Cancel all Jobs" />
</LinearLayout>
MyJobService.java
package com.example.androidjobscheduler;
import android.app.job.JobParameters;
import android.app.job.JobService;
import android.widget.Toast;
//Require API Level 21
public class MyJobService extends JobService {
public MyJobService() {
}
@Override
public boolean onStartJob(JobParameters params) {
Toast.makeText(this,
"MyJobService.onStartJob() - " +
params.getJobId(),
Toast.LENGTH_SHORT).show();
/*
* True - if your service needs to process
* the work (on a separate thread).
* False - if there's no more work to be done for this job.
*/
return false;
}
@Override
public boolean onStopJob(JobParameters params) {
Toast.makeText(this,
"MyJobService.onStopJob() - " +
params.getJobId(),
Toast.LENGTH_SHORT).show();
return false;
}
}
uses-permission of "android.permission.RECEIVE_BOOT_COMPLETED" and service of ".MyJobService" are needed in AndroidManifest.xml, for builder.setPersisted().
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.androidjobscheduler"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="21"
android:targetSdkVersion="22" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".MyJobService"
android:permission="android.permission.BIND_JOB_SERVICE" />
</application>
</manifest>
Download the files.
I'm very confused as well. I want a periodic job but it has a network requirement.
ReplyDeleteAfter so many tries, turns out that the "setPeriodic" sort of overwrites every single requirement. Now, I have no idea how to achieve what I want