Android's BroadcastReceiver Broadcast Receiver Detailed Explanation

One or four components

1.1 The Activity component is a separate window, and the program flow must run in the Activity.

1.2 The service component is used to complete user-specified operations in the background.

1.3 The content provider component will prepare a content window for all applications and retain databases and files.

1.4 The broadcast receiver component is a mechanism for transferring information between programs, and its function is to receive or send notifications.

Two broadcast receiver introduction

2.1 The broadcast receiver is one of the four major components, responsible for the transmission and reception of messages between components.

2.2 Adopt observer mode, message-based publish/subscribe event model, register and receive messages through Binder mechanism.

2.3 Roles in Broadcasting:

  • Message Subscriber (Broadcast Receiver)
  • Message publisher (broadcast publisher)
  • Message Center (AMS, Activity Manager Service)

2.4 Broadcast workflow:

  • The broadcast receiver registers with AMS through the Binder mechanism
  • The broadcast sender sends a broadcast to AMS through the Binder mechanism
  • AMS searches for a suitable broadcast receiver in the registered list according to the requirements of the broadcast sender (search basis: IntentFilter / Permission)
  • AMS sends the broadcast to the corresponding message loop queue of the appropriate broadcast receiver;
  • The broadcast receiver gets the broadcast through the message loop and calls back onReceive()

Tri-Broadcast Registration

3.1 There are two types of registration: static registration and dynamic registration

3.2 Static registration, that is, register in the manifest file

The first step: Create a broadcast receiver BroadcastReceiver, and the broadcast also passes data through Intent.

public class MyReceiver extends BroadcastReceiver {
    private static final String TAG = "MyReceiver";
    @Override
    public void onReceive(Context context, Intent intent) {
        String msg=intent.getStringExtra("msg");
        Log.e(TAG, "onReceive: "+msg);
    }
}

In the second step, the manifest file registers the broadcast

<application
	android:allowBackup="true"
	android:icon="@mipmap/ic_launcher"
	android:label="@string/app_name"
	android:supportsRtl="true"
	android:theme="@style/Theme.MyApplication">

	<receiver android:name=".receiver.MyReceiver"
		android:exported="true"/>
	
</application>

Step 3: Send broadcasts in other components, such as in Activity

private void buttonClick(){
	Intent intent = new Intent(this, MyReceiver.class);
	sendBroadcast(intent);
}

3.3 Note:

Versions after android 8.0 have restrictions on statically registered broadcasts, and custom receivers will not be able to receive broadcasts sent by the sender. The sender needs to set the receiver's package in the intent, and the receiver will receive it. as follows:

Intent intent = new Intent();
intent.setAction("cn.dinghe.test");
intent.setClass(this,Class.forName("cn.dinghe.test.MyReceiver"));
sendBroadcast(intent);

3.4 Dynamic registration: register through registerReceiver

Step 1: create a broadcast receiver as well

public class MyReceiver extends BroadcastReceiver {
    private static final String TAG = "MyReceiver";
    @Override
    public void onReceive(Context context, Intent intent) {
        String msg=intent.getStringExtra("msg");
        Log.e(TAG, "onReceive: "+msg);
    }
}

Step 2: Dynamically register broadcast in components such as Activity

public class MainActivity extends AppCompatActivity {
  
    MyReceiver myReceiver;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //动态注册广播
        myReceiver=new MyReceiver();
        IntentFilter intentFilter=new IntentFilter();
        intentFilter.addAction("com.dinghe.test.myAction");
        registerReceiver(myReceiver,intentFilter);
    }
}

Step 3: Send a broadcast in any component

private void buttonClick(){
	Intent intent=new Intent();
	intent.setAction("com.dinghe.test");
	intent.putExtra("mag","你好啊");
	sendBroadcast(intent);
}

Step 4: Cancel the registration, otherwise it will easily cause memory leaks

@Override
protected void onDestroy() {
	super.onDestroy();
	if (myReceiver!=null){
		unregisterReceiver(myReceiver);
	}
}

Five ordered broadcasts

