This is the 20th day of my participation in the August Text Challenge.More challenges in August
introduce
The Android system and applications can send and receive broadcasts to each other. Broadcasts will be sent when the event of interest occurs. Applications can register to receive specific broadcasts. Once the broadcast is sent, it is automatically transmitted to the application that agrees to receive it.
Broadcast can be used as a messaging system beyond the flow of applications and ordinary users, and abuse of post-response broadcasts and run-time operations can slow the system down.
Registration of radio
Applications can receive broadcasts in two ways: a manifest declared receiver and a context registered receiver, that is, a static register and a dynamic register.
public class MyReceiver extends BroadcastReceiver {
private static final String TAG = "MyReceiver";
@Override
public void onReceive(Context context, Intent intent) {
int key = intent.getIntExtra("KEY".0);
Log.d(TAG, "onReceive: key is "+ key); }}Copy the code
Static registered broadcast
Register in androidmanifest.xml
<application>
...
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.android.LEARN" />
</intent-filter>
</receiver>
...
</application>
Copy the code
Note: If your application targets platform versions at API level 26 or higher, you cannot declare receivers for implicit broadcasts (broadcasts that are not specifically targeted to your application) using the manifest, but some implicit broadcasts that are not subject to this restriction are excluded from the portal.
Dynamic Registration broadcast
private void registerBroadcastReceiver(a){
//1. Create an instance of BroadcastReceiver.
BroadcastReceiver broadcastReceiver = new MyReceiver();
//2. Create IntentFilter and call registerReceiver(BroadcastReceiver, IntentFilter) to register receivers
IntentFilter filter = new IntentFilter("com.android.LEARN");
this.registerReceiver(broadcastReceiver,filter);
}
Copy the code
As long as the Activity is not destroyed, it receives a broadcast. If you register in the application context, you will receive broadcasts whenever the application is running.
Use standard
To stop receiving radio, call unregisterReceiver (android. Content. BroadcastReceiver). When the sink is no longer needed or the context is no longer valid, it is important to unregister the sink.
Note where the receiver is registered and unregistered. For example, if the receiver is registered in onCreate(Bundle), unregister it in onDestroy() to prevent the receiver from being leaked from the Activity. If you register receivers in onResume(), you should unregister them in onPause() to prevent multiple registrations of receivers (this can reduce unnecessary overhead if you don’t want to receive broadcasts during pauses). Do not log out in onSaveInstanceState(Bundle), because this method will not be called if the user falls back in the history stack.
Impact on process status
The state of the BroadcastReceiver (whether or not it is running) affects the state of the process it is in, which in turn affects the likelihood that it will be killed by the system. For example, when a process executes onReceive(), it is considered a foreground process. The system keeps the process running unless it encounters extreme memory stress.
However, once the code is returned from onReceive(), the BroadcastReceiver is no longer active. The host process for onReceive() becomes just as important as the other application components running in it. If the process hosts only the receivers declared by the manifest (which is common for applications with which the user has never interacted or has not interacted recently), its process is considered a low-priority process when it returns from onReceive() and may be terminated so that resources can be made available to other, more important processes.
If theonReceive()
The work is long enough to cause the interface thread to lose frames (>16ms), I believe that the loss of frames is difficult to optimize, or from the details
Send broadcast
Android provides three ways for applications to send broadcasts:
sendOrderedBroadcast(Intent, String)
Orderly broadcast
The order in which receivers are run can be controlled by the Android: Priority attribute of the matching Intent-filter. Receivers with the same priority will run in random order.
sendBroadcast(Intent)
Conventional radioLocalBroadcastManager.sendBroadcast
Local radio
If you do not need to send broadcasts across applications, use local broadcasts. This implementation is more efficient (no interprocess communication is required), and you don’t have to worry about any security issues that other applications may have when sending and receiving your broadcasts.
Intent i = new Intent();
i.setAction("com.android.LEARN");
sendBroadcast(i);
Copy the code
The radio type
Broadcast is classified into system broadcast and custom broadcast.
System of radio
The Android system automatically sends a broadcast at various system times, such as when an application is installed or uninstalled.
The system broadcasts the complete list
In the SDK directorySdk\platforms\android-30\data\broadcast_actions
Contains all broadcasts of the current SDK version.
Changes reported by different versions of the system
Android 9
Starting with Android 9 (API level 28), NETWORK_STATE_CHANGED_ACTION broadcasts no longer receive information about a user’s location or personally identifiable data. – > portal
In addition, on Android 9 or later devices, the system broadcast received over the WLAN does not contain the SSID, BSSID, connection information, or scan results. Call getConnectionInfo() -> portal.
Android 8
For most implicit broadcasts (broadcasts that are not explicitly targeted to an application), static registrations cannot be used. Consider using dynamic registration
Of course, static registration is not completely out of the question. It can be resolved in intent.setPackage (packageName).
public class BroadcastActivity extends AppCompatActivity {
private Button mSendBroadcast;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_broadcast);
mSendBroadcast = findViewById(R.id.send_broadcast);
mSendBroadcast.setOnClickListener(v -> {
Intent i = new Intent();
i.setAction("com.android.LEARN");
i.setPackage(getPackageName());
i.putExtra("KEY".1); sendBroadcast(i); }); }}Copy the code
Statically registered in androidmanifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.shixf.servicelearn">
<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.ServiceLearn">
<activity
android:name=".BroadcastActivity"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.android.LEARN" />
</intent-filter>
</receiver>
</application>
</manifest>
Copy the code
The Android 7.0
Android 7.0 (API level 24) and later do not send the following system broadcasts:
ACTION_NEW_PICTURE
ACTION_NEW_VIDEO
In addition, applications targeting Android 7.0 and later must register CONNECTIVITY_ACTION broadcasts using registerReceiver(IntentFilter). The receiver cannot be declared in the manifest.
Restrict broadcasts by permission
Send broadcast with permission
When calling sendBroadcast(Intent, String) or sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle), you can specify permission parameters. To receive this broadcast, a receiver must request the permission (or be granted the permission if there is a danger) through the tag in its manifest. For example, the following code sends a broadcast:
private void sendPermissionBroadcast(a){
sendBroadcast(new Intent("com.android.LEARN"),
Manifest.permission.CAMERA);
}
Copy the code
To receive this broadcast, the recipient APP must request the following permissions:
<uses-permission android:name="android.permission.CAMERA"/>
Copy the code
Note: Custom permissions are registered when the application is installed. The application that defines custom permissions must be installed before the application that uses custom permissions
Receive broadcast with permission
If a permission parameter is specified when registering a BroadcastReceiver (BroadcastReceiver, IntentFilter, String, Handler) or the
tag of Androidmanifest.xml, the broadcaster must request this permission (or be granted it if there is a danger) through the < uses-Permission > tag in its manifest, To send the Intent to the receiver.
Assume that the receiver APP has permission limits
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true"
android:permission="android.permission.CAMERA">
<intent-filter>
<action android:name="com.android.LEARN" />
</intent-filter>
</receiver>
Copy the code
Or the receiver applies a receiver with dynamic registration as follows:
IntentFilter filter = new IntentFilter("com.android.LEARN");
registerReceiver(receiver, filter, Manifest.permission.CAMERA, null );
Copy the code
The sender, then, the APP must request the Manifest. Permission. CAMER permissions, can send broadcast notice is limit the sender to the receiver.
Safety considerations and best practices
-
If you don’t need to send broadcasts to components outside your application, you can use LocalBroadcastManager (you now need to add dependencies) to send and receive local broadcasts. LocalBroadcastManager is more efficient (no interprocess communication is required), and it doesn’t have to take into account any security issues that other applications have when sending and receiving broadcasts. Local broadcast can be used as a general publish/subscribe event bus in your application without any system-level broadcast overhead.
-
If many applications register to receive the same broadcast in their lists, the system may start a large number of applications, which may seriously affect device performance and user experience. To avoid this, use dynamic registrations in preference to manifest declarations (static registrations). Sometimes, the Android system itself enforces the use of dynamically registered receivers. For example, CONNECTIVITY_ACTION broadcasts are only sent to context-registered receivers.
-
Do not use an implicit intent to broadcast sensitive information. Any application registered to receive the broadcast can read this information. You can control which applications can receive your broadcasts in the following three ways:
- Permissions can be specified when a broadcast is sent.
- In Android 4.0 and later, you can use it when sending a broadcast
setPackage(String)
Specify the package name. The system restricts the broadcast to the set of applications that match the package. - You can also use
LocalBroadcastManager
Send a local broadcast.
-
When registering a receiver, any application can send potentially malicious broadcasts to our application’s receiver. You can limit the broadcasts an application can receive in the following three ways:
- Permissions can be specified when registering a broadcast receiver.
- For receivers declared in the listing, you can set the Android: Exported property to “false” in the listing. In this way, the receiver does not receive broadcasts from outside the application.
- You can use
LocalBroadcastManager
Restrict applications to receive only local broadcasts.
-
The namespace for broadcast operations is global. Be sure to write operation names and other strings in your own namespace, otherwise you may inadvertently clash with other applications.
-
Since the receiver’s onReceive(Context, Intent) method runs on the main thread, it executes quickly and returns. Be careful to generate threads or start background services if you need long-running work, as the system may terminate the entire process after onReceive() returns.
-
Do not start the Activity from a broadcast receiver; otherwise, the user experience will be affected, especially if there are multiple receivers. Instead, consider displaying notifications
Android learning is of course a reference to the official document portal.