In this tutorial, we’ll be discussing one of the fundamental components of the Android framework, namely IntentService. We’ll be developing an Android IntentService application using BroadcastReceiver.
Android IntentService
We’ve discussed Android Service in earlier tutorial. An IntentService
extends the Service
class.
Both Services and IntentServices are used to run operations that do not need a UI.
An IntentService is used to run data sequentially. Each time you call an Intent to the Service, that operation would be added into the queue.
Android IntentService vs Service
.tg {border-collapse:collapse;border-spacing:0;border-color:#999;}
.tg td{font-family:Arial, sans-serif;font-size:14px;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:#999;color:#444;background-color:#F7FDFA;}
.tg th{font-family:Arial, sans-serif;font-size:14px;font-weight:normal;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:#999;color:#fff;background-color:#26ADE4;}
.tg .tg-yw4l{vertical-align:top}
.tg .tg-6k2t{background-color:#D2E4FC;vertical-align:top}
A Service is invoked using startService() | An IntentService is invoked using Intent. |
---|---|
A Service can be invoked from any thread. | An IntentService can in invoked from the Main thread only. |
A Service runs background operations on the Main Thread of the Application by default. Hence it can block your Application’s UI. | An IntentService creates a separate worker thread to run background operations. |
A Service invoked multiple times would create multiple instances. | An IntentService invoked multiple times won’t create multiple instances. |
A service needs to be stopped using stopSelf() or stopService() | An IntentService automatically stops after the queue is completed. No need to trigger stopService() or stopSelf(). |
Android service can run parallel operations. | In an IntentService, multiple intent calls are automatically Queued and they would be executed sequentially. An IntentService cannot run parallel operation like a Service. |
In a service, the onHandleIntent()
method gets invoked when the intent is passed from the activity.
BroadcastReceivers are used to transfer messages across applications or between a service and an activity.
To transfer data between a service and an activity we need to use a LocalBroadcastManager
.
LocalBroadcastManager class comes with the support library and is used to transfer data locally only.
You cannot transfer data outside the application.
In the following section, we’ll create an application that passes a string to the IntentService which returns it to the Activity after a delay. Thanks to IntentService, this happens sequentially.
Android IntentService Example Project Structure
Layout code
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<EditText
android:id="@+id/inputText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:hint="Enter your message"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="Send Message"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/inputText" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="Message received from the Service is:n"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
The code for the MainActivity.java class is given below:
package com.journaldev.androidintentservices;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
TextView textView;
Button button;
EditText editText;
MyReceiver myReceiver;
public static final String FILTER_ACTION_KEY = "any_key";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.textView);
button = findViewById(R.id.button);
editText = findViewById(R.id.inputText);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String message = editText.getText().toString();
Intent intent = new Intent(MainActivity.this, MyService.class);
intent.putExtra("message", message);
startService(intent);
}
});
}
private void setReceiver() {
myReceiver = new MyReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(FILTER_ACTION_KEY);
LocalBroadcastManager.getInstance(this).registerReceiver(myReceiver, intentFilter);
}
@Override
protected void onStart() {
setReceiver();
super.onStart();
}
@Override
protected void onStop() {
unregisterReceiver(myReceiver);
super.onStop();
}
private class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String message = intent.getStringExtra("broadcastMessage");
textView.setText(textView.getText() + "n" + message);
}
}
}
Some important points:
- We need to set an IntentFilter to register our BroadcastReceiver.
- Inside the IntentFilter Action we specify a string.
- The same string would be used in our IntentService as well.
- We must unregister our BroadcastReceiver in the
onStop()
method. LocalBroadcastManager
instance is used to set the receiver.- Our BroadcastReceiver would append the string returned from the service.
The code for MyService.java class is given below:
package com.journaldev.androidintentservices;
import android.app.IntentService;
import android.content.Intent;
import android.os.SystemClock;
import android.support.v4.content.LocalBroadcastManager;
public class MyService extends IntentService {
public MyService() {
super("MyService");
}
@Override
protected void onHandleIntent(Intent intent) {
String message = intent.getStringExtra("message");
intent.setAction(MainActivity.FILTER_ACTION_KEY);
SystemClock.sleep(3000);
String echoMessage = "IntentService after a pause of 3 seconds echoes " + message;
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent.putExtra("broadcastMessage", echoMessage));
}
}
To return the data to the activity we use the sendBroadcast method. It passes the data to the BroadcastReceiver. The BroadcastReceiver eventually passes the data to the Activity.
You must declare the Service inside the Manifest file. Without the LocalBroadcastManager the above data won’t be passed.
The output of the above application in action is given below:
This brings an end to this tutorial. You can download the project from the link below.