5.1 Introduction to Orderly Broadcasting:

  • Ordered broadcast is a synchronously executed broadcast. After the broadcast is sent, the broadcast receiver with higher priority can receive the broadcast message first.
  • After executing the logic of the broadcast receiver, you can choose to truncate the broadcast being delivered or continue to deliver it. If the broadcast message is truncated, subsequent broadcast receivers cannot receive the broadcast message.
  • The "ordered" in ordered broadcast is for broadcast receivers. The definition process of an ordered broadcast is the same as that of a normal broadcast, except that the sending method becomes: sendOrderedBroadcast().
  • The receivers of ordered broadcasts will receive them in order according to the predetermined priority, the higher the number, the higher the priority (value range: -1000~10000)
  • Priority can be declared in <intent-filter android:priority="100"/> 
  • You can also call the setPriority() setting of the IntentFilter object
  • Call the abortBroadcast() method to terminate. Once terminated, the receiver cannot accept the broadcast

5.2 Actual combat:

The first step is to create an ordered broadcast receiver

public class MyOrderBroadcastReceiver extends BroadcastReceiver {
    private static final String TAG = "MyOrderBroadcastReceive";
    @Override
    public void onReceive(Context context, Intent intent) {
        String action=intent.getAction();
        String msg=intent.getStringExtra("msg");

        switch (action){
            case "BROADCAST_ACTION1":
                
                break;
            case "BROADCAST_ACTION2":
                
                break;
        }
    }
}

Step 2: Register orderly broadcast in the manifest file and set the priority

<receiver 
    android:name=".MyOrderBroadcastReceiver" >

    <!-- priority优先级:数字越高优先级越高 -->
    <intent-filter android:priority="2">
        <action android:name="BROADCAST_ACTION2" />
    </intent-filter>

    <intent-filter android:priority="1">
        <action android:name="BROADCAST_ACTION1" />
    </intent-filter>
</receiver>

Or dynamically register and set the broadcast priority 

IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("BROADCAST_ACTION2");
intentFilter.setPriority(2);
registerReceiver(mBroadcastReceiver, intentFilter);

Step 3: Send the broadcast

Intent intent = new Intent();
intent.setAction("BROADCAST_ACTION2");
intent.putExtra("msg","你好啊");
sendOrderedBroadcast(intent, null);

Step 4: Intercept the ordered broadcast, and intercept abortBroadcast() in the receiver;

public class MyOrderBroadcastReceiver extends BroadcastReceiver {
    private static final String TAG = "MyOrderBroadcastReceive";
    @Override
    public void onReceive(Context context, Intent intent) {
        String action=intent.getAction();
        String msg=intent.getStringExtra("msg");

        switch (action){
            case "BROADCAST_ACTION1":

                break;
            case "BROADCAST_ACTION2":
                //优先级高,先收到消息,可以拦截断开有序广播,不再执行下一广播
                abortBroadcast();
                break;
        }
    }
}

Six in-app broadcasting (LocalBroadcast)

6.1 The broadcast in Android can communicate directly across processes or even across Apps, and the registration is exported. The default value is true when there is an intent-filter , so there may be potential security risks as follows:

  • Other Apps may send targeted broadcasts that match the intent-filter of the current App, causing the current App to continuously receive and process broadcasts;
  • Other Apps can register the intent-filter consistent with the current App to receive broadcasts and obtain broadcast specific information.

6.2 The solution to the hidden dangers in the payment process is as follows:

  • For sending and receiving broadcasts within the same App, the exported attribute is artificially set to false, so that broadcasts not sent within the App will not be received;
  • When the broadcast is sent and received, the corresponding permission is added for permission verification;
  • When sending a broadcast, specify the package name of the specific broadcast receiver, specifically through intent.setPackage(packageName), so that the broadcast will only be sent to the corresponding valid broadcast receiver in the app in this package .

6.3 LocalBroadcastManage handles in-app broadcasting

The encapsulated LocalBroadcastManager class is given in the Android v4 compatibility package, which is used to uniformly handle the broadcasting problem in the App application. The usage method is almost the same as the usual global broadcasting, except that the main The call context becomes a single instance of LocalBroadcastManager. The usage is as follows:

//registerReceiver(mBroadcastReceiver, intentFilter);
//注册应用内广播接收器
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this);
localBroadcastManager.registerReceiver(mBroadcastReceiver, intentFilter);

//unregisterReceiver(mBroadcastReceiver);
//取消注册应用内广播接收器
localBroadcastManager.unregisterReceiver(mBroadcastReceiver);

Intent intent = new Intent();
intent.setAction(BROADCAST_ACTION);
//sendBroadcast(intent);
//发送应用内广播
localBroadcastManager.sendBroadcast(intent);

Seven common system broadcasting

