文章目录

有序广播的拦截

在有序广播接收者中,可以调用​​abortBroadcast()​​方法,终止有序广播继续向后传递

接着上一节的例子,当前优先级最高的是 LowReceiver,可以在处理接受有序广播的代码中终止广播

public class LowReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//区分广播的“频道”
String action = intent.getAction();
if("CCTV5".equals(action)){
String date = intent.getStringExtra("date");
Log.d("BROADCAST","LowReceiver->onReceive();时间:"+date);
}else if("CCTV1".equals(action)){
int number = intent.getIntExtra("_number",-999);
abortBroadcast();
Log.d("BROADCAST","LowReceiver->onReceive();_number:"+number);
}else{

}

}
}

重新运行程序,发送有序广播

观察日志,只有

D/BROADCAST: LowReceiver->onReceive();_number:0

注意
只能拦截有序广播,不能对无序广播使用

如果我们在无序广播中使用会报错

【达内课程】BroadcastReceiver(下)_有序广播

广播的篡改

在有序广播的接收者中,可以通​​过setResult???​​​的方法,向广播中添加数据,优先级更低的广播接收者可以通过调用对应的​​getResult???​​的方法获取此前被添加进的数据

上一节中我们设置的优先级如下:

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

按照这个优先级我们需要篡改数据如下:

LowReceiver 说:老王今天来了
MidReceiver 说:老王今天来了,还偷拍了小美
InnerLowReceiver 说:老王今天来了,还偷拍了小美,并且ps了
InnerMidReceiver
InnerHighReceiver
HighReceiver

修改 LowReceiver

@Override
public void onReceive(Context context, Intent intent) {
//区分广播的“频道”
String action = intent.getAction();
if("CCTV5".equals(action)){
......
}else if("CCTV1".equals(action)){
int number = intent.getIntExtra("_number",-999);
//拦截广播
//abortBroadcast();
//添加数据,向后面的接收者传递
setResultData("老王今天来了");
Log.d("BROADCAST","LowReceiver->onReceive();_number:"+number+",说:老王今天来了");
}else{
}
}

修改 MidReceiver

public class MidReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//区分广播的“频道”
String action = intent.getAction();
if ("CCTV5".equals(action)) {
......
} else if ("CCTV1".equals(action)) {
int number = intent.getIntExtra("_number", -999);
//获取前一个接收者传递的数据
String str = getResultData();
//篡改数据
setResultData("老王今天来了,还偷拍了小美");

Log.d("BROADCAST", "MidReceiver->onReceive();_number:" + number + "收到:" + str + ",重新说:老王今天来了,还偷拍了小美");
} else {
}
}
}

修改 InnerLowReceiver

private class InnerLowReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
//区分广播的“频道”
String action = intent.getAction();
if ("CCTV5".equals(action)) {
......
} else if ("CCTV1".equals(action)) {
int number = intent.getIntExtra("_number", -999);
//获取前一个接收者传递的数据
String str = getResultData();
//篡改数据
setResultData("老王今天来了,还偷拍了小美,并且Ps了");

Log.d("BROADCAST", "InnerLowReceiver->onReceive();_number:" + number + "收到:" + str + ",重新说:老王今天来了,还偷拍了小美,并且Ps了");
} else {

}
}
}

其余 InnerMidReceiver、InnerHighReceiver、HighReceiver 的​​onReceive​​方法都改为类似

public class HighReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//区分广播的“频道”
String action = intent.getAction();
if("CCTV5".equals(action)){
......
}else if("CCTV1".equals(action)){
int number = intent.getIntExtra("_number",-999);
//获取前一个接收者传递的数据
String str = getResultData();
Log.d("BROADCAST","HighReceiver->onReceive();_number:"+number+",收到:"+str);
}else{

}
}
}

运行程序,先注册内部接收者,然后发送有序广播,观察日志

LowReceiver->onReceive();_number:0,说:老王今天来了
MidReceiver->onReceive();_number:0收到:老王今天来了,重新说:老王今天来了,还偷拍了小美
InnerLowReceiver->onReceive();_number:0收到:老王今天来了,还偷拍了小美,重新说:老王今天来了,还偷拍了小美,并且Ps了
InnerMidReceiver->onReceive();_number:0,收到:老王今天来了,还偷拍了小美,并且Ps了
InnerMidReceiver->onReceive();_number:0,收到:老王今天来了,还偷拍了小美,并且Ps了
HighReceiver->onReceive();_number:0,收到:老王今天来了,还偷拍了小美,并且Ps了

管理呼出电话

当 Android 设备尝试呼出电话时,会由系统发出有序广播,并且通过​​setResultData(String)​​​方法将电话号码封装,最后,系统的呼叫程序将会接收到该广播,并通过​​getResultData()​​方法获取电话号码,实现呼叫

管理呼出电话原理:自定义广播接收者,接收系统的呼出电话广播,并通过​​getResultData()​​​获取呼出的电话号码,对电话号码进行判断,如果符合设定规则,通过​​setResultData()​​重新设置电话号码即可

栗子:拨打10086时改为10000

自定义 ProcessOutGoingCallReceiver

public class ProcessOutGoingCallReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
String number = getResultData();
Log.d("BROADCAST","Number"+number);
if("10086".equals(number)){
setResultData("10000");
Log.d("BROADCAST","符合规则,改为10000");
}
}
}

AndroidManifest

增加权限

<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>

注册

<receiver android:name=".ProcessOutGoingCallReceiver">
<intent-filter>
<category android:name="android.intent.category.DEFAULT"/>
<action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
</intent-filter>
</receiver>

注意
确认在应用中“电话权限”是否打开

首先拨打 12345,然后拨打 10086,观察日志

D/BROADCAST: Number12345
D/BROADCAST: Number10086
D/BROADCAST: 符合规则,改为10000

如何获取更高的有序广播者的优先级

1、使用最大的 priority 属性注册具体实施业务的广播接收者
2、使用粘性 Service,在 onCreate() 时动态注册具体实施业务的广播接受者
3、使用静态的方式注册监听开机广播(BOOT_COMPLETED)的广播接收者,并在收到该广播后,使用启动模式激活 Service
4、如果某些版本的 Android 系统不允许监听开机广播,只能尽可能的监听各种系统广播

​​源码下载​​