What is a Broadcast Receiver
A Broadcast Receiver is one of the four components and is a mechanism widely used to transmit information between applications. It transmits our data by sending intents.
Broadcast Receiver usage scenarios
- Communication of messages between different components within an application.
- Message communication across application components.
Types of Broadcast receivers
- In order of dispatch
- Standard broadcast: also known as out-of-order broadcast, in fact, out-of-order broadcast, broadcast sent together to all people completely asynchronous execution, all broadcast receivers almost at the same time, high efficiency, cannot be truncated.
- Ordered broadcast: Simultaneous broadcast, sent in priority order, only one broadcast received at a time, the preceding broadcast may be truncated.
- By sending range
- Global broadcast: outgoing broadcast can be received by any other application, and we can also receive broadcast from any other application, the data is not secure.
- Local broadcast: can only be transmitted within the application, and the broadcast receiver can only receive the broadcast from the application, other software will not listen to our broadcast data.
- According to the Broadcast Receiver implementation
- Static registration: declared in androidmanifest.xml with the receive tag. The broadcast registered in this way is resident broadcast. After registration, even if the application is not running, it can also receive the broadcast, such as the common startup monitor.
- Dynamic registration: registered in code, must start the software to receive the broadcast; In addition, dynamically registered broadcast receivers must all be unregistered. Follow the Activity lifecycle
Use of Broadcast receivers
The use of radio consists of the following steps:
- Custom broadcast receiver: override onReceiver()
- Register broadcast receivers to the message center (AMS) : dynamic (registerReceiver in code) or static (declared in Androidmanifest.xml)
- Definition and broadcast to the message center (AMS) : Context. The sendBroadcast (), the Context, sendOrderedBroadcast;
- AMS selects and sends the broadcast to the appropriate broadcast receiver (according to intent-filter, Permission)
- The broadcast receiver gets the broadcast through the message loop and calls onReceive() to process it
The above steps 1-3 should be completed by the developer, and steps 4-5 should be completed by the Android system.
Sample:
4.1 Static Registration
- 4.1.1 Define BroadcastReceiver, inherit BroadcastReceiver base class and override onReceive() :
public class SCCReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.e(getClass().getName(),"SCCReceiver, passing content:"+intent.getStringExtra("scc")); }}Copy the code
- 4.1.2 Declare through receive tag in Androidmanifest.xml
<receiver
android:name=".SCCReceiver"
android:enabled="true"
android:exported="true"/>
Copy the code
- 4.1.3 Sending Broadcasts
- activity_main.xml
<? xml version="1.0" encoding="utf-8"? > <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical">
<Button
android:id="@+id/btn_send"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Send a static broadcast" />
</LinearLayout>
Copy the code
- MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.btn_send).setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_send:
Log.e(getClass().getName(),Click on the "R.i db tn_send");
Intent intent = new Intent(this, SCCReceiver.class);
intent.putExtra("scc"."Really handsome.");
sendBroadcast(intent);
break; }}}Copy the code
- Click Send static broadcast to achieve the following effect
4.2 Dynamic Broadcast
- 4.2.1 to customize BroadcastReceiver, inherit BroadcastReceiver base class and override onReceive() :
public class SCCReceiver2 extends BroadcastReceiver {
public static final String ACTION = "com.scc.broadcastreceiver.SCCReceiver";
@Override
public void onReceive(Context context, Intent intent) {
Log.e(getClass().getName(),"SCCReceiver2, pass content:"+intent.getStringExtra("scc")); }}Copy the code
- 4.2.2 Registering broadcast
BroadcastReceiver (BroadcastReceiver, IntentFilter filter); BroadcastReceiver (BroadcastReceiver, IntentFilter filter); IntentFilter indicates the filter criteria.
private SCCReceiver2 sccReceiver2;
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_reg:
Log.e(getClass().getName(),Click on the "R.i db tn_reg");
if (sccReceiver2 == null) {// Prevent duplicate registrations
sccReceiver2 = new SCCReceiver2();
registerReceiver(sccReceiver2, new IntentFilter(SCCReceiver2.ACTION));
}
break; }}Copy the code
-
4.2.3 Sending Broadcasts
-
actvitiy_main.xml
<? xml version="1.0" encoding="utf-8"? > <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical">
<Button
android:id="@+id/btn_reg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Register for Live Broadcast" />
<Button
android:id="@+id/btn_unreg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Log off dynamic Broadcast" />
<Button
android:id="@+id/btn_send_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Send dynamic broadcast" />
</LinearLayout>
Copy the code
- MainActivity.java
private SCCReceiver2 sccReceiver2;
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_reg:
Log.e(getClass().getName(),Click on the "R.i db tn_reg");
if (sccReceiver2 == null) {// Prevent duplicate registrations
sccReceiver2 = new SCCReceiver2();
registerReceiver(sccReceiver2, new IntentFilter(SCCReceiver2.ACTION));
}
break;
case R.id.btn_unreg:
Log.e(getClass().getName(),Click on the "R.i db tn_unreg");
if(sccReceiver2 ! =null) {// Prevent duplicate logout
unregisterReceiver(sccReceiver2);
sccReceiver2 = null;
}
break;
case R.id.btn_send_action:
Log.e(getClass().getName(),Click on the "R.i db tn_send_action");
Intent intentAction = new Intent(SCCReceiver2.ACTION);
intentAction.putExtra("scc"."Dynamic, really cool.");
sendBroadcast(intentAction);
break; }}Copy the code
- Click Register dynamic > Send Dynamic Broadcast to achieve the following effect:
- 4.2.4 Deregistering broadcasts
UnregisterReceiver (BroadcastReceiver Receiver) is used to deregister broadcasts. Dynamically registered broadcasts cannot receive broadcasts after the application stops running. For example, broadcasts registered in MainActivity should be registered before the MainActivity is destroyed. UnregisterReceiver (BroadcastReceiver Receiver) is used to deregister registration
Note for dynamic broadcast:
- 1. There must be a registration must be deregistered, otherwise it will lead to memory leaks
- 2. Repeated registration and deregistration are not allowed
4.3 Out-of-order Broadcast
Unordered broadcasts are sent directly through context.sendbroadcast (). The 4.1 static broadcast and 4.2 dynamic broadcast implementations above are both out-of-order broadcasts. After an out-of-order broadcast is sent, the broadcastReceivers are completely asynchronous and not related to each other. An out-of-order broadcast cannot be abortBroadcast, nor can setResult and getResult be used to pass processing results.
4.4 Orderly Broadcast
-
Orderly broadcast through the Context, sendOrderedBroadcast () to send. Ordered broadcasts are received by different receivers according to their priorities. The priority can be set using the Android :priority attribute of the intent-filter, and the value ranges from -1000 to 1000. A larger value indicates a higher priority.
- The first received broadcast receiver can truncate the abortBroadcast. That is, the later received broadcast receiver will not receive the broadcast.
- The first receiver can modify the broadcast, and the later receiver will receive the modified broadcast.
-
4.4.1 Android: Priority Not set
<? xml version="1.0" encoding="utf-8"? > <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.scc.broadcastreceiver">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.BroadcastReceiverDemo">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/Theme.BroadcastReceiverDemo.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".SCCReceiver"
android:enabled="true"
android:exported="true"/>
<receiver
android:name=".SCCReceiver3">
<intent-filter>
<action android:name="com.scc.broadcastreceiver.SCCReceiver"/>
</intent-filter>
</receiver>
<receiver
android:name=".SCCReceiver4">
<intent-filter>
<action android:name="com.scc.broadcastreceiver.SCCReceiver"/>
</intent-filter>
</receiver>
<receiver
android:name=".SCCReceiver5">
<intent-filter>
<action android:name="com.scc.broadcastreceiver.SCCReceiver"/>
</intent-filter>
</receiver>
</application>
</manifest>
Copy the code
case R.id.btn_send_ordered:
Log.e(getClass().getName(),Click on the "R.i db tn_send_ordered");
Intent intentActionOrdered = new Intent(SCCReceiver2.ACTION);
intentActionOrdered.putExtra("scc"."Orderly, real cow.");
sendOrderedBroadcast(intentActionOrdered,null);
break;
Copy the code
Operation effect:
SCCReceiver3>SCCReceiver4>SCCReceiver5
Copy the code
- 4.4.2 Setting Android :priority
<receiver
android:name=".SCCReceiver3">
<intent-filter android:priority="100">
<action android:name="com.scc.broadcastreceiver.SCCReceiver"/>
</intent-filter>
</receiver>
<receiver
android:name=".SCCReceiver4">
<intent-filter android:priority="0">
<action android:name="com.scc.broadcastreceiver.SCCReceiver"/>
</intent-filter>
</receiver>
<receiver
android:name=".SCCReceiver5">
<intent-filter android:priority="100">
<action android:name="com.scc.broadcastreceiver.SCCReceiver"/>
</intent-filter>
</receiver>
Copy the code
Operation effect:
SCCReceiver5(100)>SCCReceiver4(0)>SCCReceiver3(-100)
Copy the code
- 4.4.3 Modifying broadcast Interception
- 4.4.3.1 SCCReceiver5. Java
public class SCCReceiver5 extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.e(getClass().getName(),"SCCReceiver5, pass content:"+intent.getStringExtra("scc"));
Bundle bundle = getResultExtras(true);
bundle.putString("scc"."Changed the data."); setResultExtras(bundle); }}Copy the code
- 4.4.3.2 SCCReceiver4. Java
public class SCCReceiver4 extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = getResultExtras(true);
String name = bundle.getString("scc");
Log.e(getClass().getName(),"SCCReceiver4, pass content:"+name);
abortBroadcast();
Log.e(getClass().getName(),"SCCReceiver4, Intercept"); }}Copy the code
Operation effect:
SCCReceiver5(100) Modified data >SCCReceiver4(0) Intercept > No SCCReceiver3(-100)
Copy the code
Implementation principles of Broadcast Receiver
In Android, broadcasting is for communication between components. As a matter of fact, Android has Binder for interprocess communication, and there are more ways to communicate with the same process. The reason for using broadcast, sender and receiver do not need to know the existence of each other. The advantage of this is that various components of the system can be loosely coupled together, so that the system has a high degree of scalability. Easy integration with other systems.
Broadcasting in Android uses the Observer model: an event-driven model based on a publish/subscribe message model.
The broadcast model contains three roles:
- Message Publisher (Broadcast publisher)
- Message Center (AMS, Activity Manager Service)
- Message subscriber (broadcast receiver)
Implementation steps:
- Broadcast recipients register for listening in AMS through a Binder mechanism
- Broadcast publishers send broadcasts to AMS through Binder mechanisms
- AMS obtains the appropriate broadcast receiver from the registry according to the sender’s requirements (according to intent-filter, Permission)
- AMS sends the broadcast to the appropriate broadcast receiver in the message loop queue
- The broadcast receiver gets the broadcast through the message loop and calls onReceive()
In the whole broadcast sending and receiving process, the sender and receiver are asynchronous. The sender does not need to know whether there is a receiver or when the receiver receives the broadcast.
LocalBroadcastManager characteristics
- Local broadcast can only be transmitted within your own App without worrying about the leakage of private data
- Local broadcast does not allow other apps to send this broadcast to your App, so there is no need to worry about security holes being exploited
- Local broadcasting is more efficient than global broadcasting
Precautions for Broadcast Receiver
- Dynamically registered broadcasts that are unregistered when they are not needed or when the carrier is about to be destroyed, i.e. each registerReceiver needs to have a corresponding unregisterReceiver.
- Do not perform time-consuming operations in the broadcast receiver onReceive(), which will cause ANR(10s).
- Do not start asynchronous tasks in the broadcast receiver onReceive(), otherwise there will be an empty thread at the end of its life cycle, resulting in task loss or ANR.
- StartService for time-consuming tasks and use startService instead of bindService.
- Use LocalBroadcas for in-application broadcasts because it uses a Handler, which is cheaper and more secure than the Binder mechanism of Broadcast.
- The broadcast priority of dynamic registration is higher than that of static registration (when the configured priorities are the same), and the registration and deregistration of dynamic registration can be controlled. Therefore, dynamic registration is preferred when functions are available
- If you cannot receive the broadcast sent by yourself, check whether it is due to a permission problem.