The role of the BroadcastReceiver

Broadcast is a widely used mechanism for transmitting information between applications. It is mainly used to listen to broadcast information sent by the system or application, and then process the broadcast information as the corresponding logic. It can also be used to transmit small amounts of low-frequency data.

In the realization of boot service and network state change, power change, SMS and call through receiving system broadcast so that the application to make the corresponding processing.

The BroadcastReceiver itself does not implement a graphical user interface (GUI), but when it receives a notification, it can start a Service, start an Activity, or notify the user.

BroadcastReceiver uses caution points

When the system or application sends a broadcast, it will scan all the broadcast receivers in the system and send the broadcast to the corresponding receiver through action matching. After the receiver receives the broadcast, it will generate an instance of the broadcast receiver and execute the onReceiver() method. It is important to note that the lifetime of this instance is only 10 seconds, and if the onReceiver() is not executed within 10 seconds, the system will report an error.

After onReceiver() completes, the instance is destroyed, so do not perform time-consuming operations in onReceiver(), and do not create child threads in it to handle business (because it is possible that the receiver will be reclaimed before the child thread completes, and the child thread will also be reclaimed); The correct way to do this is to call the activity or service through in.

The registration of the BroadcastReceiver

BroadcastReceiver can be registered in only two ways, one is static registration (recommended), and the other is dynamic registration. Broadcast receivers listen for broadcast messages sent between systems or applications after registering.

Example of SMS broadcast receiver:

Customize the BroadcastReceiver class

