Site icon C1CTech

Android JobScheduler Example

<h3 class&equals;"nolinks"><span style&equals;"color&colon; &num;0000ff&semi;">Introduction<&sol;span><&sol;h3>&NewLine;<p>When working with Android&comma; there will be occasions where you want to run a task at a later point in time or under certain conditions&comma; such as when a device is plugged into a power source or connected to a Wi-Fi network&period; Google has provided a new component known as the <span style&equals;"color&colon; &num;008000&semi;"><strong>JobScheduler<&sol;strong><&sol;span> API to handle this very scenario&period;<&sol;p>&NewLine;<p>Android JobScheduler API is a better choice for scheduling background jobs for your application&period;It improves the battery life by performing similar jobs as batches in the background&period;It is the better alternative for <strong><span style&equals;"color&colon; &num;008000&semi;">AlarmManager<&sol;span><&sol;strong> and <strong><span style&equals;"color&colon; &num;008000&semi;">syncAdapters<&sol;span><&sol;strong>&period;<&sol;p>&NewLine;<p>In this tutorial&comma; you will learn how to use the <strong><span style&equals;"color&colon; &num;008000&semi;">JobScheduler<&sol;span><&sol;strong> API  for running a task in background&period; The <strong><span style&equals;"color&colon; &num;008000&semi;">JobScheduler<&sol;span><&sol;strong> API allows developers to create jobs that execute in the background when certain conditions are met&period;<&sol;p>&NewLine;<p>Get <span style&equals;"color&colon; &num;000080&semi;"><strong>GITHUB<&sol;strong><&sol;span> code from <a href&equals;"https&colon;&sol;&sol;github&period;com&sol;arunk7839&sol;JobSchedulerExample"><strong><span style&equals;"color&colon; &num;00ff00&semi;">here<&sol;span><&sol;strong><&sol;a>&period;<&sol;p>&NewLine;<h3 class&equals;"nolinks"><span style&equals;"color&colon; &num;0000ff&semi;">Creating the Job Service<&sol;span><&sol;h3>&NewLine;<ul>&NewLine;<li>Create a new Android project with a minimum required API of 21&comma; because the <strong><span style&equals;"color&colon; &num;008000&semi;">JobScheduler<&sol;span><&sol;strong> API works only on API level 21 and above&period;<&sol;li>&NewLine;<li>Firstly create a new Java class that extends <strong><span style&equals;"color&colon; &num;008000&semi;">JobService<&sol;span><&sol;strong> class&period; To keep things simple&comma; let&&num;8217&semi;s name it <span style&equals;"color&colon; &num;0000ff&semi;"><strong>JobSchedulerService<&sol;strong><&sol;span> &period;<&sol;li>&NewLine;<li>Now you must override two methods <strong><span style&equals;"color&colon; &num;008000&semi;">onStartJob<&sol;span><span style&equals;"color&colon; &num;008000&semi;">&lpar;JobParameters params&rpar;<&sol;span><&sol;strong> and <strong><span style&equals;"color&colon; &num;008000&semi;">onStopJob&lpar;JobParameters params&rpar;<&sol;span><&sol;strong>&period;<&sol;li>&NewLine;<&sol;ul>&NewLine;<pre style&equals;"padding-left&colon; 30px&semi;"><code>public class JobSchedulerService extends JobService &lbrace;&NewLine;&NewLine; &commat;Override&NewLine; public boolean onStartJob&lpar;JobParameters jobParameters&rpar; &lbrace;&NewLine; &NewLine; return false&semi;&NewLine; &rcub;&NewLine;&NewLine; &commat;Override&NewLine; public boolean onStopJob&lpar;JobParameters params&rpar; &lbrace;&NewLine; return false&semi;&NewLine; &rcub;&NewLine;&rcub;<&sol;code><&sol;pre>&NewLine;<p>&nbsp&semi;<&sol;p>&NewLine;<p><strong><span style&equals;"color&colon; &num;0000ff&semi;">onStartJob&lpar;JobParameters params&rpar;<&sol;span><&sol;strong> &colon;<&sol;p>&NewLine;<ul>&NewLine;<li>This method is called by the system when all the job parameters are met and the time for job execution arrived&period;<&sol;li>&NewLine;<li>You can place your job in this method&period;<&sol;li>&NewLine;<li>you must return a boolean from this method&period;<&sol;li>&NewLine;<li>If the return value is <strong><span style&equals;"color&colon; &num;008000&semi;">false<&sol;span><&sol;strong>&comma; the system assumes that whatever task has run did not take long and is done by the time the method returns&lpar;false&rpar;&period;<&sol;li>&NewLine;<li>Always keep in mind that the  job service runs on your application&&num;8217&semi;s main thread&period; This means that you <em>have to<&sol;em> use another thread&comma; a handler&comma; or an asynchronous task to run longer tasks to not block the main thread&period;<&sol;li>&NewLine;<li>If you place your job in separate thread then you have to return true from the onStartJob&lpar;&rpar; method&period;<&sol;li>&NewLine;<li>If the return value is <span style&equals;"color&colon; &num;008000&semi;"><strong>true<&sol;strong><&sol;span>&comma; then the system assumes that your job is still running in a separate thread and the burden falls on you&comma; the developer&comma; to tell the system when the given task is complete by calling <strong><span style&equals;"color&colon; &num;008000&semi;">jobFinished&lpar;JobParameters params&comma; boolean needsRescheduled&rpar;<&sol;span><&sol;strong>&period;<&sol;li>&NewLine;<li>For the jobFinished&lpar;&rpar; you have to pass two parameters&colon;<&sol;li>&NewLine;<&sol;ul>&NewLine;<ol>&NewLine;<li>Job parameters&period;<&sol;li>&NewLine;<li>Boolean&lpar;return true if you want to re-scheduled the same job again otherwise false&rpar;&period;<&sol;li>&NewLine;<&sol;ol>&NewLine;<p>&nbsp&semi;<&sol;p>&NewLine;<p><strong><span style&equals;"color&colon; &num;0000ff&semi;">onStopJob&lpar;JobParameters params&rpar;<&sol;span><&sol;strong> &colon;<&sol;p>&NewLine;<ul>&NewLine;<li>System called this method if your background job is cancelled before being finished&period;This happens if any of your job parameters are no longer available&period;For example wifi cuts off while downloading a file&period;<&sol;li>&NewLine;<li>You can clear the unfinished job resources from this method&period;<&sol;li>&NewLine;<li>You have to return true from this method if you want to re-scheduled the same job again otherwise return false&period;<&sol;li>&NewLine;<&sol;ul>&NewLine;<p>&nbsp&semi;<&sol;p>&NewLine;<p>Here we will use  <strong><span style&equals;"color&colon; &num;0000ff&semi;">AsynTask<&sol;span><&sol;strong> to run our job in  <span style&equals;"color&colon; &num;008000&semi;"><strong>JobSchedulerService <&sol;strong><&sol;span>class&period;<&sol;p>&NewLine;<pre><code>private static class JobTask extends AsyncTask&lt&semi;JobParameters&comma; Void&comma; JobParameters&gt&semi; &lbrace;&NewLine; private final JobService jobService&semi;&NewLine;&NewLine; public JobTask&lpar;JobService jobService&rpar; &lbrace;&NewLine; this&period;jobService &equals; jobService&semi;&NewLine; &rcub;&NewLine;&NewLine; &commat;Override&NewLine; protected JobParameters doInBackground&lpar;JobParameters&period;&period;&period; params&rpar; &lbrace;&NewLine;&NewLine;<strong><span style&equals;"color&colon; &num;008000&semi;">&sol;&sol;Place your code here<&sol;span><&sol;strong>&NewLine; for&lpar;int i&equals;1&semi;i&lt&semi;&equals;10&semi;i&plus;&plus;&rpar;&NewLine; &lbrace;&NewLine; Log&period;e&lpar;"number"&comma;"num"&plus;i&rpar;&semi;&NewLine; &rcub;&NewLine;&NewLine; return params&lbrack;0&rsqb;&semi;&NewLine; &rcub;&NewLine;&NewLine; &commat;Override&NewLine; protected void onPostExecute&lpar;JobParameters jobParameters&rpar; &lbrace;&NewLine; jobService&period;jobFinished&lpar;jobParameters&comma; false&rpar;&semi;&NewLine; &rcub;&NewLine;&rcub;<&sol;code><&sol;pre>&NewLine;<p>In the <strong><span style&equals;"color&colon; &num;008000&semi;">AsyncTask<&sol;span><&sol;strong>&comma; implement the <strong><span style&equals;"color&colon; &num;008000&semi;">doInBackground&lpar;JobParameters&&num;8230&semi; params&rpar;<&sol;span><&sol;strong>  method  and the <span style&equals;"color&colon; &num;008000&semi;"><strong>onPostExecute&lpar;JobParameters jobParameters&rpar;<&sol;strong><&sol;span>&period;Inside the <span style&equals;"color&colon; &num;008000&semi;"><strong>doInBackground<&sol;strong><&sol;span> method&comma; to keep things simple we will print the numbers from 1 to 10 though this is where you can put the logic of your own task which you want to execute&period;<&sol;p>&NewLine;<p>In <strong><span style&equals;"color&colon; &num;008000&semi;">onPostExecute<&sol;span><&sol;strong> method &comma;when the task is done&comma; you need to call <strong><span style&equals;"color&colon; &num;008000&semi;">jobFinished&lpar;JobParameters params&comma; boolean needsRescheduled&rpar;<&sol;span><&sol;strong> to let the system know that you&&num;8217&semi;re done with that task and now it can begin queuing up the next operation&period; If you don&&num;8217&semi;t do this&comma; your jobs will only run once and your application will not be allowed to perform additional jobs&period;<&sol;p>&NewLine;<p>With the <strong><span style&equals;"color&colon; &num;008000&semi;">AsyncTask<&sol;span><&sol;strong> created&comma; you can go ahead and start implementing the <strong>onStartJob&lpar;JobParameters params&rpar;<&sol;strong> and <strong>onStopJob&lpar;JobParameters params&rpar;<&sol;strong> methods to control your tasks&period; You&&num;8217&semi;ll notice that in the following code snippet&comma; the <strong><span style&equals;"color&colon; &num;008000&semi;">onStartJob&lpar;JobParameters params&rpar;<&sol;span><&sol;strong> method returns true&period; This is because you&&num;8217&semi;re going to use an <strong>AsyncTask<&sol;strong>  to control your operation&comma; which means that it could take longer to finish than the onStartJob&lpar;JobParameters params&rpar; method&period; By returning <strong>true<&sol;strong>&comma; you&&num;8217&semi;re letting the application know that you will manually call the <strong><span style&equals;"color&colon; &num;008000&semi;">jobFinished&lpar;JobParameters params&comma; boolean needsRescheduled&rpar; <&sol;span><&sol;strong>method&period;<&sol;p>&NewLine;<pre><code>&commat;Override&NewLine;public boolean onStartJob&lpar;JobParameters jobParameters&rpar; &lbrace;&NewLine; Toast&period;makeText&lpar;getApplicationContext&lpar;&rpar;&comma; "Job started "&comma; Toast&period;LENGTH&lowbar;LONG&rpar;&period;show&lpar;&rpar;&semi;&NewLine; new JobTask&lpar;this&rpar;&period;execute&lpar;jobParameters&rpar;&semi;&NewLine;&NewLine; return true&semi;&NewLine;&rcub;&NewLine;&NewLine;&commat;Override&NewLine;public boolean onStopJob&lpar;JobParameters params&rpar; &lbrace;&NewLine; return false&semi;&NewLine;&rcub;<&sol;code><&sol;pre>&NewLine;<p>Once you&&num;8217&semi;re done with the Java portion of the <strong><span style&equals;"color&colon; &num;008000&semi;">JobSchedulerService<&sol;span> <&sol;strong>class&comma; you need to go into <strong><span style&equals;"color&colon; &num;008000&semi;"><span class&equals;"skimlinks-unlinked">AndroidManifest&period;xml<&sol;span><&sol;span><&sol;strong> and add a node for the service so that your application has permission to bind and use this class as a <strong><span style&equals;"color&colon; &num;008000&semi;">JobService<&sol;span><&sol;strong>&period;<&sol;p>&NewLine;<&excl;-- WP QUADS Content Ad Plugin v&period; 3&period;0&period;1 -->&NewLine;<div class&equals;"quads-location quads-ad2" id&equals;"quads-ad2" style&equals;"float&colon;none&semi;margin&colon;0px&semi;">&NewLine;&NewLine;<&sol;div>&NewLine;&NewLine;<pre><code>&lt&semi;service android&colon;name&equals;"&period;JobSchedulerService"&NewLine; android&colon;permission&equals;"android&period;permission&period;BIND&lowbar;JOB&lowbar;SERVICE"&NewLine; android&colon;exported&equals;"true"&sol;&gt&semi;<&sol;code><&sol;pre>&NewLine;<h3 class&equals;"nolinks"><span style&equals;"color&colon; &num;0000ff&semi;"> Creating the Job Scheduler<&sol;span><&sol;h3>&NewLine;<p>With <strong><span style&equals;"color&colon; &num;008000&semi;">JobSchedulerService<&sol;span> <&sol;strong>class finished&comma; we can start looking at how your application will interact with the JobScheduler API&period; The first thing you will need to do is create a <strong><span style&equals;"color&colon; &num;008000&semi;">JobScheduler<&sol;span><&sol;strong> object&comma; called <strong><span style&equals;"color&colon; &num;008000&semi;">jobScheduler<&sol;span><&sol;strong> in the sample code&comma; and initialize it by getting an instance of the system service <span style&equals;"color&colon; &num;008000&semi;"><strong>JOB&lowbar;SCHEDULER&lowbar;SERVICE<&sol;strong><&sol;span>&period; In the sample application&comma; this is done in the <strong><span style&equals;"color&colon; &num;008000&semi;">MainActivity<&sol;span> <&sol;strong>class&period;<&sol;p>&NewLine;<pre><code>final JobScheduler jobScheduler &equals;&NewLine; &lpar;JobScheduler&rpar; getSystemService&lpar;Context&period;JOB&lowbar;SCHEDULER&lowbar;SERVICE&rpar;&semi;<&sol;code><&sol;pre>&NewLine;<p>When you want to create your scheduled task&comma; you can use the JobInfo&period;Builder to construct a JobInfo object that gets passed to your service&period; To create a <strong><span style&equals;"color&colon; &num;008000&semi;">JobInfo<&sol;span><&sol;strong> object&comma; <strong><span style&equals;"color&colon; &num;008000&semi;">JobInfo&period;Builder<&sol;span><&sol;strong> accepts two parameters&period; The first is the identifier of the job that you will run and the second is the component name of the service that you will use with the <strong><span style&equals;"color&colon; &num;008000&semi;">JobScheduler<&sol;span><&sol;strong> API&period;<&sol;p>&NewLine;<pre><code>if &lpar;Build&period;VERSION&period;SDK&lowbar;INT &gt&semi;&equals; Build&period;VERSION&lowbar;CODES&period;N&rpar; &lbrace;&NewLine; jobInfo &equals; new JobInfo&period;Builder&lpar;JOB&lowbar;ID&comma; new ComponentName&lpar;this&comma; JobSchedulerService&period;class&rpar;&rpar;&NewLine; &period;setPeriodic&lpar;15&ast;60&ast;1000&comma;7&ast;60&ast;1000&rpar;&NewLine; &period;build&lpar;&rpar;&semi;&NewLine;&NewLine;&rcub; else&NewLine;&lbrace;&NewLine; jobInfo &equals; new JobInfo&period;Builder&lpar;JOB&lowbar;ID&comma; new ComponentName&lpar;this&comma; JobSchedulerService&period;class&rpar;&rpar;&NewLine; &period;setPeriodic&lpar;60&ast;1000&rpar;&NewLine; &period;build&lpar;&rpar;&semi;&NewLine;&rcub;<&sol;code><&sol;pre>&NewLine;<p>This builder allows you to set many different options for controlling when your job will execute&period; The following code snippet shows how you could set your task to run periodically every one minute&period;It works well in Lollipop &amp&semi; Marshmallow only&period;<&sol;p>&NewLine;<pre><code>jobInfo&period;setPeriodic&lpar;60&ast;1000&rpar;&semi;<&sol;code><&sol;pre>&NewLine;<ul>&NewLine;<li><strong><span style&equals;"color&colon; &num;0000ff&semi;">setPeriodic&lpar;long intervalMillis&rpar;<&sol;span><&sol;strong> &colon; Specify that this job should recur with the provided interval&comma; not more than once per period&period; You have no control over when within this interval this job will be executed&comma;only the guarantee that it will be executed at most once within this interval&period;<&sol;li>&NewLine;<&sol;ul>&NewLine;<p>For Nougat and above we have to write the below code&colon;<&sol;p>&NewLine;<pre><code>jobInfo&period;setPeriodic&lpar;15&ast;60&ast;1000&comma;7&ast;60&ast;1000&rpar;<&sol;code><&sol;pre>&NewLine;<ul>&NewLine;<li><strong><span style&equals;"color&colon; &num;0000ff&semi;">setPeriodic&lpar;long intervalMillis&comma;long flexMillis&rpar;<&sol;span><&sol;strong> &colon; This method accepts 2 parameters &colon;<br &sol;>&NewLine;<code>intervalMs<&sol;code><strong class&equals;"markup--strong markup--p-strong"> <&sol;strong>The job should run at most once every intervalMs&period; The minimum value is 15min&period;<br &sol;>&NewLine;<code>flexMs<&sol;code> How close to the end of the period the job should run&period; The minimum value is 5min&period;<&sol;li>&NewLine;<&sol;ul>&NewLine;<p>So our task will run every 15 minutes&period; And since our flex parameter is set to 7 minutes the library will determine the best moment between 8th and 15th minute to execute the <strong><span style&equals;"color&colon; &num;008000&semi;">JobSchedulerService<&sol;span><&sol;strong>&period;<&sol;p>&NewLine;<p>Other methods include&colon;<&sol;p>&NewLine;<ul>&NewLine;<li><strong><span style&equals;"color&colon; &num;0000ff&semi;">setMinimumLatency&lpar;long minLatencyMillis&rpar;<&sol;span><&sol;strong> &colon; This makes your job not launch until the stated number of milliseconds have passed&period; This is incompatible with<strong><span style&equals;"color&colon; &num;008000&semi;"> setPeriodic&lpar;long time&rpar;<&sol;span><&sol;strong> and <em>will<&sol;em> cause an exception to be thrown if they are both used&period;<&sol;li>&NewLine;<li style&equals;"list-style-type&colon; none&semi;"><&sol;li>&NewLine;<li><span style&equals;"color&colon; &num;0000ff&semi;"><strong>setOverrideDeadline&lpar;long maxExecutionDelayMillis&rpar; <&sol;strong><&sol;span>&colon; This will set a deadline for your job&period; Even if other requirements are not met&comma; your task will start approximately when the stated time has passed&period; Like <span style&equals;"color&colon; &num;008000&semi;"><strong>setMinimumLatency&lpar;long time&rpar;<&sol;strong>&comma;<&sol;span> this function is mutually exclusive with <strong><span style&equals;"color&colon; &num;008000&semi;">setPeriodic&lpar;long time&rpar;<&sol;span><&sol;strong> and <em>will <&sol;em>cause an exception to be thrown if they are both used&period;<&sol;li>&NewLine;<li style&equals;"list-style-type&colon; none&semi;"><&sol;li>&NewLine;<li><strong><span style&equals;"color&colon; &num;0000ff&semi;">setPersisted&lpar;boolean isPersisted&rpar; <&sol;span><&sol;strong>&colon; This function tells the system whether your task should continue to exist after the device has been rebooted&period;<&sol;li>&NewLine;<li style&equals;"list-style-type&colon; none&semi;"><&sol;li>&NewLine;<li><strong><span style&equals;"color&colon; &num;0000ff&semi;">setRequiredNetworkType&lpar;int networkType&rpar; <&sol;span><&sol;strong>&colon; This function will tell your job that it can only start if the device is on a specific kind of network&period; The default is <strong><span style&equals;"color&colon; &num;008000&semi;">JobInfo&period;NETWORK&lowbar;TYPE&lowbar;NONE<&sol;span><&sol;strong>&comma; meaning that the task can run whether there is network connectivity or not&period; The other two available types are <strong><span style&equals;"color&colon; &num;008000&semi;">JobInfo&period;NETWORK&lowbar;TYPE&lowbar;ANY<&sol;span><&sol;strong>&comma; which requires some type of network connection available for the job to run&comma; and <strong><span style&equals;"color&colon; &num;008000&semi;">JobInfo&period;NETWORK&lowbar;TYPE&lowbar;UNMETERED<&sol;span><&sol;strong>&comma; which requires that the device be on a non-cellular network&period;<&sol;li>&NewLine;<li><strong><span style&equals;"color&colon; &num;0000ff&semi;">setRequiresCharging&lpar;boolean requiresCharging&rpar; <&sol;span><&sol;strong>&colon; Using this function will tell your application that the job should not start until the device has started charging&period;<&sol;li>&NewLine;<li><strong><span style&equals;"color&colon; &num;0000ff&semi;">setRequiresDeviceIdle&lpar;boolean requiresDeviceIdle&rpar; <&sol;span><&sol;strong>&colon; This tells your job to not start unless the user is not using their device and they have not used it for some time&period;<&sol;li>&NewLine;<&sol;ul>&NewLine;<p>Once the preferred conditions are stated&comma; you can build the <strong><span style&equals;"color&colon; &num;008000&semi;">JobInfo<&sol;span><&sol;strong> object and send it to your <strong><span style&equals;"color&colon; &num;008000&semi;">JobScheduler<&sol;span><&sol;strong> object as shown below&period;<&sol;p>&NewLine;<div>&NewLine;<pre><code>jobScheduler&period;schedule&lpar;jobInfo&rpar;&semi;<&sol;code><&sol;pre>&NewLine;<p>We can also check whether the schedule fails or not by writting below code&colon;<&sol;p>&NewLine;<&sol;div>&NewLine;<div class&equals;"line number1 index0 alt2">&NewLine;<pre><code>if&lpar; jobScheduler&period;schedule&lpar; builder&period;build&lpar;&rpar; &rpar; &lt&semi;&equals; 0 &rpar; &lbrace;&NewLine;    &sol;&sol;If something goes wrong&NewLine; &rcub;<&sol;code><&sol;pre>&NewLine;<&sol;div>&NewLine;<div>&NewLine;<p>You&&num;8217&semi;ll notice that the <strong><span style&equals;"color&colon; &num;008000&semi;">schedule<&sol;span><&sol;strong> operation returns an integer&period; If <strong><span style&equals;"color&colon; &num;008000&semi;">schedule<&sol;span><&sol;strong> fails&comma; it will return a value of zero or less&comma; corresponding to an error code&period; Otherwise it will return the job identifier that we defined in the<span style&equals;"color&colon; &num;008000&semi;"><strong> JobInfo&period;Builder<&sol;strong><&sol;span>&period;<&sol;p>&NewLine;<p>If your application requires that you stop a specific or all jobs&comma; you can do so by calling <strong><span style&equals;"color&colon; &num;008000&semi;">cancel&lpar;int jobId&rpar;<&sol;span><&sol;strong> or <strong><span style&equals;"color&colon; &num;008000&semi;">cancelAll<&sol;span><&sol;strong>&lpar;&rpar; on the <strong><span style&equals;"color&colon; &num;008000&semi;">JobScheduler <&sol;span><&sol;strong><span style&equals;"color&colon; &num;000000&semi;">object<&sol;span>&period;<&sol;p>&NewLine;<pre><code>jobScheduler&period;cancel&lpar;JOB&lowbar;ID&rpar;&semi;<&sol;code><&sol;pre>&NewLine;<pre><code>jobScheduler&period;cancelAll&lpar;&rpar;&semi;<&sol;code><&sol;pre>&NewLine;<div>&NewLine;<div id&equals;"highlighter&lowbar;385686" class&equals;"syntaxhighlighter noskimlinks noskimwords java"><&sol;div>&NewLine;<&sol;div>&NewLine;<p>You should now be able to use the <span style&equals;"color&colon; &num;008000&semi;"><strong>JobScheduler<&sol;strong><&sol;span> API with your own applications to batch jobs and run background operations&period;<&sol;p>&NewLine;<&sol;div>&NewLine;&NewLine;

Exit mobile version