JobIntentService Android Example
What is JobIntentService?
Helper for processing work that has been enqueued for a job/service. When running on Android O
or later, the work will be dispatched as a job via JobScheduler.enqueue
. When running on older versions of the platform, it will use Context.startService
.
You must publish your subclass in your manifest for the system to interact with. This should be published as a JobService
, as described for that class, since on O and later platforms it will be executed that way.
Use enqueueWork(Context, Class, int, Intent)
to enqueue new work to be dispatched to and handled by your service. It will be executed in onHandleWork(Intent)
.
One of Android’s greatest strengths is its ability to use system resources in the background regardless app execution. sometimes it became the behaviour to use system resources excessively.
Checkout Background Execution Limits in Android O
Lets Start
IntentService.class is an extensively used service class in Android because of its simplicity and robust in nature. Since the release of Oreo, made things more difficult for developers to use this class in a full swing for their applications. For those who are relied on IntentService class, from oreo onwards you cannot simply use this class. I was also searching for an exact and efficient alternative for this class so that I can change old intentservice class to that. The search ended up in JobIntentService which is exactly does the same job of IntentService by using new Job APIs of oreo. This class is available in the support library of SDK 26.
Implementation of JobIntentService class is a simple process. Also, You can easily migrate from IntentServiceClass to JobIntentServiceClass.For device targeting SDK 26 or later, This class’ works are dispatched via JobScheduler class and for SDK 25 or below devices, It uses Context.startService() (Same as in IntentService). First, compile the dependency on your app level gradle.
implementation 'com.android.support:support-compat:27.0.0'
or later version
Steps to implement JobIntentService
1. Create a subclass of JobIntentService
2. Override onHandleWork() method
3. Expose enqueueWork() method
4. Write code in Manifest file
- For Pre-Oreo devices
- add in Manifest WAKE-LOCK permission
- For Oreo device or above
- Allow JobIntentService to user JobScheduler API
- Declare android.premssion.BIND_JOb_SERVICE
1) Create a JobService.java extends JobIntentService
private static final String TAG = JobService.class.getSimpleName();
public static final String RECEIVER = "receiver";
public static final int SHOW_RESULT = 123;
/**
* Result receiver object to send results
*/
private ResultReceiver mResultReceiver;
/**
* Unique job ID for this service.
*/
static final int DOWNLOAD_JOB_ID = 1000;
/**
* Actions download
*/
private static final String ACTION_DOWNLOAD = "action.DOWNLOAD_DATA";
/**
* Convenience method for enqueuing work in to this service.
*/
public static void enqueueWork(Context context, ServiceResultReceiver workerResultReceiver) {
Intent intent = new Intent(context, JobService.class);
intent.putExtra(RECEIVER, workerResultReceiver);
intent.setAction(ACTION_DOWNLOAD);
enqueueWork(context, JobService.class, DOWNLOAD_JOB_ID, intent);
}
@SuppressLint("DefaultLocale")
@Override
protected void onHandleWork(@NonNull Intent intent) {
Log.d(TAG, "onHandleWork() called with: intent = [" + intent + "]");
if (intent.getAction() != null) {
switch (intent.getAction()) {
case ACTION_DOWNLOAD:
mResultReceiver = intent.getParcelableExtra(RECEIVER);
for(int i=0;i<10;i++){
try {
Thread.sleep(1000);
Bundle bundle = new Bundle();
bundle.putString("data",String.format("Showing From JobIntent Service %d", i));
mResultReceiver.send(SHOW_RESULT, bundle);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
break;
}
}
}
2) Add WAKELOCK Permission to Manifest.xml
<uses-permission android:name="android.permission.WAKE_LOCK" />
3) Add JobIntentService class to Manifest.xml
<service
android:name=".JobService"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="true"/>
4) Create a ServiceResultReceiver.java to communicate with Activity from JobIntentService
private Receiver mReceiver;
/**
* Create a new ResultReceive to receive results. Your
* {@link #onReceiveResult} method will be called from the thread running
* <var>handler</var> if given, or from an arbitrary thread if null.
*
* @param handler the handler object
*/
public ServiceResultReceiver(Handler handler) {
super(handler);
}
public void setReceiver(Receiver receiver) {
mReceiver = receiver;
}
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
if (mReceiver != null) {
mReceiver.onReceiveResult(resultCode, resultData);
}
}
public interface Receiver {
void onReceiveResult(int resultCode, Bundle resultData);
}
5) Create MainActivity.java to enqueue work to JobIntentService, Initialise the ServiceResultReceiver, Show data from the Service
public class MainActivity extends AppCompatActivity implements ServiceResultReceiver.Receiver {
private ServiceResultReceiver mServiceResultReceiver;
private TextView mTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mServiceResultReceiver = new ServiceResultReceiver(new Handler());
mServiceResultReceiver.setReceiver(this);
mTextView = findViewById(R.id.textView);
showDataFromBackground(MainActivity.this, mServiceResultReceiver);
}
private void showDataFromBackground(MainActivity mainActivity, ServiceResultReceiver mResultReceiver) {
JobService.enqueueWork(mainActivity, mResultReceiver);
}
public void showData(String data) {
mTextView.setText(String.format("%s\n%s", mTextView.getText(), data));
}
@Override
public void onReceiveResult(int resultCode, Bundle resultData) {
switch (resultCode) {
case SHOW_RESULT:
if (resultData != null) {
showData(resultData.getString("data"));
}
break;
}
}
}
Download source code from Github
For any questions or suggestions, please leave comments.
Thank you Happy Coding