广播拦截和abort短信
普通广播(Normal Broadcast):
优缺点:和有序广播的优缺点相反!
发送广播的方法:
sendBroadcast()
有序广播(Ordered Broadcast):
优缺点
优点:1.按优先级的不同,优先Receiver可对数据进行处理,并传给下一个Receiver
2.通过abortBroadcast可终止广播的传播
缺点:效率低
发送广播的方法:
sendOrderedBroadcast()
特点:
优先接收到Broadcast的Receiver可通过setResultExtras(Bundle)方法将处理结果存入Broadcast中,下一个Receiver 通过 Bundle bundle=getResultExtras(true)方法获取上一个 Receiver传来的数据。
实现拦截广播,abort短信的代码如下
public class SmsReceiver extends BroadcastReceiver {
// 当接收到短信时被触发
@Override
public void onReceive(Context context, Intent intent) {
// 如果是接收到短信
if (intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")) {
// 取消广播(这行代码将会让系统收不到短信)
abortBroadcast();
StringBuilder sb = new StringBuilder();
// 接收由SMS传过来的数据
Bundle bundle = intent.getExtras();
// 判断是否有数据
if (bundle != null) {
// 通过pdus可以获得接收到的所有短信消息
Object[] pdus = (Object[]) bundle.get("pdus");
// 构建短信对象array,并依据收到的对象长度来创建array的大小
SmsMessage[] messages = new SmsMessage[pdus.length];
for (int i = 0; i < pdus.length; i++) {
messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
}
// 将送来的短信合并自定义信息于StringBuilder当中
for (SmsMessage message : messages) {
sb.append("短信来源:");
// 获得接收短信的电话号码
sb.append(message.getDisplayOriginatingAddress());
sb.append("\n------短信内容------\n");
// 获得短信的内容
sb.append(message.getDisplayMessageBody());
}
}
Toast.makeText(context, sb.toString(), 5000).show();
}
}
}
有序广播,添加权限
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="wuchen.broadcastReceiver"
android:versionCode="1"
android:versionName="1.0" >
<application
android:icon="@drawable/icon"
android:label="@string/app_name" >
<receiver android:name=".SmsReceiver" >
<intent-filter android:priority="800" >
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
</application>
<!-- 授予程序接收短信的权限 -->
<uses-permission android:name="android.permission.RECEIVE_SMS" />
</manifest>
广播是否可以请求网络
直接请求网络是不可以的,需要开启线程请求。但是onReceived方法的周期比较短暂,可能出现广播关闭,线程还没结束,系统容易杀死无组件的进程,导致线程也被杀死。好的方式例如启动一个IntentService等。
广播引起anr的时间限制
在onReceive函数中不能做耗时操作,参考值在10s以内。严格上讲,系统级别监听的broadcastReceiver激活后也只能最多运行10秒钟,如果10秒内还没有处理完业务,Android会认为该程序无响应,并弹出ANR(application No Response)对话框。对于这种”限制“,我们处理这种限制的方式,也是项目中用到的最多一种方法:启动service。最可靠的方式是在广播中启动一个service,让service在后台去处理数据,这样就算广播生命周期结束,service也不会被销毁,因为用startService这种方式启动的service,就算访问者(广播)销毁自己也不会销毁,而且本来在广播中处理数据的耗时操作,交给了service去做,同时避免了ANR问题的出现。用启动新线程的方式也不可靠,广播的生命周期,就是内部onReceive方法的周期,当onReceiver方法结束,也就意味着广播的结束。
虽然我们可以在onReceiver内执行启动一个新线程执行耗时的业务,由于onReceiver方法周期很短暂,可能出现的情况是:子线程还没有结束广播就关闭了,广播一旦关闭,虽然子线程还可以运行,但系统会认为广播处于无组件活动的状态,在内存紧张的时候优先结束该进程,这样可能会导致子线程不能执行完任务。所以最好的方式是启动service。
网友评论