Android IntentService using BroadcastReceiver

Filed Under: Android

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

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

android intent-services-broadcast-receivers-output

Layout code


<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://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:

android intentservice broadcastreceiver

This brings an end to this tutorial. You can download the project from the link below.

You can also download the project code from our GitHub Repository.

Comments

  1. bhoomika says:

    hello, you say An IntentService can in invoked from the Main thread only.
    but below code work.
    so please tell me where my mistake
    Thread thread = new Thread(new Runnable() {
    @Override
    public void run() {
    Log.e(“run Thread: “, String.valueOf(Thread.currentThread().getId()));
    //startService(new Intent(HomeActivity.this, SimpleServiceEx.class));

    startService(new Intent(HomeActivity.this, IntentServiceExample.class));
    }
    });

    thread.start();

  2. Soumya says:

    My app should send data to server every 10 min. Is it ok to use intentservice? And will it support all the versions of android?

    1. sunil says:

      service and intent service can be stopped by OS for free up space, for regular interval update you can use job scheduler to full fill your purpose

  3. ChampionTej05 says:

    Thank you so much for your quick help. I wanted to know that I am trying to make an alarm clock with some step counting activity, so can I run that complete step counting work on HandleIntent() method??

Leave a Reply

Your email address will not be published. Required fields are marked *

close
Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages