Skip to content

Instantly share code, notes, and snippets.

@hgross
Forked from MohammadSamandari/Android-Broadcasts.md
Created February 6, 2023 11:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hgross/d5bc1d4d7c63b1ae2349b5bd02203008 to your computer and use it in GitHub Desktop.
Save hgross/d5bc1d4d7c63b1ae2349b5bd02203008 to your computer and use it in GitHub Desktop.
Broadcasts and Broadcast Receivers

Broadcasts

Broadcasts are messages that the Android system and Android apps send when events occur that might affect the functionality of other apps. For example, the Android system sends an event when the system boots up, when power is connected or disconnected, and when headphones are connected or disconnected. Your Android app can also broadcast events, for example when new data is downloaded.

In general, broadcasts are messaging components used for communicating across apps when events of interest occur. There are two types of broadcasts:

  • System broadcasts are delivered by the system.
  • Custom broadcasts are delivered by your app.

System Broadcasts

System broadcasts are wrapped in Intent objects.

The intent object's action field contains event details such as android.intent.action.HEADSET_PLUG, which is sent when a wired headset is connected or disconnected.

  • When the device boots, the system broadcasts a system Intent with the action ACTION_BOOT_COMPLETED.
  • When the device is disconnected from external power, the system sends a system Intent with the action field ACTION_POWER_DISCONNECTED.

System broadcasts aren't targeted at specific recipients. Interested apps must register a component to "listen" for these events. This listening component is called a broadcast receiver.

Custom Broadcasts

Custom broadcasts are broadcasts that your app sends out. Use a custom broadcast when you want your app to take an action without launching an activity. For example, use a custom broadcast when you want to let other apps know that data has been downloaded to the device and is available for them to use. More than one broadcast receiver can be registered to receive your broadcast.

To create a custom broadcast, define a custom Intent action.

There are three ways to deliver a custom broadcast:

Normal Broadcasts

The sendBroadcast() method sends broadcasts to all the registered receivers at the same time, in an undefined order.

public void sendBroadcast() {
   Intent intent = new Intent();
   intent.setAction("com.example.myproject.ACTION_SHOW_TOAST");
   // Set the optional additional information in extra field.
   intent.putExtra("data","This is a normal broadcast");
   sendBroadcast(intent);
}

Ordered Broadcasts

To send a broadcast to one receiver at a time, use the sendOrderedBroadcast() method:

  • The android:priority attribute that's specified in the intent filter determines the order in which the broadcast is sent.
  • If more than one receiver with same priority is present, the sending order is random.
  • The Intent is propagated from one receiver to the next.
  • During its turn, a receiver can update the Intent, or it can cancel the broadcast. (If the receiver cancels the broadcast, the Intent can't be propagated further.)
public void sendOrderedBroadcast() {
   Intent intent = new Intent();

   // Set a unique action string prefixed by your app package name.
   intent.setAction("com.example.myproject.ACTION_NOTIFY");
   // Deliver the Intent.
   sendOrderedBroadcast(intent);
}

Local Broadcasts

If you don't need to send broadcasts to a different app, use the LocalBroadcastManager.sendBroadcast() method, which sends broadcasts to receivers within your app

To send a local broadcast:

  1. To get an instance of LocalBroadcastManager, call getInstance() and pass in the application context.
  2. Call sendBroadcast() on the instance. Pass in the intent that you want to broadcast.
 LocalBroadcastManager.getInstance(this).sendBroadcast(customBroadcastIntent);

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.

Use broadcast receivers to respond to messages that have been broadcast from apps or from the Android system. To create a broadcast receiver:

  1. Define a subclass of the BroadcastReceiver class and implement the onReceive() method.
  2. Register the broadcast receiver, either statically or dynamically.

Subclass a Broadcast receivers

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 the BroadcastReceiver object receives an Intent broadcast .
  • Inside onReceive(), include any other logic that your broadcast receiver needs.

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();
       }
   }
}
  • Note:
  1. Don't try to show a dialog from within a BroadcastReceiver. Instead, display a notification using the NotificationManager API.
  2. Don't try to bind to a service from within a BroadcastReceiver. Instead, use Context.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 element in your AndroidManifest.xml file:

The following code snippet shows static registration of a broadcast receiver that listens for a custom broadcast Intent with the action "ACTION_SHOW_TOAST":

<receiver
 android:name=".AlarmReceiver"
 android:exported="false">
 <intent-filter>
     <action android:name=    
          "com.example.myproject.intent.action.ACTION_SHOW_TOAST"/>
 </intent-filter>
</receiver>
  • The receiver's name is the name of the BroadcastReceiver 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 custom Intent action defined within the app.

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 that Activity is destroyed.

To use the context to register your receiver dynamically:

  1. Create an IntentFilter and add the Intent actions that you want your app to listen for. You can add more than one action to the same IntentFilter object.
 IntentFilter intentFilter = new IntentFilter();
 filter.addAction(Intent.ACTION_POWER_CONNECTED);
 filter.addAction(Intent.ACTION_POWER_DISCONNECTED);
  1. Register the receiver by calling registerReceiver() method on the context. Pass in the BroadcastReceiver object and the IntentFilter object.
 mReceiver = new AlarmReceiver();
 this.registerReceiver(mReceiver, intentFilter);
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:

  1. Get an instance of LocalBroadcastManager by calling the getInstance() method.
  2. Call registerReceiver(), passing in the receiver and an IntentFilter object.
 LocalBroadcastManager.getInstance(this)
    .registerReceiver(mReceiver, 
           new IntentFilter(CustomReceiver.ACTION_CUSTOM_BROADCAST));
Unregister the receiver

Call unregisterReceiver() and pass in your BroadcastReceiver object:

 unregisterReceiver(mReceiver);
 LocalBroadcastManager.getInstance(this)
    .unregisterReceiver(mReceiver);

Where you call these unregisterReceiver() methods depends on the desired lifecycle of your BroadcastReceiver 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 in onPause().
  • You can also use the onStart()/onStop() or onCreate()/onDestroy() method pairs, if they are more appropriate for your use case.
package mohammad.samandari.powerreceiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class CustomReceiver extends BroadcastReceiver {
private static final String ACTION_CUSTOM_BROADCAST = BuildConfig.APPLICATION_ID + ".ACTION_CUSTOM_BROADCAST";
@Override
public void onReceive (Context context, Intent intent) {
//Get the Intent action from the intent parameter and store it in a String variable called intentAction.
String intentAction = intent.getAction();
if (intentAction != null) {
String toastMessage = "unknown intent action";
switch (intentAction) {
case Intent.ACTION_POWER_CONNECTED:
toastMessage = "Power connected";
break;
case Intent.ACTION_POWER_DISCONNECTED:
toastMessage = "Power Disconnected";
break;
case ACTION_CUSTOM_BROADCAST:
toastMessage = intent.getStringExtra("data");
break;
}
Toast.makeText(context, toastMessage, Toast.LENGTH_LONG).show();
}
}
}
package mohammad.samandari.powerreceiver;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends AppCompatActivity {
private static final String ACTION_CUSTOM_BROADCAST = BuildConfig.APPLICATION_ID + ".ACTION_CUSTOM_BROADCAST";
private CustomReceiver mReceiver = new CustomReceiver();
@Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_POWER_CONNECTED);
filter.addAction(Intent.ACTION_POWER_DISCONNECTED);
filter.addAction(ACTION_CUSTOM_BROADCAST);
// Register the receiver using the activity context.
getApplicationContext().registerReceiver(mReceiver, filter);
}
@Override
protected void onDestroy () {
super.onDestroy();
getApplicationContext().unregisterReceiver(mReceiver);
}
public void sendBroadcast (View view) {
Intent intent = new Intent(ACTION_CUSTOM_BROADCAST);
intent.putExtra("data", "Data from the Broadcast");
sendBroadcast(intent);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment