BroadcastReceiver


A BroadcastReceiver is an android component responsible for listening to system-wide broadcast events or intents.

In Android, most system events are broadcast through Intent objects. To do this these Intent objects get sent to the BroadcastReceivers using the Context.sendBroadcast() methods.

When such an event is broadcasted the BroadcastReceiver will receive the event and react by either creating a status bar notification or performing a given task.

A BroadcastReceiver is an android component like Activity and Service hence most of the times it needs to be registered in the android manifest file.

However unlike the Activity, BroadcastReceivers don't have any user interface.

BroadcastReceiver as a class is abstract, hence normally has a method called onReceive() that we do override to do the task we want to happen when the task is received.

Most of the standard system events are defined as action strings and can be found in the API documentation for the Intent class.

Suppose for example, if your app needs to be notified whenever the user connects or disconnects the charger to the device, two broadcast actions defined in the Intent class do that:

  1. ACTION_POWER_DISCONNECTED
  2. ACTION_POWER_CONNECTED.

Here's an example.

public class PhoneChargerConnectedListener extends BroadcastReceiver {
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (Intent.ACTION_POWER_CONNECTED.equals(action)) {
            context.startService(
            new Intent(MyService.ACTION_POWER_CONNECTED));
        } else if (Intent.ACTION_POWER_DISCONNECTED.equals(action)) {
        context.startService(
        new Intent(MyService.ACTION_POWER_DISCONNECTED));
        }
    }
}

In this method, the only thing you do is call Context.startService() to delegate the event to a service that performs the actual work.

How do I register BroadcastReceiver?

Well we can register broadcastReceiver in two ways.

1. Via AndroidManifest.xml

The default method for implementing BroadcastReceivers is to declare them in the android manifest. Because of that, it’s possible for the BroadcastReceiver to notify your service even though the user hasn’t started your application.

This is especially useful for applications that should start on certain system events without user interaction.

<receiver android:name=".PhoneChargerConnectedListener">
    <intent-filter>
        <action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
        <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
    </intent-filter>
</receiver>

This method is also the easiest way.

By using AndroidManifest.xml to register BroadcastReceiver, your application will be getting the Broadcasts until you uninstall the application. This means you sacifice a little bit of control or the BroadcastReceiver's lifecycle as you can't just register it and unregister it as you wish.

To do that, you check the next way of registering broadcast receivers.

2. Programmatically

BroadcastReceivers can also be registered programmatically within Activities and Services.

Infact some broadcast Intents can only be registered programmatically. On the other hand some only work if you declare them in your manifest.

When you register a BroadcastReceiver programmatically you also have to remember to unregister it in the matching callback.

Here's an example:

public class MyActivity extends AppCompatActivity {
    private PhoneChargerConnectedListener myPhoneChargerConnectedListener;
    @Override
    protected void onResume() {
        super.onResume();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_POWER_CONNECTED);
        intentFilter.addAction(Intent.ACTION_POWER_DISCONNECTED);
        myPhoneChargerConnectedListener = new PhoneChargerConnectedListener();
        registerReceiver(myPhoneChargerConnectedListener, intentFilter);
    }
    @Override
    protected void onPause() {
        super.onPause();
        unregisterReceiver(myPhoneChargerConnectedListener);
    }
}

In this case we have registered the BroadcastReceiver programmatically using the the registerReceiver() method of the Context class. By using this method, we can control our BroadcastReceiver's lifecycle by registering and un-registering them as per our requirement.

BroadcastReceiver Example with AlarmManager

Let's look at a simple broadcast receiver example with alarm manager.

We will have one activity and one class.

(a). MainActivity.java

Start by creating an activity in your android studio.

Here we have Our MainActivity class. This class will be Deriving from AppCompatActivity which resides in the support library.

We will have three methods:

  1. onCreate(),
  2. initializeViews(),
  3. go().

This activity's user interface will be inflated from content_main.xml using the setContentView() method.

The views we use are EditTexts and Buttons. We Reference them from our layout specification using findViewById().

We will Initialize and start our alarm in the go() method.

