Broadcast Receivers
Broadcast receivers are app components that can register for system events or app events. When an event occurs, registered broadcast receivers are notified via an Intent
. For instance, if you are implementing a media app and you're interested in knowing when the user connects or disconnects a headset, register for the ACTION_HEADSET_PLUG
intent action.
Use broadcast receivers to respond to messages that have been broadcast from apps or from the Android system. To create a broadcast receiver:
- Define a subclass of the
BroadcastReceiver
class and implement theonReceive()
method. - Register the broadcast receiver, either statically or dynamically.
These steps are described below.
Subclass a BroadcastReceiver
To create a broadcast receiver, define a subclass of the BroadcastReceiver
class. This subclass is where Intent
objects are delivered if they match the intent filters you register for.
Within your subclass:
- Implement the
onReceive()
method, which is called when theBroadcastReceiver
object receives anIntent
broadcast . - Inside
onReceive()
, include any other logic that your broadcast receiver needs.
Example: Create a broadcast receiver
In this example, the myReceiver
class a subclass of BroadcastReceiver
. If the incoming broadcast intent has the ACTION_SHOW_TOAST
action, the myReceiver
class shows a toast message:
//Subclass of the BroadcastReceiver class.
private class myReceiver extends BroadcastReceiver {
// Override the onReceive method to receive the broadcasts
@Override
public void onReceive(Context context, Intent intent) {
//Check the Intent action and perform the required operation
if (intent.getAction().equals(ACTION_SHOW_TOAST)) {
CharSequence text = "Broadcast Received!";
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
}
}
}
The onReceive()
method is called when your app receives a registered Intent
broadcast. The onReceive()
method runs on the main thread unless it is explicitly asked to run on a different thread in the registerReceiver()
method.
The onReceive()
method has a timeout of 10 seconds. After 10 seconds, the Android system considers your receiver to be blocked, and the system might show the user an "application not responding" error. For this reason, you shouldn't implement long-running operations in onReceive()
.
In particular:
- Don't try to show a dialog from within a
BroadcastReceiver
. Instead, display a notification using theNotificationManager
API. - Don't try to bind to a service from within a
BroadcastReceiver
. Instead, useContext.startService()
to send a command to the service.
If you need to perform a long-running operation inside BroadcastReceiver
, use WorkManager
to schedule a job. When you schedule a task with WorkManager
, the task is guaranteed to run. WorkManager
chooses the appropriate way to run your task, based on such factors as the device API level and the app state.
Register your broadcast receiver and set intent filters
There are two types of broadcast receivers:
- Static receivers, which you register in the Android manifest file.
- Dynamic receivers, which you register using a context.
Static receivers
Static receivers are also called manifest-declared receivers. To register a static receiver, include the following attributes inside the <receiver>
element in your AndroidManifest.xml
file:
The value for this attribute is the fully classified name of the
BroadcastReceiver
subclass, including the package name. To use the package name that's specified in the manifest, prefix the subclass name with a period, for example.AlarmReceiver
.android:exported
(optional)If this boolean value is set to
false
, other apps cannot send broadcasts to your receiver. This attribute is important for security.Include this nested element to specify the broadcast
Intent
actions that your broadcast receiver component is listening for.
The following code snippet shows static registration of a broadcast receiver that listens for a custom broadcast Intent
with the action "ACTION_SHOW_TOAST
":
- The receiver's
name
is the name of theBroadcastReceiver
subclass (.AlarmReceiver
). - The receiver is not exported, meaning that no other apps can deliver broadcasts to this app.
- The intent filter checks whether incoming intents include an action named
ACTION_SHOW_TOAST
, which is a customIntent
action defined within the app.<receiver android:name=".AlarmReceiver" android:exported="false"> <intent-filter> <action android:name= "com.example.myproject.intent.action.ACTION_SHOW_TOAST"/> </intent-filter> </receiver>
Note: For Android 8.0 (API level 26) and higher, static receivers can't receive most implicit broadcasts. (Implicit broadcasts are broadcasts that don't target your app specifically.) Even if you register for these broadcasts in the manifest, the Android system won't deliver them to your app. However, you can still use a dynamic receiver to register for these broadcasts.
A few broadcasts, such as ACTION_BOOT_COMPLETED
and ACTION_TIMEZONE_CHANGED
, are excepted from this restriction. You can declare them in the manifest, no matter what the target API level.
Intent filters
An intent filter specifies the types of intents that a component can receive. When the system receives an Intent
as a broadcast, it searches the broadcast receivers based on the values specified in receivers' intent filters.
To create an intent filter statically, use the <intent-filter>
element in the Android manifest. An <intent-filter>
element has one required element, <action>
. The Android system compares the Intent
action of the incoming broadcast to the filter action's android:name
strings. If any of the names in the filter match the action name in the incoming broadcast, the broadcast is sent to your app.
This <intent-filter>
listens for a system broadcast that's sent when the device boots up. Only Intent
objects with an action named BOOT_COMPLETED
match the filter:
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
If no intent filters are specified, the broadcast receiver can only be activated with an explicit broadcast Intent
that specifies the component by name
Dynamic receivers
Dynamic receivers are also called context-registered receivers. You register a dynamic receiver using an application context or an Activity
context. A dynamic receiver receives broadcasts as long as the registering context is valid:
- If you use the application context to register your receiver, your app receives relevant broadcasts as long as your app is running in either the foreground or the background.
- If you use an
Activity
context to register your receiver, your app receives relevant broadcasts until thatActivity
is destroyed.
To use the context to register your receiver dynamically:
Create an
IntentFilter
and add theIntent
actions that you want your app to listen for. You can add more than one action to the sameIntentFilter
object.IntentFilter intentFilter = new IntentFilter(); filter.addAction(Intent.ACTION_POWER_CONNECTED); filter.addAction(Intent.ACTION_POWER_DISCONNECTED);
When the device power is connected or disconnected, the Android system broadcasts the
Intent.ACTION_POWER_CONNECTED
andIntent.ACTION_POWER_DISCONNECTED
intent actions.Register the receiver by calling
registerReceiver()
method on the context. Pass in theBroadcastReceiver
object and theIntentFilter
object.mReceiver = new AlarmReceiver(); this.registerReceiver(mReceiver, intentFilter);
In this example the
Activity
context (this
) is used to register your receiver. So the app will receive the broadcast as long as theActivity
is running.
Local broadcasts
You must register local receivers dynamically, because static registration in the manifest is not possible for a local broadcasts.
To register a receiver for local broadcasts:
- Get an instance of
LocalBroadcastManager
by calling thegetInstance()
method. - Call
registerReceiver()
, passing in the receiver and anIntentFilter
object.LocalBroadcastManager.getInstance(this) .registerReceiver(mReceiver, new IntentFilter(CustomReceiver.ACTION_CUSTOM_BROADCAST));
Unregister the receiver
To save system resources and avoid leaks, unregister dynamic receivers when your app no longer needs them, or before the Activity
or app is destroyed. This is also true for local broadcast receivers, because they're registered dynamically.
To unregister a normal broadcast receiver:
Call
unregisterReceiver()
and pass in yourBroadcastReceiver
object:unregisterReceiver(mReceiver);
To unregister a local broadcast receiver:
Get an instance of the
LocalBroadcastManager
.Call
LocalBroadcastManager.unregisterReceiver()
and pass in yourBroadcastReceiver
object:LocalBroadcastManager.getInstance(this) .unregisterReceiver(mReceiver);
Where you call these
unregisterReceiver()
methods depends on the desired lifecycle of yourBroadcastReceiver
object:Sometimes the receiver is only needed when your activity is visible, for example to disable a network function when the network is not available. In these cases, register the receiver in
onResume()
and unregister the receiver inonPause()
.- You can also use the
onStart()
/onStop()
oronCreate()
/onDestroy()
method pairs, if they are more appropriate for your use case.
Comments
Post a Comment