Android Service and BroadcastReceiver Example - Truiton
Skip to content

Android Service and BroadcastReceiver Example

Android Service with BroadcastReceiver

A very useful and important concept of Android is services, I was going through Truiton, and saw I have nothing on Android Services. So I decided, to write some interesting stuff that one can do with Android services. First off lets start with some basic intro to services.

Android Services Introduction

There are times when one wants to perform some long running operation on a device. Like processing of some data, establishing a two way connection over a network; to download a file from the internet, or maybe just play some music on a device. In all these situations one would require an Android component which can do processing in the background, i.e. should not have an UI. That component is called Android Service.

Please Note: Do not get confused by the word background here, Android Service runs on main thread, unless a new thread is spawned for it.

Although in this Android Service and BroadcastReceiver Example, I have taken care of this situation by doing all the processing in a separate thread. By taking this approach I averted the situation where app could be laggy, or go in an ANR state. Also its a good programming practice in Android to do heavy operations in a thread other than main thread.

Broadly speaking Android Services are of two types, started and bound, although a single service could act as started and bound both. I will show how this could be done in a separate tutorial. Here in this Android Service and BroadcastReceiver Example, I would mainly concentrate on started services. Lets start off by declaring the service in app manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.truiton.servicebroadcasts"
          xmlns:android="http://schemas.android.com/apk/res/android"
          android:versionCode="1"
          android:versionName="1.0">

    <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=".BroadcastService">
        </service>
    </application>

</manifest>

Android Service : Started

When a service is not bound to any app component, and is started by a call to startService() method, its called a started service. A started service once started has the capability of running indefinitely based on the flags, that were used to start it. Now you might be wondering when will it stop. The answer is; it will only stop if an app component stops it by calling stopService(). Or the service itself has a logic to stop by calling the stopSelf() method.

Android Service : Send Broadcast to Activity

Although communication between a service and an activity should be done through an IBinder interface by binding a service to a component. But for instance if there is a situation when you need to broadcast an intent to entire system, then one can also send a broadcast. This Android Service and BroadcastReceiver Example shows how to this. Although official android documentation mentions nothing regarding this procedure, so why am I doing it? because I can do it and I am not violating any guidelines. Have a look at the service code below:

package com.truiton.servicebroadcasts;

import android.annotation.TargetApi;
import android.app.Service;
import android.content.Intent;
import android.os.Build;
import android.os.IBinder;
import android.util.Log;

import java.util.ArrayList;

public class BroadcastService extends Service {
    private String LOG_TAG = null;
    private ArrayList<String> mList;

    @Override
    public void onCreate() {
        super.onCreate();
        LOG_TAG = this.getClass().getSimpleName();
        Log.i(LOG_TAG, "In onCreate");
        mList = new ArrayList<String>();
        mList.add("Object 1");
        mList.add("Object 2");
        mList.add("Object 3");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(LOG_TAG, "In onStartCommand");
        new Thread(new Runnable() {
            public void run() {
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Intent broadcastIntent = new Intent();
                broadcastIntent.setAction(MainActivity.mBroadcastStringAction);
                broadcastIntent.putExtra("Data", "Broadcast Data");
                sendBroadcast(broadcastIntent);

                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                broadcastIntent.setAction(MainActivity.mBroadcastIntegerAction);
                broadcastIntent.putExtra("Data", 10);
                sendBroadcast(broadcastIntent);

                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                broadcastIntent
                        .setAction(MainActivity.mBroadcastArrayListAction);
                broadcastIntent.putExtra("Data", mList);
                sendBroadcast(broadcastIntent);
            }
        }).start();
        return START_REDELIVER_INTENT;
    }

    @Override
    public IBinder onBind(Intent intent) {
        // Wont be called as service is not bound
        Log.i(LOG_TAG, "In onBind");
        return null;
    }

    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
    @Override
    public void onTaskRemoved(Intent rootIntent) {
        super.onTaskRemoved(rootIntent);
        Log.i(LOG_TAG, "In onTaskRemoved");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i(LOG_TAG, "In onDestroy");
    }
}