package com.tutorials.hp.alarmmanagerstarter;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    Button startBtn;
    EditText timeTxt;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

         initializeViews();

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });

    }

    /*
    INITIALIZE VIEWS
     */
    private void initializeViews()
    {
        timeTxt= (EditText) findViewById(R.id.timeTxt);
        startBtn= (Button) findViewById(R.id.startBtn);

        startBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
               go();
            }
        });
    }

    /*
    INITIALIZE AND START OUR ALARM
     */
    private void go()
    {
        //GET TIME IN SECONDS AND INITIALIZE INTENT
        int time=Integer.parseInt(timeTxt.getText().toString());
        Intent i=new Intent(this,MyReceiver.class);

        //PASS CONTEXT,YOUR PRIVATE REQUEST CODE,INTENT OBJECT AND FLAG
        PendingIntent pi=PendingIntent.getBroadcast(this,0,i,0);

        //INITIALIZE ALARM MANAGER
        AlarmManager alarmManager= (AlarmManager) getSystemService(ALARM_SERVICE);

        //SET THE ALARM
        alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+(time*1000),pi);
        Toast.makeText(MainActivity.this, "Alarm set in "+time+" seconds", Toast.LENGTH_SHORT).show();
    }

}

(b). MyReciever.java

  • Our MyReciever class.
  • Derives from android.content.BroadcastReceiver class.
  • Methods: onReceive().
  • We show a toast message in ouronReceive() method to simulate alarm ringing.
package com.tutorials.hp.alarmmanagerstarter;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;

public class MyReceiver extends BroadcastReceiver {
    /*
    RING ALARM WHEN IN WHEN WE RECEIVE OUR BROADCAST
     */
    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context, "Alarm Ringing...", Toast.LENGTH_SHORT).show();
    }
}

(c) activity_main.xml

  • Our main activity layout file.
  • Shall get inflated to MainActivity.
  • Root tag is relativeLayout.
  • Contains an EditText and a button.
<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout 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="com.tutorials.hp.alarmmanagerstarter.MainActivity"
    >

    <EditText
        android:id="@+id/timeTxt"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginTop="28dp"
        android:ems="10"
        android:hint="Number of seconds"
        android:inputType="numberDecimal" />

    <Button
        android:id="@+id/startBtn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignRight="@+id/timeTxt"
        android:layout_below="@+id/timeTxt"
        android:layout_marginRight="60dp"
        android:layout_marginTop="120dp"
        android:text="Start" />
</RelativeLayout>

(d). AndroidManifest.xml

We will have to register our BroadcastReceiver class in our android manifest.

Here's my manifest in full:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.tutorials.hp.alarmmanagerstarter">
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <receiver android:name="MyReceiver" >
        </receiver>
    </application>

</manifest>

Quick BroadcastReceiver Examples

1. Listen to Network State Changes with BroadcastReceiver

First we need to create a java class, and then have it derive from android.content.BroadcastReceiver.

As instance fields we will have a boolean isNetWorkConnected which will hold for us the a true or false indicating whether network is connected or not.

We will also have a Context object.

We provide two constructors, one which will inject into our class the Context object. Then we override the onReceive() method of the BroadcastReceiver class. Normally this method receives two objects, one a Context object and the other an Intent object.

Here we will initialize a ConnectivityManager using the getSystemService() ,method of the Context class.

Using the ConnectivityManager instance, we invoke the getActiveNetworkInfo() method to receive network information which we hold in an android.net.NetworkInfo object.

Ultimately we set the isConnected() value to isNetWorkConnected boolean.

Then we also have the isNetWorkAvailable() method, which will basically check for us if network is available.

It's just a public method that needs the instance of this class to be invoked as we will see in a short while.

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.widget.Toast;
import java.util.concurrent.CopyOnWriteArrayList;

public class NetWorkStateReceiver extends BroadcastReceiver {
    public boolean isNetWorkConnected;
    private Context mContext;

    public NetWorkStateReceiver() {
        super();
    }
    public NetWorkStateReceiver(Context context) {
        mContext = context;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        ConnectivityManager connectivityManager = (ConnectivityManager)
                context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();

        if (networkInfo != null && networkInfo.isConnected()) {
            isNetWorkConnected = true;
        } else {
            isNetWorkConnected = false;
            Toast.makeText(context, "No network Connection", Toast.LENGTH_SHORT).show();
        }

    }