7.1 Android has built-in multiple system broadcasts: as long as it involves the basic operations of the mobile phone (such as booting, network status changes, taking pictures, etc.), corresponding broadcasts will be sent out.

7.2 When using the system broadcast, you only need to define the relevant action when registering the broadcast receiver, and there is no need to manually send the broadcast. When the system has related operations, the system broadcast will be performed automatically

7.3 Each broadcast has a specific Intent-Filter (including specific action), and the Android system broadcast action is as follows:

Monitor network changes
android.net.conn.CONNECTIVITY_CHANGE

Turn off or turn on airplane mode
Intent.ACTION_AIRPLANE_MODE_CHANGED


Intent.ACTION_BATTERY_CHANGED when charging or when the battery level changes

Low battery
Intent.ACTION_BATTERY_LOW

battery level
Intent.ACTION_BATTERY_OKAY

After the system boot is complete (only broadcast once)
Intent.ACTION_BOOT_COMPLETED


Intent.ACTION_CAMERA_BUTTON when the camera button (hardware button) is pressed

Screen lock screen
Intent.ACTION_CLOSE_SYSTEM_DIALOGS

When the current settings of the device are changed (interface language, device orientation, etc.)
Intent.ACTION_CONFIGURATION_CHANGED


Intent.ACTION_HEADSET_PLUG when headphones are plugged in

When the SD card is not removed correctly but has been taken out (correct removal method: Settings--SD card and device memory--uninstall SD card)
Intent.ACTION_MEDIA_BAD_REMOVAL

Insert external storage device (such as SD card)
Intent.ACTION_MEDIA_CHECKING

Successfully installed APK
Intent.ACTION_PACKAGE_ADDED

Successfully removed APK
Intent.ACTION_PACKAGE_REMOVED

Reboot device
Intent.ACTION_REBOOT

The screen is turned off
Intent.ACTION_SCREEN_OFF

The screen is turned on
Intent.ACTION_SCREEN_ON


Intent.ACTION_SHUTDOWN when shutting down the system

Reboot device
Intent.ACTION_REBOOT

7.4 Examples, such as listening to event minute changes

 Step 1: Create a Time Change Listener

/**
 * 时间更新监听
 */
BroadcastReceiver mTimeUpdateReceiver = new BroadcastReceiver() {
	@Override
	public void onReceive(Context context, Intent intent) {
		if (intent == null) {
			return;
		}
		String action = intent.getAction();
		if (action == null || action.isEmpty()) {
			return;
		}

		if (action.equals(Intent.ACTION_TIME_TICK)) {
			//system every 1 min send broadcast
			
			Log.e(TAG, "onReceive: " + Config.FOOTPRINTTIME);
		}
	}
};

Step 2: Register system monitor

/**
 * 注册时间监听
 */
private void registerUpdateTimeReceiver() {
	//register time update
	IntentFilter filter = new IntentFilter();
	filter.addAction(Intent.ACTION_TIME_TICK);
	registerReceiver(mTimeUpdateReceiver, filter);
}

 Step 3: Cancel the system time monitoring

/**
 * 注销时间监听
 */
private void unRegisterUpdateTimeReceiver() {
	if (mTimeUpdateReceiver != null) {
		unregisterReceiver(mTimeUpdateReceiver);
	}
}

8. Other ways of broadcasting

8.1 The role of broadcasting is to actively monitor and receive data changes, but broadcasting is a system component that needs to pass context, and non-standard use may cause memory leaks. Moreover, the update of the system may limit the use of some functions of the broadcast, so other frameworks based on the publish/subscribe model have emerged, such as the very widely used EventBus.

8.2 EventBus Advantages:

  • Scheduling is flexible and does not depend on Context. When using it, you don't need to pay attention to the injection and delivery of Context like broadcasting.
  • The monitoring and processing of notifications by the parent class can be inherited by subclasses, which is crucial for simplifying the code.
  • The priority of notifications can ensure that Subscriber pays attention to the most important notifications.
  • Sticky events (sticky events) can ensure that the notification will not be ignored due to the absence of the Subscriber

8.3 Of course, both broadcast and EventBus can be used to achieve the mechanism of listening to messages, and you can choose according to your own situation. There are other similar sending/receiving mechanism frameworks, such as RxJava, LiveData, etc. used with network requests.

Guess you like

Origin blog.csdn.net/qq_29848853/article/details/130645245