Android applications use broadcasts to communicate with each other. Broadcasts can be sent by either the android system or other applications. Each android application can register it’s interesting broadcast, then it will only receive the interested broadcasts that have been registered.
1. Android Broadcast Principle.
- The broadcast in Android uses the observer pattern, based on the message’s publish/subscribe event model.
- This greatly decouples the sender and receiver of the broadcast, making the system easy to integrate and expand.
1.1 Android Broadcast Process Steps.
- Broadcast receiver registers interested broadcast events to activity manager service.
- The broadcast sender sends a broadcast message to the activity manager service.
- Activity manager service search matched broadcast receiver by registered intent filter and permission.
- If found then send the broadcast to the receiver’s activity message loop queue.
- When the message loop executes and finds this broadcast, then it will execute the BroadcastReceiver‘s onReceive() method.
- From the above process steps, we can get the below conclusions.
- The broadcast sender and the broadcast receiver belong to the message publication and subscription end of the observer pattern.
- Activity manager service is the center of the process, it’s task is to receive the broadcast messages and dispatch the message to the registered receiver.
- The send and receive broadcast actions are asynchronous. The broadcast senders do not care about whether the broadcast message can be received or not as well as when the broadcast message can be received.
2. Android Broadcast Receiver.
2.1 How To Create Android Broadcast Receiver.
- To create and use a broadcast receiver, you should follow the below steps.
- Create a class that extends android.content.BroadcastReceiver.
- Override it’s onReceive(Context context, Intent intent) method.
- When the activity manager service receives matched broadcast message, it will execute the BroadcastReceiver‘s onReceive() method.
- Do not write time-consumed code in this method.
- We will commonly interact with other components in this method, such as sending notifications, startup another service, etc.
2.2 BroadcastReceiver Register Type.
2.2.1 Static Registered Broadcast Receiver.
- Register broadcast receiver in AndroidManifest.xml file.
<application... <receiver android:name="string" android:label="string resource" android:enabled=["true" | "false"] android:icon="drawable resource" android:exported=["true" | "false"] android:permission="string" android:process="string" > . . . </receiver> </application>
- android:name – broadcast receiver class name, do not forget to add package name.
- android:exported – whether this broadcast receiver can receive other App sent broadcast messages or not. The value is true means can receive, false means can not receive. The default value is true.
- android:permission – If set, can only receive broadcast which requires receiver has this permission.
- android:process – broadcast receiver execution process. Default is the app’s execution process.
2.2.1.1 Static Registered Broadcast Receiver Example.
- Below broadcast receiver will process low storage and low battery system events.
- When the receiver belonged app startup, it will register this receiver to the android OS and waiting for the event to occur.
<application... <receiver android:name="com.example.CustomBroadcastReceiver" > <intent-filter> <action android:name="android.intent.action.DEVICE_STORAGE_LOW" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.BATTERY_LOW" /> </intent-filter> </receiver> </application>
2.2.2 Dynamic Registered Broadcast Receiver.
- You can also register a broadcast receiver in java code when your android app executes.
IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE"); networkChangeReceiver = new NetworkChangeReceiver(); registerReceiver(networkChangeReceiver, intentFilter);
- But you also need to unregister it when the app destroy.
@Override protected void onDestroy() { super.onDestroy(); if(this.networkChangeReceiver!=null) { unregisterReceiver(this.networkChangeReceiver); } }
3. Android Broadcast Classification.
3.1 System Broadcast.
- There are multiple system broadcasts built into the Android system, and all the basic phone operations will be broadcast by the system. Such as OS startup, network status change, take photos, screen close and open, light up and down, etc.
- Each system broadcast has a specific intent-filter, which includes specific system pre-defined actions. For example.
- android.intent.action.BATTERY_LOW
- android.intent.action.BATTERY_CHANGED
- android.net.conn.CONNECTIVITY_CHANGE
- android.intent.action.BOOT_COMPLETED
- android.intent.action.DATA_SMS_RECEIVED
- You can find all the system broadcast action lists in the broadcast_actions.txt file which is saved in your android SDK folder like \ Android \ sdk \ platforms \ android-26 \ data \.
3.2 Normal Broadcast.
- Normal broadcasts are fully asynchronous broadcasts, all broadcast receivers receive the broadcast message almost at the same time after the broadcast is sent, so there’s no receive order priority between receivers.
- Developers will define their own intent and action, then use sendBroadcast(Intent intent) method to send it.
- The receiver should have enough permission to receive the broadcast as the sender requires. This kind of broadcast is efficient but cannot be intercepted.
3.3 Ordered Broadcast.
- Ordered broadcasts are simultaneous broadcasts, after the broadcast is sent, the receivers will receive the broadcast message one by one in order by it’s priorities, and the broadcast will continue to be transmitted when the logic of the previous broadcast receiver is completed.
- Therefore, the broadcast receiver is in order, and the high priority receiver can receive the broadcast message first, it can even intercept the broadcast, this will make the low priority broadcast receiver not receive the broadcast message anymore.
- To send an ordered broadcast, you need to first create an intent with custom action value, then use sendOrderedBroadcast(intent, receiverPermission, …) method to send it.
- The received order is decided by all the registered broadcast receiver(dynamic registered or static registered )’s priority value. The bigger the value, the higher the priority.
- For a dynamic registered and static registered broadcast receiver with the same priority value, the dynamic registered receiver will receive the broadcast message first.
3.3.1 Set Broadcast Receiver Priority Example.
- In java source code.
IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE"); intentFilter.setPriority(100);
- In AndroidManifest.xml file.
<application ... <receiver ... <intent-filter android:priority="99"> <action .../> </intent-filter> </receiver> </application>
3.4 Local Broadcast.
3.4.1 In-app broadcast.
- In-app broadcast is the broadcast only sends and receive inside the App application process.
- The broadcast in Android can be cross-processed and even cross-app.
3.4.2 There may be security concerns as following.
- Other App will send broadcast messages to which current App registered, this will make the current App receive and process the broadcast repeatedly.
- Other apps can register the same broadcast intent filter as the current App to steal broadcast messages.
3.4.3 To resolve the above broadcast security issue, we can use the following methods.
- For sending and receiving broadcasts within the same App, the exported attribute should be set to false, so that the current App will not receive income broadcast messages sent from other App.
- When send or receive a broadcast message, add corresponding permission for permission verification.
- Use Intent.setPackage(packageName) to specify the broadcast receiver class package name when send broadcast. So that the broadcast will only be sent to the matched broadcast receiver in the current App.
- The in-App broadcast can be understood as a form of local broadcast, where both the sender and the receiver belong to the same App.
- Instead of using a global broadcast, the local broadcast is more efficient and more secure.
- Android v4 compatible package provides a LocalBroadcastManager class for you to process In-App broadcasts. The usage is similar to normal broadcasts.
// Create a broadcast receiver instance. BroadcastReceiver broadcastReceiver = new BroadcastReceiver(); // Get LocalBroadcastManager instance. LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this); // Register In-App broadcast receiver. localBroadcastManager.registerReceiver(broadcastReceiver, intentFilter); // Unregister In-App broadcast receiver. localBroadcastManager.unregisterReceiver(broadcastReceiver); // Create intent. Intent intent = new Intent(); // Set intent action. intent.setAction(BROADCAST_ACTION); // Send In-App broadcast. localBroadcastManager.sendBroadcast(intent);