Android Broadcast Receivers
Broadcast Receivers are used to respond to broadcast messages from other applications or the system. These messages are sometimes referred to as events or intents. For example, an application can initiate a broadcast to let other applications know that some data has been downloaded to the device and is available for them to use. Broadcast Receivers can define appropriate actions to intercept these communications.
There are two important steps to make the system's broadcast intents work with Broadcast Receivers:
- Create a Broadcast Receiver
- Register the Broadcast Receiver
There is an additional step to implement custom intents: you must create and broadcast these intents.
Creating a Broadcast Receiver
A Broadcast Receiver needs to be implemented as a subclass of the BroadcastReceiver class and override the onReceive() method to receive messages with Intent objects as parameters.
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Intent Detected.", Toast.LENGTH_LONG).show();
}
}
Registering a Broadcast Receiver
An application listens for specific broadcast intents by registering the Broadcast Receiver in the AndroidManifest.xml. Suppose we are going to register MyReceiver to listen for the ACTION_BOOT_COMPLETED event generated by the system. This event is broadcast when the Android system has completed the boot process.
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<receiver android:name="MyReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED">
</action>
</intent-filter>
</receiver>
</application>
Now, whenever an Android device is booted, it will be intercepted by the Broadcast Receiver MyReceiver, and the logic implemented in onReceive() will be executed.
Many system-generated events are defined as static constants in the Intent class. The following table lists some important system events:
Event Constant | Description |
---|---|
android.intent.action.BATTERY_CHANGED | Sticky broadcast containing the battery charging status, level, and other information. |
android.intent.action.BATTERY_LOW | Indicates a low battery condition on the device. |
android.intent.action.BATTERY_OKAY | Indicates the battery is now okay after being low. |
android.intent.action.BOOT_COMPLETED | Broadcast once after the system has finished booting. |
android.intent.action.BUG_REPORT | Show activity for reporting a bug. |
android.intent.action.CALL | Make a call to someone specified by the data. |
android.intent.action.CALL_BUTTON | User pressed the "call" button to open the dialer or other appropriate interface. |
android.intent.action.DATE_CHANGED | Date has changed. |
android.intent.action.REBOOT | Device reboots. |
Broadcasting Custom Intents
If you want your application to generate and send custom intents, you need to create and send these intents using sendBroadcast() in the activity class. If you use sendStickyBroadcast(Intent), the intent is sticky, meaning the intent you broadcast remains after the broadcast is complete.
public void broadcastIntent(View view) {
Intent intent = new Intent();
intent.setAction("com.tutorialpro.CUSTOM_INTENT");
sendBroadcast(intent);
}
The intent com.tutorialpro.CUSTOM_INTENT can be registered just like we registered the system-generated intents.
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<receiver android:name="MyReceiver">
<intent-filter>
<action android:name="com.tutorialpro.CUSTOM_INTENT">
</action>
</intent-filter>
</receiver>
</application>
Example
This example will explain how to create a Broadcast Receiver to intercept a custom intent. Once you are familiar with custom intents, you can program your application to intercept system-generated intents. Let's modify the Android application we created in the Hello World example section following these steps:
Step | Description |
---|---|
1 | Create an Android application using Android Studio and name it broadcastreceiver, under the package com.tutorialpro.broadcastreceiver. |
2 | Modify the main activity file MainActivity.java to add the broadcastIntent() method. |
3 | Create a new Java file named MyReceiver.java in the package com.tutorialpro.broadcastreceiver to define the Broadcast Receiver. |
4 | An application can handle one or more custom or system intents without any restrictions. Each intent you want to intercept needs to be registered in AndroidManifest.xml using the <receiver.../> tag. |
5 | Modify the default content in the res/layout/activity_main.xml file to include a button to broadcast an intent. |
6 | No changes are needed for the string file, as Android Studio handles the string.xml file. |
7 | Start the Android emulator to run the application and verify the results of the changes made. |
Below is the content of the modified main activity file src/com.tutorialpro.broadcastreceiver/MainActivity.java. This file includes each basic lifecycle method. We added the broadcastIntent() method to broadcast a custom event.
package com.tutorialpro.broadcastreceiver;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.content.Intent;
import android.view.View;
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
// Broadcast a custom intent
public void broadcastIntent(View view){
Intent intent = new Intent();
intent.setAction("cn.programmer.CUSTOM_INTENT");
sendBroadcast(intent);
}
}
Below is the content of src/com.tutorialpro.broadcastreceiver/MyReceiver.java:
package com.tutorialpro.broadcastreceiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "检测到意图。", Toast.LENGTH_LONG).show();
}
}
Next, modify the AndroidManifest.xml file by adding the <receiver.../> tag to include our Broadcast Receiver:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tutorialpro.broadcastreceiver"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="22" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/title_activity_main" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
</activity>
<receiver android:name="MyReceiver">
<intent-filter>
<action android:name="cn.programmer.CUSTOM_INTENT">
</action>
</intent-filter>
</receiver>
</application>
</manifest>
Below is the content of the res/layout/activity_main.xml
file, which includes a button to broadcast a custom intent.
<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" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Broadcast Example"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:textSize="30dp" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="www.tutorialpro.org"
android:textColor="#ff87ff09"
android:textSize="30dp"
android:layout_above="@+id/imageButton"
android:layout_centerHorizontal="true"
android:layout_marginBottom="40dp" />
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/imageButton"
android:src="@drawable/ic_launcher"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button2"
android:text="Broadcast Intent"
android:onClick="broadcastIntent"
android:layout_below="@+id/imageButton"
android:layout_centerHorizontal="true" />
</RelativeLayout>
Below is the content of the res/values/strings.xml
file, which defines two new constants.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Android Broadcast Receiver</string>
<string name="action_settings">Settings</string>
<string name="menu_settings">Settings</string>
<string name="title_activity_main">Main Activity</string>
</resources>
Let's run the newly modified Hello World! application. I assume you have already created an AVD while setting up the environment. Open the activity file in your project and click on the
Now click the "Broadcast Intent" button to broadcast our custom intent. This will broadcast our custom intent "cn.programmer.CUSTOM_INTENT", which will be intercepted by our registered broadcast receiver MyReceiver
and execute the logic we implemented. A toast will appear at the bottom of the emulator as follows:
You can try implementing other broadcast receivers to intercept intents generated by the system, such as system startup, date change, and low battery, among others.