The class above shows how to create a service in Android, which can broadcast the results to the system. As per the specifications to start a service at-least an onBind() method is required. Although the main logic in a started service should be written in onStartCommand() method. Another important method here is onCreate, where you can initialize the service, as what all things need to be taken care of when service is created.

A service can be started in three modes:

  • START_NOT_STICKY
  • START_STICKY
  • START_REDELIVER_INTENT

In this example we are performing a service activity communication through START_REDELIVER_INTENT flag. By using this flag in onStartCommand() method, we are specifying that, if Android system kills this service due to low memory. Then it should start this service again and re-deliver the last intent it received. Also it would receive all the intents, that are pending.

As you can see that in the above Android service, all work is done in onStartCommand() method. In this method I am sending broadcasts with different types of data in it. This demonstrates that we can send any type of data we want to send through broadcasts.

Please Note: In the above example all the broadcasts are system wide broadcasts, if you want to make broadcasts accessible only to your app, then please use the LocalBroadcastManager.

Android Broadcast Receiver: Receiving Broadcasts From Service

Now I will create an activity, where I would listen to the broadcasts of the service created above. To do that I would create a layout first, with a single TextView:

<RelativeLayout 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"
                tools:context="com.truiton.servicebroadcasts.MainActivity">

    <TextView
        android:id="@+id/textview1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</RelativeLayout>

Moving on I would define an activity with BroadcastReceiver where this layout would be used:

package com.truiton.servicebroadcasts;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
    public static final String mBroadcastStringAction = "com.truiton.broadcast.string";
    public static final String mBroadcastIntegerAction = "com.truiton.broadcast.integer";
    public static final String mBroadcastArrayListAction = "com.truiton.broadcast.arraylist";
    private TextView mTextView;
    private IntentFilter mIntentFilter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTextView = (TextView) findViewById(R.id.textview1);
        mIntentFilter = new IntentFilter();
        mIntentFilter.addAction(mBroadcastStringAction);
        mIntentFilter.addAction(mBroadcastIntegerAction);
        mIntentFilter.addAction(mBroadcastArrayListAction);

        Intent serviceIntent = new Intent(this, BroadcastService.class);
        startService(serviceIntent);
    }

    @Override
    public void onResume() {
        super.onResume();
        registerReceiver(mReceiver, mIntentFilter);
    }

    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            mTextView.setText(mTextView.getText()
                    + "Broadcast From Service: \n");
            if (intent.getAction().equals(mBroadcastStringAction)) {
                mTextView.setText(mTextView.getText()
                        + intent.getStringExtra("Data") + "\n\n");
            } else if (intent.getAction().equals(mBroadcastIntegerAction)) {
                mTextView.setText(mTextView.getText().toString()
                        + intent.getIntExtra("Data", 0) + "\n\n");
            } else if (intent.getAction().equals(mBroadcastArrayListAction)) {
                mTextView.setText(mTextView.getText()
                        + intent.getStringArrayListExtra("Data").toString()
                        + "\n\n");
                Intent stopIntent = new Intent(MainActivity.this,
                        BroadcastService.class);
                stopService(stopIntent);
            }
        }
    };

    @Override
    protected void onPause() {
        unregisterReceiver(mReceiver);
        super.onPause();
    }
}

The above class demonstrates how to receive broadcasts in android dynamically. That is by declaring a BroadcastReceiver like this we don’t need to specify the receiver in manifest. It may be an advantage or disadvantage, but by doing this the activity would listen to broadcasts only when its in foreground, i.e. when its visible.

Now since we are using a started service, it will keep on running until its stopSelf() method is called. Or one can call its stopService() method from any other class. In this example I called stopService() method after receiving the final broadcast, and stopped the service. Have a look at the final screenshot:

Android Service

Source Code

Here you can see that all the three broadcasts from BroadcastService are received. Also from the link above you can access the source code for this Android Service and BroadcastReceiver Example. On a closing note, I would like to say this example is not the perfect way one should use an Android service, its just an alternate approach which does not break any guidelines. Hope this helped.

7 thoughts on “Android Service and BroadcastReceiver Example”

  1. I’ve been trying to make a location service to use with requestLocationUpdates and I searched for hours before I found this example. I am learning android for a project which is due soon so this example was a lifesaver for me!

Leave a Reply

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