Basic use of Android Broadcast

Keywords: Android network xml

1. What is broadcasting
Broadcast mechanism is used for process/thread communication. The main feature of broadcasting is that the sender does not care whether the recipient receives data or how the recipient processes the data. It is only responsible for saying, regardless of whether you listen or not. Broadcast can come from systems or other applications.

  • Sort by Send Method:

    Standard broadcasting: A completely asynchronous broadcast with no sequence. All broadcasting receivers receive this broadcast message almost at the same time. It is efficient and cannot be truncated.
    Ordered broadcast: A synchronized broadcast in sequence in which only one receiver can receive the broadcast message at a time, a higher priority broadcast receiver can receive the broadcast message first, and the front broadcast receiver can also truncate the ongoing broadcast so that the later broadcast receiver cannot receive the broadcast message.

  • Classify by Registration Method
    Static broadcast: listens regardless of whether the application is active or not
     Dynamic broadcasting: Register in code, note that dynamically registered broadcasts must be unregisterReceiver() method called in onDestroy() method to implement
    Static broadcast: A new Receiver object is created each time it is triggered.
    Dynamic broadcasting: The same Receiver will be used from creation until it is unregistered, regardless of how many times the broadcast is triggered;
  • Classify by definition

    System Broadcasting: There are multiple system broadcasts built into the Android system. Each system broadcasting has a specific intent-filter, which mainly includes specific action s. Once the system broadcasts are sent, they will be received by the corresponding BroadcastReceiver.System broadcasts are automatically sent out by the system when a specific event occurs within the system.
    Custom broadcasts: broadcasts defined by application developers themselves

2. Why use broadcasting (when use broadcasting)

  • For example, when a push message is received, the number of message displays on the current page changes, which can then be used for broadcasting;
  • For example, qq and other disconnected network or network When disconnected to a normal connection, monitor network status changes, which can be used for broadcasting

In fact, the places where broadcasts are needed are everywhere, but some have been replaced by third-party libraries, such as rxbus, EventBus, etc.

