List broadcast restrictions

As of Android O version (Android 8.0, API 26), broadcast receivers registered in Androidmanifest.xml cannot receive implicit broadcasts.

Since an implicit broadcast cannot be received, an explicit broadcast can be sent, for example by specifying the packet name of the receiver at the time the broadcast is sent

Intent intent = new Intent("some_action");
// Specify the receiver's packet name to send an explicit broadcast
intent.setPackage("receiver_package");
sendBroadcast(intent);
Copy the code

If you’re a system developer, you can also get around this limitation by adding a flag

Intent intent = new Intent("some_action");
// This flag indicates that manifest registered broadcast receivers can also receive implicit broadcasts
intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
sendBroadcast(intent);
Copy the code

Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND is not available to third-party applications. However, third-party applications can override this limitation by replacing the flag with a corresponding value

Intent intent = new Intent("some_action");
// Third-party applications specify values directly
intent.addFlags(0x01000000);
sendBroadcast(intent);
Copy the code

Add permissions for broadcasts

Adding permissions to a broadcast limits the sender or receiver of the broadcast for filtering purposes.

Restricted receiver

If now want to send a broadcast, we don’t hope everyone can receive the broadcast, we may take into consideration in the use of the Context. The sendBroadcast () or Context. SendOrderedBroadcast () to send with a limit parameters. We can use system permissions, or we can redefine a permission.

If you now want to send a broadcast with custom permissions, you first define the permissions in androidmanifest.xml

<permission android:name="com.bxll.sender.receiver_permission"/>
Copy the code

This permission is then passed to the method as a parameter when the broadcast is sent

Intent intent = new Intent("some_action");
sendBroadcast(intent, "com.bxll.sender.receiver_permission");
Copy the code

The second argument to sendBroadcast() is the custom permission. Of course, if you want the broadcast receiver registered with the manifest to receive the broadcast, you have to do the same.

In order to receive this broadcast, the receiving application must apply for this permission in androidmanifest.xml

<uses-permission android:name="com.bxll.sender.receiver_permission" />
Copy the code

Limit sender

Suppose we already have a broadcast receiver, and we don’t want everyone to be able to send broadcasts to this receiver, we can add a permission when registering the broadcast receiver.

Also, if you add custom permissions, you must first define them in androidmanifest.xml

<permission android:name="com.bxll.receiver.sender_permission" />
Copy the code

Then use this permission during registration. We know that there are two ways to register broadcast receivers, one is dynamic registration, the other is static registration.

For static registration, the code in androidmanifest.xml is as follows

        <receiver android:name=".MyReceiver" 
                  android:permission="com.bxll.receiver.sender_permission">
            <intent-filter>
                <action android:name="com.bxll.reciever.action" />
            </intent-filter>
        </receiver>
Copy the code

For dynamic registration, such as in an Activity, the code is as follows

IntentFilter filter = new IntentFilter("com.bxll.reciever.action");
registerReceiver(receiver, filter, "com.bxll.receiver.sender_permission".null);
Copy the code

The sender of the broadcast can send the broadcast to the receiver as long as it has requested the permission in androidmanifest.xml

<uses-permission android:name="com.bxll.receiver.sender_permission" />
Copy the code

Note that you no longer need to carry the permission parameter!!!! when sending a broadcast

summary

Whether you add permission when you send a broadcast or when you register a broadcast receiver, you just need to apply for this permission in the other party’s Androidmanifest.xml, and no extra processing is required.

Effects of broadcast receivers on host process state

When a broadcast receiver’s onReceive() is executed, the system assumes that the host process of the broadcast receiver handles the foreground and keeps the process running except when the system runs out of memory.

However, when the broadcast receiver’s onReceive() method completes and the host has only one broadcast receiver running, the system assumes that the host process is handling a low-priority state and is likely to kill the process to free resources.

Therefore, we should not create a background thread in onReceive() for processing tasks (the broadcast receiver is executed in the main thread) because the host process may be killed and the background thread terminated. If we have a situation where we must process tasks in the background thread, we can use JobScheduler to schedule future tasks or call goSync() to indicate that you need more time in the background so that the system knows that the process needs to continue executing the task and won’t kill the process under normal circumstances.

public class MyBroadcastReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        final PendingResult pendingResult = goAsync();
        Task asyncTask = new Task(pendingResult);
        asyncTask.execute();
    }

    private static class Task extends AsyncTask<String.Integer.String> {

        private final PendingResult pendingResult;

        private Task(PendingResult pendingResult) {
            this.pendingResult = pendingResult;
        }

        @Override
        protected String doInBackground(String... strings) {
			// Perform time-consuming tasks here
            return "some_result";
        }

        @Override
        protected void onPostExecute(String s) {
            // Notifies the system that the task is completependingResult.finish(); }}}Copy the code

Call the goSync() method in onReceive() to notify the system process that it needs more time to process the task. GoSync () returns a PendingResult object. When the task is complete, You also need to call Finish () of PendingResult to notify the system that the background tasks of the process are complete, and the system will decide whether to kill the process to release resources.