广播常用的分为三种,有序、无序和本地;从接收者注册角度来看分为动态和静态两种。无序广播即平常使用的广播方式,这里我并没有写demo,并且注册上只用了动态注册。
参考博客:https://blog.csdn.net/carson_ho/article/details/52973504
一:有序广播,有序是针对广播接收者而言的
广播接受者接收广播的顺序规则(同时面向静态和动态注册的广播接受者)
- 按照Priority属性值从大-小排序;
- Priority属性相同者,动态注册的广播优先;
特点
- 接收广播按顺序接收
- 先接收的广播接收者可以对广播进行截断,即后接收的广播接收者不再接收到此广播;
- 先接收的广播接收者可以对广播进行修改,那么后接收的广播接收者将接收到被修改后的广播
demo如下,定义了三个有序广播,通过设置优先级决定每个广播的先后:
package custombroadcast.order;
import androidx.appcompat.app.AppCompatActivity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import com.example.androidpratic.R;
import com.example.androidpratic.network.PickImageFromWorld;
public class OrderBroadcastActivity extends AppCompatActivity {
private static final String TAG = "OrderBroadcastActivity";
private OrderOneReceiver mOrderOneReceiver;
private OrderTwoReceiver mOrderTwoReceiver;
private OrderThreeReceiver mOrderThreeReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_order_broast);
mOrderOneReceiver = new OrderOneReceiver();
mOrderTwoReceiver = new OrderTwoReceiver();
mOrderThreeReceiver = new OrderThreeReceiver();
IntentFilter intentFilter1 = new IntentFilter();
intentFilter1.addAction("com.example.broadCast.Order");
intentFilter1.setPriority(100);
IntentFilter intentFilter2 = new IntentFilter();
intentFilter2.addAction("com.example.broadCast.Order");
intentFilter2.setPriority(98);
IntentFilter intentFilter3 = new IntentFilter();
intentFilter3.addAction("com.example.broadCast.Order");
intentFilter3.setPriority(96);
registerReceiver(mOrderOneReceiver, intentFilter1);
registerReceiver(mOrderTwoReceiver, intentFilter2);
registerReceiver(mOrderThreeReceiver, intentFilter3);
sendBroad();
}
private void sendBroad() {
Intent intent = new Intent("com.example.broadCast.Order");
sendOrderedBroadcast(intent, null, new OrderFourReceiver(), null, RESULT_OK, "发送广播了", null);
Log.d(TAG, "send broadcast");
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mOrderOneReceiver);
unregisterReceiver(mOrderTwoReceiver);
unregisterReceiver(mOrderThreeReceiver);
}
class OrderOneReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String resultData = getResultData();
Log.d(TAG, resultData);
setResultData("OrderOne修改了数据");
// abortBroadcast(); // 截断测试
}
}
class OrderTwoReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String resultData = getResultData();
Log.d(TAG, resultData);
setResultData("OrderTwo修改了数据");
}
}
class OrderThreeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String resultData = getResultData();
Log.d(TAG, resultData);
}
}
// 定义的一个特殊的广播接收者,在发送有序广播的时候以参数的形式传递进去
class OrderFourReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String resultData = getResultData();
Log.d(TAG, "最终接收:" + resultData);
}
}
}
二:本地广播
- App应用内广播可理解为一种局部广播,广播的发送者和接收者都同属于一个App。
- 相比于全局广播(普通广播),App应用内广播优势体现在:安全性高 & 效率高
注:对于LocalBroadcastManager方式发送的应用内广播,只能通过LocalBroadcastManager动态注册,不能静态注册。
demo如下,需要提前导入本地广播依赖:
package custombroadcast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import com.example.androidpratic.R;
public class LocalBroadCastActivity extends AppCompatActivity {
private static final String TAG = "LocalBroadCastActivity";
private LocalBroadCastReceiver mLocalBroadCastReceiver;
private LocalBroadcastManager mLocalBroadcastManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_local_broad_cast);
mLocalBroadCastReceiver = new LocalBroadCastReceiver();
IntentFilter intentFilter = new IntentFilter("com.example.LocalBroadCast");
mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);
mLocalBroadcastManager.registerReceiver(mLocalBroadCastReceiver, intentFilter);
Intent intent = new Intent();
intent.setAction("com.example.LocalBroadCast");
intent.putExtra("DATA", "发送数据");
mLocalBroadcastManager.sendBroadcast(intent);
}
@Override
protected void onDestroy() {
super.onDestroy();
mLocalBroadcastManager.unregisterReceiver(mLocalBroadCastReceiver);
}
class LocalBroadCastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String data = intent.getStringExtra("DATA");
Log.d(TAG, "onReceive data: " + data);
}
}
}
三:安全注意点
参考博客:https://juejin.im/post/6844904115290685448
- 优先使用则可以使用LocalBroadcastManager
如果不需要向应用以外的组件发送广播,使用LocalBroadcastManager 效率更高(无需进行进程间通信)。本地广播可在应用中作为通用的发布/订阅事件总线,而不会产生任何系统级广播开销。- 优先使用上下文注册而不是清单声明
如果有许多应用在其清单中注册接收相同的广播,可能会导致系统启动大量应用,从而对设备性能和用户体验造成严重影响。有时,Android 系统本身会强制使用上下文注册的接收器。例如,CONNECTIVITY_ACTION 广播只会传送给上下文注册的接收器。- 通过权限限制广播
- 当注册接收器时,任何应用都可以向你应用的接收器发送潜在的恶意广播。
可以通过以下三种方式限制你的应用可以接收的广播:
- 在注册广播接收器时指定权限
- 对于清单声明的接收器,可以在清单中将 android:exported 属性设置为“false”,这样接收器就不会接收来自应用外部的广播。
- 使用 LocalBroadcastManager 注册广播
- 勿使用隐式 intent 广播敏感信息
可以通过以下三种方式控制哪些应用可以接收广播:
- 可以在发送广播时指定权限
- 可以在发送广播时使用 setPackage(String) 指定软件包
- 可以使用 LocalBroadcastManager 发送本地广播
- onRecive返回后即有可能被系统回收,如需做耗时操作,尽量使用goAsync()开启后台任务或JobScheduler