Public class MyBroadcastReceiver extends BroadcastReceiver {// Action name String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED" ; public void onReceive(Context context, Intent.getaction ().equals(SMS_RECEIVED)) {// Intent.getAction ().equals(SMS_RECEIVED)) You need to judge the intent. GetAction (Action name) in onReceive. }}}Copy the code

The static way

In the Androidmanifest.xml application, define the receiver and set the action to receive.

< receiver android:name = ".MyBroadcastReceiver" > 

 < intent-filter android:priority = "777" >             
<action android:name = "android.provider.Telephony.SMS_RECEIVED" />
</ intent-filter > 

</ receiver >
Copy the code

The value of priority ranges from -1000 to 1000. A larger value indicates a higher priority. Note that the system has a limit on receiving SMS messages.

< uses-permission android:name ="android.permission.RECEIVE_SMS" />
Copy the code

A static BroadcastReceiver is a global listener that is resident in the system. When you install a BroadcastReceiver in an application, the BroadcastReceiver is resident in the system regardless of whether the application is running. Also, all receivers in the application are in the manifest file for easy viewing.

To destroy statically registered broadcast receivers, the Receiver can be disabled by calling the PackageManager.

Dynamic way

Declare the BroadcastReceiver extension object in the Activity, register it in onResume, and uninstall it in onPause.

public class MainActivity extends Activity { MyBroadcastReceiver receiver; // BroadcastReceiver = new MyBroadcastReceiver(); // Override protected void onResume(); IntentFilter intentFilter = new IntentFilter( "android.provider.Telephony.SMS_RECEIVED" ); registerReceiver( receiver , intentFilter); super.onResume(); } @override protected void onPause() {unregisterReceiver(receiver); super.onPause(); }}Copy the code

The difference between static and dynamic registration

1. The statically registered broadcast receiver is resident in the system once it is installed, and there is no need to restart to wake up the receiver;

Dynamically registered broadcast receivers as the application life cycle, registerReceiver starts listening, unregisterReceiver unregisterReceiver unregisterReceiver unregisterReceiver unregisterReceiver unregisterReceiver unregisterReceiver unregisterReceiverCopy the code

2. When the broadcast receiver starts an activity or service with an intent, if the intent does not match the corresponding component.

Dynamically registering broadcast receivers will cause an application error. Statically registered broadcast receivers will not report any errors because the broadcast receivers have been disconnected from the application since the application was installed.Copy the code

Send a BroadcastReceiver

There are two main types of sending broadcasts:

Ordinary radio

The application is used in situations where each broadcast receiver needs to be notified, such as boot upCopy the code

Usage: sendBroadcast()

Intent intent = new Intent("android.provider.Telephony.SMS_RECEIVED"); Intent. PutExtra ("data", "finch"); // Perform an intent with a small amount of data. SendBroadcast (Intent);Copy the code

Normal broadcasts are completely asynchronous and can be received (logically) by all receivers at the same time, and all qualified BroadcastReceivers randomly execute their onReceive() method.

The order of acceptance at the same level is random;

The message transmission efficiency is relatively high, and the broadcast cannot be interrupted.

     

Orderly broadcast

It can be used in specific interception scenarios, such as blacklist SMS and call interception.Copy the code

Usage:

sendOrderedBroadcast(intent, receiverPermission);

ReceiverPermission: A receiver must be held to receive your broadcast. If null, no permission required (generally null).

SendOrderedBroadcast (Intent, null);Copy the code

In an ordered broadcast, we can either pass the processed data from the previous broadcast receiver to the subsequent broadcast receiver or terminate the broadcast by calling abortBroadcast().

Public void onReceive(Context arg0, Intent Intent) {public void onReceive(Context arg0, Intent Intent) {public void onReceive(Context arg0, Intent Intent) //true: create a new Bundle if there is no result from the previous broadcast; False: do not create Bundle bundle.putString("key", "777"); // Put the bundle data into the broadcast to the next broadcast receiver setResultExtras(bundle); // abortBroadcast to the next broadcast receiver abortBroadcast(); }Copy the code

After receiving the broadcast, a higher-level broadcast may decide whether to cut it off.

The order of same-level receives is random. If the first recipient truncates the broadcast, the other recipients of the same level cannot receive the broadcast.

Asynchronous broadcasting

Usage: sendStickyBroadcast() :

The outgoing Intent will be held to be re-broadcast to the future when the receiving Activity resumes its onResume state Receivers). This means that the last Intent sent by sendStickyBroadcast is retained and will be received the next time the Activity is active.

This broadcast requires permissions:

<uses-permission android:name="android.permission.BROADCAST_STICKY" />
Copy the code

Uninstall this broadcast:

removeStickyBroadcast(intent);
Copy the code

The intent is retained until unloaded, and is available to the recipient in the received state.

Asynchronous ordered broadcast

Method of use: sendStickyOrderedBroadcast (intent, resultReceiver, scheduler, initialCode, initialData and initialExtras) :

This method has both ordered broadcast and asynchronous broadcast properties; At the same time, it is necessary to limit rights:

 <uses-permission android:name="android.permission.BROADCAST_STICKY" /> 
Copy the code

summary

  

  • The processor for receiving static broadcast is PackageManagerService. When the phone is started or a new application is installed, PackageManagerService scans all installed apps on the phone. Parses the information about registered broadcasts from androidmanifest.xml and stores it in a global static variable.

  • The active broadcast receiver handler is handled by ActivityManagerService. When the APP service or process is up, the code logic that registers the broadcast receiver is loaded and stored in another global static variable. Note that:

1. This is not static, when the program is killed, the registered dynamic broadcast receiver will be removed from the global variable, until the next program starts, the dynamic broadcast registration, of course, the order has been changed once.

2. There is no complete sorting of broadcast, only the order of registration is recorded, and there is no processing combined with priority.

  • When a broadcast is sent, the broadcast receiver receives it in the following order:

1. When the broadcast is a normal broadcast, the receiving sequence is as follows:

Ignore dynamic broadcast receivers that have priority over static receivers of the same priority, the first registered receivers are greater than the last registered static receivers of the same priority, and the first scanned receivers are greater than the last scanned receiversCopy the code

2. If the broadcast is an ordered broadcast, the dynamic and static broadcast handlers are combined to process the broadcast messages, ultimately determining the order in which the broadcast is received:

Dynamic receivers with the same priority receive dynamic receivers with the same priority first, dynamic receivers have precedence over static receivers with the same priority, static receivers registered first are greater than static receivers with the same priority registered later, and static receivers scanned first are greater than those scanned laterCopy the code

Common system-broadcast actions and permissions

  • Powered up
<action android:name="android.intent.action.BOOT_COMPLETED"/> 
Copy the code
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />  
Copy the code
  • The network status
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>  
Copy the code
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> 
Copy the code

Methods for whether the network is available:

public static boolean isNetworkAvailable(Context context) { ConnectivityManager mgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo[] info = mgr.getAllNetworkInfo(); if (info ! = null) { for (int i = 0; i < info.length; i++) { if (info[i].getState() == NetworkInfo.State.CONNECTED) { return true; } } } return false; }Copy the code
  • Electricity changes
<action android:name="android.intent.action.BATTERY_CHANGED"/>  
Copy the code

BroadcastReceiver onReceive method:

public void onReceive(Context context, Intent intent) { int currLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0); Int total = intent.getintextra (batteryManager.extra_scale, 1); Int percent = currLevel * 100 / total; Log.i(TAG, "battery: " + percent + "%"); }Copy the code