    /**
     * Check if network is available
     * @return boolean value
     */
    public boolean isNetWorkAvailable() {
        ConnectivityManager connectivityManager = (ConnectivityManager)
                mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
        if (networkInfo != null) {
            return networkInfo.isConnected();
        }
        return false;
    }
}

Then in your MainActivity or wherever, you can come and start by instantiating the above class:

    publi class MainActivity extends AppCompatActivity{
        NetWorkStateReceiver receiver;
        @Override
        public void onCreate(Bundle savedInstanceState){
            .....
           receiver = new NetWorkStateReceiver(this);
           if(receiver.isNetWorkAvailable())
           {
               //do something network is available
           }
        }
    }

In you AndroidManifest.xml you must firts add the appropriate permissions as well as register your BroadcastReceiver:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    >

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <application>
        ....
        <receiver
            android:name=".broadcasts.NetWorkStateReceiver"
            android:enabled="true"
            android:exported="true" />
        ....                
    </application>

2. How to create a custom BroadcastReceiver

Here's a custom abstract BroadcastReciever class. Obviously it derives from the BroadcastReceiver. We proceed and redefine the important methods in this class like the registerReceiver(), unregisterReceiver() and sendBroadcast() methods.


import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v4.content.LocalBroadcastManager;

public abstract class LocalBroadcastCommunicator extends BroadcastReceiver {

    // The action name used to send and alsoe receive intents
    private static String sAction = null;

    private static <T> void registerReceiver(LocalBroadcastCommunicator receiver, Context context) {
        sAction = receiver.getClass().getName();
        LocalBroadcastManager.getInstance(context).registerReceiver(receiver, new IntentFilter(sAction));
    }

    private static <T> void unregisterReceiver(LocalBroadcastCommunicator receiver, Context context) {
        LocalBroadcastManager.getInstance(context).unregisterReceiver(receiver);
    }

    public static void sendBroadcast(Context context, Intent intent) {
        if(sAction == null) {
            /* If sAction is null at this point, no receiver has been registered yet and there's no
             * point in sending a broadcast. */
            return;
        }

        intent.setAction(sAction);
        LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
    }

    public void registerReceiver(Context context) {
        registerReceiver(this, context);
    }

    public void unregisterReceiver(Context context) {
        unregisterReceiver(this, context);
    }
}

Full Examples

1. How to Display Notification For Low Battery using BroadcastReceiver

We are creating a simple BatteryManager using the BroadcasteReceiver class. We will show a the Battery Level in a TextView and show the progress in the progressbar.

Here are some of the API's you may not know that we use:

(a). BroadcastReceiver

This is the base class for code that will receive intents sent by sendBroadcast().

(b). IntentFilter

IntentFilter is a Structured description of Intent values to be matched. An IntentFilter can match against actions, categories, and data (either via its type, scheme, and/or path) in an Intent.

(c). BatteryManager

This class contains strings and constants used for values in the ACTION_BATTERY_CHANGED Intent.

This is the main activity.

package com.example.ankitkumar.broadcastreceiver_batterymanager;

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

public class MainActivity extends AppCompatActivity {
    TextView batteryLevel;
    ProgressBar myProgressBar;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        batteryLevel = (TextView)findViewById(R.id.textView);
        myProgressBar = (ProgressBar)findViewById(R.id.progressBar);
        IntentFilter intentFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
        registerReceiver(myBroadcastReceiver, intentFilter);

    }

    BroadcastReceiver myBroadcastReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            context.unregisterReceiver(this);
            int currentLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
            int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
            int level = -1;
            if (currentLevel >= 0 && scale > 0) {
                level = (currentLevel * 100) / scale;
            }
            batteryLevel.setText("Battery Level remaining :"+  level +"%");
            myProgressBar.setProgress(level);
        }
    };
}

This is the main activity's layout. Here we will have a TextView to show battery level and a progressbar to show battery percentage.

<?xml version="1.0" encoding="UTF-8"?>

<RelativeLayout
        tools:context="com.example.ankitkumar.broadcastreceiver_batterymanager.MainActivity" android:paddingTop="@dimen/activity_vertical_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingBottom="@dimen/activity_vertical_margin" android:layout_height="match_parent" android:layout_width="match_parent" android:id="@+id/activity_main" xmlns:tools="http://schemas.android.com/tools" xmlns:android="http://schemas.android.com/apk/res/android">

<TextView 
        android:layout_height="wrap_content" android:layout_width="wrap_content" android:id="@+id/textView" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:textSize="20sp" android:text="Hello World!"/>

<ProgressBar 
        android:layout_height="20dp" android:layout_width="match_parent" android:id="@+id/progressBar" android:layout_alignParentRight="true" android:layout_alignParentEnd="true" android:layout_below="@+id/textView" android:layout_marginTop="25dp" android:max="100" style="?android:attr/progressBarStyleHorizontal"/>

</RelativeLayout>
No. Location Link
1. GitHub Download
2. GitHub Browse
2. GitHub Original Creator: @AnkitKumar111

2. Use BroadcastReceiver to Listen to InComing SMS and Show it

We listen to that incoming SMS and then read it and show it in a Toast message.

This is the main activity.

package com.example.ankitkumar.msgreceive;

import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //checking wether the permission is already granted
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_SMS) != PackageManager.PERMISSION_GRANTED) {

            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_SMS}, 1);

        }

    }

}

Our IncomingSMS.java file. Here are some of the APIs we use:

(a). SmsManager

This is a class defined in the android.telephony package that is responsible for managemenet of SMS operations such as sending data, text, and pdu SMS messages.

(b). SmsMessage

This represents a Short Message Service message.

package com.example.ankitkumar.msgreceive;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;
import android.util.Log;
import android.widget.Toast;
import static android.telephony.SmsMessage.createFromPdu;

public class IncomingSms extends BroadcastReceiver {

    // Get the object of SmsManager
    final SmsManager sms = SmsManager.getDefault();

    @Override
    public void onReceive(Context context, Intent intent) {

        // Retrieves a map of extended data from the intent.
        final Bundle bundle = intent.getExtras();

        try {

            if (bundle != null) {

                final Object[] pdusObj = (Object[]) bundle.get("pdus");

                for (int i = 0; i < pdusObj.length; i++) {

                    SmsMessage currentMessage = createFromPdu((byte[]) pdusObj[i]);
                    String phoneNumber = currentMessage.getDisplayOriginatingAddress();

                    String senderNum = phoneNumber;
                    String message = currentMessage.getDisplayMessageBody();

                    Log.i("SmsReceiver", "senderNum: " + senderNum + "; message: " + message);

                    int duration = Toast.LENGTH_LONG;
                    final Toast toast = Toast.makeText(context, "senderNum: " + senderNum + ", message: " + message, duration);
                    toast.show();

                    //Countdown Timer for extending normal time of toast notification
                    new CountDownTimer(9000, 1000) {

                        public void onTick(long millisUntilFinished) {
                            toast.show();
                        }

                        public void onFinish() {
                            toast.show();
                        }

                    }.start();
                } // end for loop
            } // bundle is null

        } catch (Exception e) {
            Log.e("SmsReceiver", "Exception smsReceiver" + e);

        }
    }

}

This is the main activity's layout.

<?xml version="1.0" encoding="UTF-8"?>

<RelativeLayout
        tools:context="com.example.ankitkumar.msgreceive.MainActivity" android:background="#f2f2f2" android:layout_height="match_parent" android:layout_width="match_parent" xmlns:tools="http://schemas.android.com/tools" xmlns:android="http://schemas.android.com/apk/res/android">

<ImageView 
        android:background="@drawable/ic_sms" android:layout_height="200sp" android:layout_width="200sp" android:contentDescription="@string/app_name" android:layout_centerInParent="true" android:alpha="0.4"/>

</RelativeLayout>
No. Location Link
1. GitHub Download
2. GitHub Browse
2. GitHub Original Creator: @AnkitKumar111

How do You Feel after reading this?

According to scientists, we humans have 8 primary innate emotions: joy, acceptance, fear, surprise, sadness, disgust, anger, and anticipation. Feel free to tell us how you feel about this article using these emotes or via the comment section. This feedback helps us gauge our progress.

Help me Grow.

I set myself some growth ambitions I desire to achieve by this year's end regarding this website and my youtube channel. Am halfway. Help me reach them by:




Recommendations


What do You Think


Previous Post Next Post