3. Use of broadcasting

  1. Static Broadcast
    In the application of AndroidManifest.xml, receiver s are defined and actions to be received are set. MyReceiver overrides the onReceiver method to inherit the class of BroadcastReceiver and processes broadcasts in the onReceiver method.The <intent-filter>tag sets the filter to receive the specified action broadcast.

    • register
         <receiver android:name=".MyReceiver">//Specify Broadcast Receiver
             <intent-filter android:priority="100">//Set shutdown priority
                 <action android:name="XXX"></action>//Determine the radio channel you want to receive (custom name)
             </intent-filter>
         </receiver>
      Feature: The application will listen regardless of whether it is active or not
    • Send out
         Intent intent = new Intent("XXX");//xxx is action
         intent.putExtra("key", "To pass value");
         sendBroadcast(intent);
    • Receive
      public class MyReceiver extends BroadcastReceiver {
      //Can't do a good job on onReceiver
      @Override
      public void onReceive(Context context, Intent intent) {
         String value = intent.getStringExtra("test");
         Toast.makeText(context, value, Toast.LENGTH_LONG).show();
      }
      }
  2. Dynamic Broadcasting

    • register
      MyReceiver myReceiver= new MyReceiver();
      IntentFilter filter = new IntentFilter();
      filter.addAction("XXX");   //Add Action Condition
      //filter.setPriority(Integer.MAX_VALUE); //In an ordered broadcast his priority can be set
      registerReceiver(myReceiver, filter);  //Method of registering receiver: 1. Entity class of receiver 2. Information of action channel
    • Send out:
      Intent intent = new Intent();
      intent.setAction("XXX");
      intent.putExtra("key", "Delivered value");
      sendBroadcast(intent);
    • Receive
      public class MyReceiver2 extends BroadcastReceiver {
      @Override
      public void onReceive(Context context, Intent intent) {
         String value = intent.getStringExtra("value");
         Toast.makeText(context, value, Toast.LENGTH_LONG).show();
      }
      }
    • Cancellation:
      @Override
      protected void onDestroy() {
         super.onDestroy();
         unregisterReceiver(myReceiver);//Logoff Receiver
      }
  3. Ordered Broadcasting

    • register

         <! -- Actions identically indicate a channel, and priority sets the priority level (lower numbers lower priorities, upper Integer.MAX, lower Integer.MIN, -1000~1000-->
         <!--export=false means that only this application's broadcasts are accepted, and external app's broadcasts are not accepted-->
         <receiver android:name=".MyReceiver1" android:exported="false">
             <intent-filter android:priority="100">
                 <action android:name="Test"/>
             </intent-filter>
         </receiver>
          <receiver android:name=".MyReceiver2">
             <intent-filter android:priority="-100">
                 <action android:name="Test"/>
             </intent-filter>
         </receiver>
    • Send out

      Intent intent2 = new Intent();
      intent2.setAction("Test");
      intent2.putExtra("key1", "Launched");
      sendOrderedBroadcast(intent2, null);//(null does not match permissions)
    • Receive

      public class MyReceiver1 extends BroadcastReceiver {
      @Override
      public void onReceive(Context context, Intent intent) {
         Toast.makeText(context, intent.getStringExtra("key1"), Toast.LENGTH_LONG).show();
         setResultData("I'm also going to launch");//To subsequent receivers
      }
      }
      public class MyReceiver2 extends BroadcastReceiver {
      @Override
      public void onReceive(Context context, Intent intent) {
         Toast.makeText(context, getResultData(), Toast.LENGTH_SHORT).show();
         //abortBroadcast();//interrupt all subsequent receivers
      }
      }

    Broadcast security issues

    1. Set export=false for intent-filter (only broadcasts for this application are accepted, not for external apps)
    2. When broadcasting is sent and received, a corresponding permission is added for permission validation.
    3. When sending a broadcast, specify the package name where the particular broadcast receiver is located, specifically through intent.setPackage(packageName), so that the broadcast will only be sent to a valid broadcast receiver that matches it within App in the package;
    4. Use LocalBroadcastManager.
  4. Local BroadcastManager uses
    Can only register dynamically, not statically

    public class MainActivity extends AppCompatActivity {
     private IntentFilter intentFilter;
     private LocalReceiver localReceiver;
     private LocalBroadcastManager localBroadcastManager;
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
         Button button = (Button) findViewById(R.id.button);
         button.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
                 Intent intent = new Intent("com.example.broadcasttest.LOCAL_BROADCAST");
                 localBroadcastManager.sendBroadcast(intent); // Send local broadcasts
             }
         });
         localBroadcastManager = LocalBroadcastManager.getInstance(this); // Get Instances
         localReceiver = new LocalReceiver();
         intentFilter = new IntentFilter();
         intentFilter.addAction("com.example.broadcasttest.LOCAL_BROADCAST");
         localBroadcastManager.registerReceiver(localReceiver, intentFilter); // Register local broadcast listeners
     }
    
     @Override
     protected void onDestroy() {
         super.onDestroy();
         localBroadcastManager.unregisterReceiver(localReceiver);
     }
    
     class LocalReceiver extends BroadcastReceiver {
         @Override
         public void onReceive(Context context, Intent intent) {
             Toast.makeText(context, "received local broadcast", Toast.LENGTH_SHORT).show();
         }
     }
    }
  5. Sticky Broadcast
    Sticky Broadcast was abandoned after 5.0, so there's no need to talk about it now
  6. Custom broadcast rights

    • Static Registration
              <receiver
                   android:name=".MyBroadcastReceiver"
                   android:exported="false"
                   android:permission="com.lazyxu.permission.test">
                   <intent-filter>
                       <action android:name="action.name"/>
                   </intent-filter>
               </receiver>
    • Dynamic Registration

         MyBroadcastReceiver receiver = new MyBroadcastReceiver();
         IntentFilter intentFilter = new IntentFilter();
         intentFilter.addAction("action.name");
         intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
         //When registering receivers, specify directly what permissions the sender should have.Otherwise, external applications can still reach the receiver
         registerReceiver(receiver, intentFilter, "com.lazyxu.permission.test", null);

      When registering, the most critical point is to register with registerReceiver(BroadcastReceiver, IntentFilter, String, Handler), instead of registerReceiver(BroadcastReceiver, IntentFilter).In contrast to the latter, the former requires the sender to have permissions when registering.If the sender does not have this privilege, the broadcast sent by the sender will not be received by the receiver even though it is filtered by IntentFilter.At this point, if you customize another permission and set the protectionLevel of the permission to signature, the permission cannot be used by an external application and the receiver cannot be reached.

    • Send a broadcast

         Intent intent = new Intent("action.name");
         sendBroadcast(intent,"com.lazyxu.permission.test");

      You also need to define permissions in the manifest file and declare them

        <permission
           android:name="com.lazyxu.permission.test"
           android:label="BroadcastReceiverPermission"
           android:protectionLevel="signature">
         </permission>
         <uses-permission android:name="com.lazyxu.permission.test"/>

      When customizing permissions, the protectionLevel property is usually specified, as follows:

      normal: By default, users can see the appropriate permissions before the application is installed, but no user's active authorization is required.
      Dangerous: Any dangerous operation other than normal security level control.When dangerous level permissions are required, Android explicitly requires authorization from the user.Common examples are: network usage rights, camera usage rights and contact information usage rights.
      Signature: It requires both the permission declaration application and the permission use application to be signed using the same keystore.If the same keystore is used, the permission is granted by the system, otherwise it will be denied.Users are not notified when permissions are granted.It is often used internally.Declare protectionLevel as a signature, and if other applications do not use the same signature file, they will not be able to use that privilege, thereby protecting their recipients.

Be careful

  1. If BroadcastReceiver's onReceiver() method does not complete in 10 seconds, Android will assume the program is unresponsive.Do not perform time-consuming operations in onReceiver(), otherwise the ANR(Application No Response) dialog box will pop up.If you need to complete a time-consuming operation based on Broadcast, consider starting a Service with Intent to complete the operation.Don't win Consider using a new thread to complete time-consuming operations, because BroadcastReceiver itself has a short life cycle, and it may appear that the subthread has not finished yet and BroadcastReceiver has exited.
  2. BroadcastReceiver itself is not a Context and does not have a Context inside, but it has a context parameter in onReceive(Context context, Intent intent).This context varies with how receiver s are registered:
    Static registration: context is ReceiverRestrictedContext
    Dynamic registration: contexts are contexts of activities
    Dynamic Registration of LocalBroadcastManager: Context is the context of the Application
  3. Statically registered broadcast receivers can still receive an app as long as it has the appropriate broadcast, even if the app exits, but may not be established since Android 3.1
    • For system broadcasts, this intent flag value cannot be changed because it is emitted directly from within the system, and the flag value is added directly by default to FLAG_EXCLUDE_STOPPED_PACKAGES. Therefore, 3.1 will start BroadcastReceiver for Statically Registered Receiving System Broadcasts and will not receive broadcasts if the App process has exited.
    • For custom broadcasts, the static registered BroadcastReceiver can receive broadcasts and start the application process by copying flag to FLAG_INCLUDE_STOPPED_PACKAGES, even if App exits, but at this time the BroadcastReceiver is newly created.
      The implementation code is:
      Intent intent = new Intent();
      intent.setAction(BROADCAST_ACTION);
      intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
      sendBroadcast(intent);

Posted by liquidd on Sun, 16 Jun 2019 09:11:45 -0700