Today recognize a new Android four components – broadcast. As the name implies, broadcast plays the role of communication, with the purpose of notifying a large number of receiving apps, such as Android system-level broadcast lock screen, unlock, low battery, etc. When these conditions occur, the system will send a broadcast to the app that needs to use it. It is sometimes used for Interprocess communication on Android

The receiver and sender of broadcast belong to the two ends of message publishing and subscription in the observer mode, while AMS belongs to the middle processing center. The execution of broadcast sender and receiver is asynchronous. After the sender sends the message to AMS, it does not care whether the receiver receives it or not

Android broadcast registration

In Android, there are two ways to register a broadcast, the first is static registration and the second is dynamic registration

Dynamic registration

Dynamic registration radio is registered in the code, rather than in the listing file to declare the < receiver / >, the advantage of this way of registration is flexible, and take up less space, only receives the broadcast, the program is run after the program exits, will broadcast the unbundling of in time, to prevent memory leaks, therefore, after the program exits, Is not able to receive the broadcast.

Here is how to dynamically register broadcast, through the code how to achieve

Define a class that extends from BroadcastReceiver

public class LockScreenBroadcastReceiver  extends BroadcastReceiver {

    private final static String TAG = LockScreenBroadcastReceiver.class.getSimpleName();

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();

        if (Intent.ACTION_SCREEN_OFF.equals(action)) {
            Log.e(TAG, "Locked screen.");
        }

        if(Intent.ACTION_SCREEN_ON.equals(action)) {
            Log.e(TAG, "Unlocked"); }}}Copy the code

Two types of broadcast are accepted, lockscreen broadcast and unlock broadcast, and the broadcast event can be retrieved with intent.getAction() of the parameter

Bind broadcast in MainActivity

public class MainActivity extends AppCompatActivity {

    private LockScreenBroadcastReceiver receiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
		
        IntentFilter intentFilter = new IntentFilter();
		
        // Add broadcast events (note that the type of broadcast you want to receive must be added here, otherwise it cannot be received)
        intentFilter.addAction(Intent.ACTION_SCREEN_ON);
        intentFilter.addAction(Intent.ACTION_SCREEN_OFF);

        receiver = new LockScreenBroadcastReceiver();
        registerReceiver(receiver, intentFilter);
    }

    @Override
    protected void onDestroy(a) {
        // Unbind broadcast during Activity destruction to prevent memory leaks
        unregisterReceiver(receiver);
        super.onDestroy(); }}Copy the code

The above method is called dynamically bound broadcast, which does not require any configuration in the manifest file, but can be declared in Java code

Broadcast events are received when the screen is unlocked or locked

E/LockScreenBroadcastReceiver: lock screen E/LockScreenBroadcastReceiver: unlockCopy the code

The static radio

Static broadcasting requires a self-implemented BroadcastReceiver to be defined in a manifest file

<receiver android:name=".LockScreenBroadcastReceiver">
    <intent-filter>
        <action android:name="android.intent.action.SCREEN_OFF"/>
        <action android:name="android.intent.action.SCREEN_ON"/>
    </intent-filter>
</receiver>
Copy the code

You also need to specify the type of broadcast to receive in the intent-filter

Some frequently produce radio, for example, unlocked, the lock screen, low battery tips, etc., using static registration radio is invalid, can only use this to dynamically register radio, 8, the Android Google to static radio laid hands on him, the three of the major application using radio to keep alive, boot from the radio, for example, since the launch of three party applications using this radio service, Sneaking around backstage. While blocking static broadcast using dynamic broadcast can ensure that only the application in the foreground can receive broadcast, and then the corresponding processing

Send broadcast

Our app can also send broadcast, which is mainly divided into orderly broadcast and unordered broadcast. Orderly broadcast receives broadcast layer by layer by defining the priority of broadcast, while unordered broadcast is easier to understand. Once a broadcast is produced, everyone can receive it at the same time

A disorderly radio

Next, we define a broadcast by ourselves to implement out-of-order broadcast. The first example uses self-monitoring broadcast, that is, app sends broadcast and receives it by itself

Broadcast first

public class MainActivity extends AppCompatActivity {

    private final static String TAG = MainActivity.class.getSimpleName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button sendBtn = findViewById(R.id.send_btn);
        sendBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.e(TAG, "Button was clicked, broadcast event has been generated.");
                final String action = "com.sui.CUSTOMER_ACTION";
                Intent intent = new Intent(action);

