文章目录
广播的种类
- 普通广播/无序广播
表现为广播的接收者们将不区分先后顺序,几乎同时接收广播,并且广播接收者们在接收广播时互不相干 - 有序广播
表现为广播的接收者们会根据一定的先后顺序,接收到广播。类似于生活中的“传话”的特性 - 粘滞广播/粘性广播(也区分为有序和无序)
无视,在Android 5.0已声明为过期
栗子:发送有序广播
对上一篇的栗子进行改进,增加1个按钮
<Button
android:id="@+id/btn_send_ordered_broadcast"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="发送有序广播"/>
MainActivity
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
...
private Button btnSendOrderedBroadcast;
...
private int number;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
btnSendOrderedBroadcast = findViewById(R.id.btn_send_ordered_broadcast);
...
btnSendOrderedBroadcast.setOnClickListener(this);
}
public void onClick(View view) {
switch (view.getId()) {
...
case R.id.btn_send_ordered_broadcast:
//准备Intent对象
Intent intent2 = new Intent();
intent2.setPackage("com.example.testapplication");
intent2.putExtra("_number", number);
number++;
intent2.setAction("CCTV1");
//接收者的权限
String receiverPermission = null;
//发送有序广播
sendOrderedBroadcast(intent2, receiverPermission);
break;
case R.id.btn_register_receiver:
if (receiver == null) {
receiver = new InnerReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("CCTV5");
filter.addAction("CCTV1");
registerReceiver(receiver, filter);
}
...
}
}
private class InnerReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
//区分广播的“频道”
String action = intent.getAction();
if ("CCTV5".equals(action)) {
String date = intent.getStringExtra("date");
Log.d("BROADCAST", "InnerReceiver->onReceive();时间:" + date);
} else if ("CCTV1".equals(action)) {
int number = intent.getIntExtra("_number", -999);
Log.d("BROADCAST", "InnerReceiver->onReceive();_number:" + number);
} else {
}
}
}
}
增加一个按钮,增加点击事件,让其发送有序广播,这次发送的频道是“CCTV1”,为了能让 InnerReceiver 也能接收“CCTV1”,我们在动态注册 InnerReceiver 时,除了filter.addAction("CCTV5");
也增加
filter.addAction("CCTV1");
然后在接收到广播时,对“频道”进行区分,再进行不同的处理
String action = intent.getAction();
与此同时,我们还有 CustomReceiver 和 CustomReceiver2 ,也进行同样的“频道”区分操作
CustomReceiver
public class CustomReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
//区分广播的“频道”
String action = intent.getAction();
if ("CCTV5".equals(action)) {
String date = intent.getStringExtra("date");
Log.d("BROADCAST", "CustomReceiver->onReceive();时间:" + date);
} else if ("CCTV1".equals(action)) {
int number = intent.getIntExtra("_number", -999);
Log.d("BROADCAST", "CustomReceiver->onReceive();_number:" + number);
} else {
}
}
}
CustomReceiver2
public class CustomReceiver2 extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
//区分广播的“频道”
String action = intent.getAction();
if ("CCTV5".equals(action)) {
String date = intent.getStringExtra("date");
Log.d("BROADCAST", "CustomReceiver2->onReceive();时间:" + date);
} else if ("CCTV1".equals(action)) {
int number = intent.getIntExtra("_number", -999);
Log.d("BROADCAST", "CustomReceiver2->onReceive();_number:" + number);
} else {
}
}
}
在AndroidManifest中进行注册
<receiver android:name=".CustomReceiver">
<intent-filter>
<action android:name="CCTV1"/>
<action android:name="CCTV5"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
<receiver android:name=".CustomReceiver2">
<intent-filter>
<action android:name="CCTV1"/>
<action android:name="CCTV5"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
运行程序
点击发送普通广播
D/BROADCAST: Mainctivity->onClick();时间:1523513945123
D/BROADCAST: CustomReceiver->onReceive();时间:1523513945123
D/BROADCAST: CustomReceiver2->onReceive();时间:1523513945123
点击发送有序广播
D/BROADCAST: CustomReceiver->onReceive();_number:0
D/BROADCAST: CustomReceiver2->onReceive();_number:0
再次点击发送有序广播
D/BROADCAST: CustomReceiver->onReceive();_number:1
D/BROADCAST: CustomReceiver2->onReceive();_number:1
点击注册内部接收者,再点击发送有序广播
D/BROADCAST: InnerReceiver->onReceive();_number:2
D/BROADCAST: CustomReceiver->onReceive();_number:2
D/BROADCAST: CustomReceiver2->onReceive();_number:2
广播的接收者们的优先级
- 根据注册广播时,IntentFilter 的
priority
属性决定,该属性的值是 int 类型的数值,数值越大,则优先级越高,即更优先接收到广播 - 当多个广播接收者的
priority
属性值相同时,动态注册的广播接收者优先级更高 - 当根据以上 2 条无法确定优先级时,将根据注册的先后顺序进行区分,先注册的优先级更高
- 如果在不同的应用程序中,都使用了相同的注册方式,且 priority 属性值相同
如果是使用的动态注册,可以直接区分出执行注册的先后顺序
如果是使用的静态注册,则根据项目的 package 属性值,按字典排序法进行区分
栗子
现有 3 个广播接收者
代码类似,以 HighReceiver 为例
public class HighReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
//区分广播的“频道”
String action = intent.getAction();
if("CCTV5".equals(action)){
String date = intent.getStringExtra("date");
Log.d("BROADCAST","HighReceiver->onReceive();时间:"+date);
}else if("CCTV1".equals(action)){
int number = intent.getIntExtra("_number",-999);
Log.d("BROADCAST","HighReceiver->onReceive();_number:"+number);
}else{
}
}
}
都需要在AndroidManifest中注册
<receiver android:name=".HighReceiver">
<intent-filter>
<action android:name="CCTV1"/>
<action android:name="CCTV5"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
布局和上个栗子相同
除了上面的 HighReceiver、MidReceiver 和 LowReceiver 外,我们在 MainActivity 中再定义 3 个内部接收者 InnerHighReceiver、InnerMidReceiver 和 InnerLowReceiver
MainActivity进行改进
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button btnSend;
private Button btnResiger;
private Button btnUnregister;
private Button btnSendOrderedBroadcast;
private InnerHighReceiver highReceiver;
private InnerMidReceiver midReceiver;
private InnerLowReceiver lowReceiver;
private int number;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnSend = findViewById(R.id.btn_send);
btnResiger = findViewById(R.id.btn_register_receiver);
btnUnregister = findViewById(R.id.btn_unregister_receiver);
btnSendOrderedBroadcast = findViewById(R.id.btn_send_ordered_broadcast);
btnSend.setOnClickListener(this);
btnResiger.setOnClickListener(this);
btnUnregister.setOnClickListener(this);
btnSendOrderedBroadcast.setOnClickListener(this);
}
public void onClick(View view) {
switch (view.getId()) {
case R.id.btn_send:
long date = System.currentTimeMillis();
Intent intent = new Intent();
intent.setPackage("com.example.testapplication");
intent.setAction("CCTV5");
intent.putExtra("date", "" + date);
Log.d("BROADCAST", "Mainctivity->onClick();时间:" + date);
sendBroadcast(intent);
break;
case R.id.btn_send_ordered_broadcast:
//准备Intent对象
Intent intent2 = new Intent();
intent2.setPackage("com.example.testapplication");
intent2.putExtra("_number", number);
number++;
intent2.setAction("CCTV1");
//接收者的权限
String receiverPermission = null;
//发送有序广播
sendOrderedBroadcast(intent2, receiverPermission);
break;
case R.id.btn_register_receiver:
if (highReceiver == null) {
highReceiver = new InnerHighReceiver();
IntentFilter hignFilter = new IntentFilter();
hignFilter.addAction("CCTV5");
hignFilter.addAction("CCTV1");
registerReceiver(highReceiver, hignFilter);
}
if (midReceiver == null) {
midReceiver = new InnerMidReceiver();
IntentFilter midFilter = new IntentFilter();
midFilter.addAction("CCTV5");
midFilter.addAction("CCTV1");
registerReceiver(midReceiver, midFilter);
}
if (lowReceiver == null) {
lowReceiver = new InnerLowReceiver();
IntentFilter lowFilter = new IntentFilter();
lowFilter.addAction("CCTV5");
lowFilter.addAction("CCTV1");
registerReceiver(lowReceiver, lowFilter);
}
break;
case R.id.btn_unregister_receiver:
if (highReceiver != null) {
unregisterReceiver(highReceiver);
highReceiver = null;
}
if (midReceiver != null) {
unregisterReceiver(midReceiver);
midReceiver = null;
}
if (lowReceiver != null) {
unregisterReceiver(lowReceiver);
lowReceiver = null;
}
break;
}
}
private class InnerHighReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
//区分广播的“频道”
String action = intent.getAction();
if ("CCTV5".equals(action)) {
String date = intent.getStringExtra("date");
Log.d("BROADCAST", "InnerHighReceiver->onReceive();时间:" + date);
} else if ("CCTV1".equals(action)) {
int number = intent.getIntExtra("_number", -999);
Log.d("BROADCAST", "InnerHighReceiver->onReceive();_number:" + number);
} else {
}
}
}
private class InnerMidReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
//区分广播的“频道”
String action = intent.getAction();
if ("CCTV5".equals(action)) {
String date = intent.getStringExtra("date");
Log.d("BROADCAST", "InnerMidReceiver->onReceive();时间:" + date);
} else if ("CCTV1".equals(action)) {
int number = intent.getIntExtra("_number", -999);
Log.d("BROADCAST", "InnerMidReceiver->onReceive();_number:" + number);
} else {
}
}
}
private class InnerLowReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
//区分广播的“频道”
String action = intent.getAction();
if ("CCTV5".equals(action)) {
String date = intent.getStringExtra("date");
Log.d("BROADCAST", "InnerLowReceiver->onReceive();时间:" + date);
} else if ("CCTV1".equals(action)) {
int number = intent.getIntExtra("_number", -999);
Log.d("BROADCAST", "InnerLowReceiver->onReceive();_number:" + number);
} else {
}
}
}
}
在不指定优先级的情况下,先点击“注册内部接收者”,然后点击发送“有序广播”
观察日志
D/BROADCAST: InnerHighReceiver->onReceive();_number:0
D/BROADCAST: InnerMidReceiver->onReceive();_number:0
D/BROADCAST: InnerLowReceiver->onReceive();_number:0
D/BROADCAST: HignReceiver->onReceive();_number:0
D/BROADCAST: MidReceiver->onReceive();_number:0
D/BROADCAST: LowReceiver->onReceive();_number:0
我们发现内部接收者会优先收到广播,下面我们手动设置priority
属性
先设置内部类
public void onClick(View view) {
switch (view.getId()) {
...
case R.id.btn_register_receiver:
if (highReceiver == null) {
highReceiver = new InnerHighReceiver();
IntentFilter hignFilter = new IntentFilter();
hignFilter.setPriority(100);
hignFilter.addAction("CCTV5");
hignFilter.addAction("CCTV1");
registerReceiver(highReceiver, hignFilter);
}
if (midReceiver == null) {
midReceiver = new InnerMidReceiver();
IntentFilter midFilter = new IntentFilter();
midFilter.setPriority(500);
midFilter.addAction("CCTV5");
midFilter.addAction("CCTV1");
registerReceiver(midReceiver, midFilter);
}
if (lowReceiver == null) {
lowReceiver = new InnerLowReceiver();
IntentFilter lowFilter = new IntentFilter();
lowFilter.setPriority(900);
lowFilter.addAction("CCTV5");
lowFilter.addAction("CCTV1");
registerReceiver(lowReceiver, lowFilter);
}
break;
...
}
}
再设置外部类
<receiver android:name=".HighReceiver">
<intent-filter>
<action android:name="CCTV1"/>
<action android:name="CCTV5"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
<receiver android:name=".MidReceiver">
<intent-filter android:priority="1000">
<action android:name="CCTV1"/>
<action android:name="CCTV5"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
<receiver android:name=".LowReceiver">
<intent-filter android:priority="5000">
<action android:name="CCTV1"/>
<action android:name="CCTV5"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
同样的先点击“注册内部接收者”,然后点击发送“有序广播”
观察日志
D/BROADCAST: LowReceiver->onReceive();_number:0
D/BROADCAST: MidReceiver->onReceive();_number:0
D/BROADCAST: InnerLowReceiver->onReceive();_number:0
D/BROADCAST: InnerMidReceiver->onReceive();_number:0
D/BROADCAST: InnerHighReceiver->onReceive();_number:0
D/BROADCAST: HighReceiver->onReceive();_number:0