                if(Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {
                    intent.setComponent(new ComponentName("com.sui.sendstaticbroadcast"."com.sui.sendstaticbroadcast.CustomerBroadcastReceiver"));
                }
				
                // Send unordered broadcast via sendBroadcastsendBroadcast(intent); }}); }}Copy the code

In an Intent, specify the action that sends the broadcast, the identity of the broadcast. Only the broadcast receiver that specifies the identity can receive the broadcast

After Android 8, or API 26, sending a broadcast requires specifying the package name of the broadcast receiver application, as well as the fully qualified class name of the receiver, passed in via ComponentName.

ComponentName The first parameter is the receiver’s application package name, and the second parameter is the receiver’s fully qualified class name

Then create a broadcast receiver and register it in the manifest file

public class CustomerBroadcastReceiver extends BroadcastReceiver {

    private static final String TAG = CustomerBroadcastReceiver.class.getSimpleName();

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();

        if("com.sui.CUSTOMER_ACTION".equals(action)) {
            Log.e(TAG, "Custom broadcast event received"); }}}Copy the code
<receiver android:enabled="true" android:name=".CustomerBroadcastReceiver">
    <intent-filter>
        <action android:name="com.sui.CUSTOMER_ACTION"/>
    </intent-filter>
</receiver>
Copy the code

Start the APP, click the button to generate broadcast, you can see the custom broadcast sending and monitor the printed Log

E/MainActivity: button is clicked, has produced a broadcast event E/CustomerBroadcastReceiver: receive custom broadcast eventsCopy the code

If you want to receive custom broadcasts in other apps, you need to specify the package name of the receiver app and the fully qualified class name of the receiver by specifying the package name of the receiver by specifying the fully qualified class name of the receiver when generating broadcasts. Otherwise, the receiver cannot receive the broadcasts.

Orderly broadcast

Ordered broadcast can receive broadcast messages in hierarchic levels, which are created by specifying the priority of the broadcast receiver. Officially, the priority is [-1000, 1000], but in fact, it is within the integer range [-2147483648, 2147483647]. The higher the number, the higher the priority. The sooner you receive the broadcast

Create three broadcast receivers

public class MyBroadcastReceiver {

    private final static String TAG = MyBroadcastReceiver.class.getSimpleName();

    public static class HighBroadcastReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if ("com.sui.CUSTOMER_ACTION".equals(action)) {
                boolean orderedBroadcast = isOrderedBroadcast();
            			Log.e(TAG, "Is it an orderly broadcast?" + orderedBroadcast);
                Log.e(TAG, "I am HighBroadcastReceiver");
                int code = 0;
                String data = "Hello";
                Bundle bundle = null; setResult(code, data, bundle); }}}public static class MidBroadcastReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if ("com.sui.CUSTOMER_ACTION".equals(action)) {
                Log.e(TAG, "I am MidBroadcastReceiver");

                int resultCode = getResultCode();
                String resultData = getResultData();

                Log.e(TAG, "result code: " + resultCode + " resultData: " + resultData);

                resultCode += 1;
                resultData += "World";

                setResult(resultCode, resultData, null); }}}public static class LowBroadcastReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if ("com.sui.CUSTOMER_ACTION".equals(action)) {
                Log.e(TAG, "I am LowBroadcastReceiver");

                int resultCode = getResultCode();
                String resultData = getResultData();

                Log.e(TAG, "result code: " + resultCode + " resultData: "+ resultData); }}}}Copy the code

Register broadcast receivers dynamically in MainActivity and set different priorities for the three broadcast receivers

public class MainActivity extends AppCompatActivity {

    private static final String TAG = MainActivity.class.getSimpleName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        init();

        Button sendBtn = findViewById(R.id.send_btn);
        sendBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.e(TAG, "Generated a broadcast message.");
                Intent intent = new Intent("com.sui.CUSTOMER_ACTION");

                intent.putExtra("count".100);
				
                // The method used to send an ordered broadcast
                sendOrderedBroadcast(intent, null); }}); }public void init(a) {
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("com.sui.CUSTOMER_ACTION");
        
        intentFilter.setPriority(3000);
        registerReceiver(new MyBroadcastReceiver.HighBroadcastReceiver(), intentFilter);
        intentFilter.setPriority(2000);
        registerReceiver(new MyBroadcastReceiver.MidBroadcastReceiver(), intentFilter);
        intentFilter.setPriority(1000);
        registerReceiver(newMyBroadcastReceiver.LowBroadcastReceiver(), intentFilter); }}Copy the code

If no priority is specified, broadcasts are received in the order they were registered

In the broadcast receiver, the isOrderedBroadcast() method can be used to determine whether the broadcast is ordered or not, and abortBroadcast() can be used to terminate the broadcast when the broadcast is ordered, that is, the broadcast is not propagated downward, as shown in the following example

public static class HighBroadcastReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        boolean orderedBroadcast = isOrderedBroadcast();
        Log.e(TAG, "Is it an orderly broadcast?" + orderedBroadcast);
        String action = intent.getAction();
        if ("com.sui.CUSTOMER_ACTION".equals(action)) {
            Log.e(TAG, "I am HighBroadcastReceiver");
            int code = 0;
            String data = "Hello";
            Bundle bundle = null;

            setResult(code, data, bundle);
			
            // Terminate the broadcastabortBroadcast(); }}}Copy the code

The setResult() and getResult() methods can only be used in ordered broadcasts, and using them in unordered broadcasts will result in an error

When the system or other application broadcasts a broadcast, the Android system checks whether the BroadcastReceiver is configured for each installed app. If the BroadcastReceiver action is configured, the Android system instantiates the BroadcastReceiver, and then executes the Receiver () method. The BroadcastReceiver is instantiated only after it matches the action!!

Broadcasts have a very short lifetime and do not perform time-consuming operations on the receiver, which will throw an ANR exception if the result is not returned for 10s (the data says 10s, but I tried 15s without ANR)