广播接收者(BroadcastReceiver)用于异步接收广播Intent,广播Intent的发送是通过调用Context.sendBroadcast()、Context.sendOrderedBroadcast()或者Context.sendStickyBroadcast()来实现的。通常一个广播Intent可以被订阅了此Intent的多个广播接收者所接收,广播接收者和JMS中的Topic消息接收者很相似。要实现一个广播接收者方法如下:
第一步:继承BroadcastReceiver,并重写onReceive()方法。
public class IncomingSMSReceiver extends BroadcastReceiver {
@Override public void onReceive(Context context, Intent intent) {
}
}
第二步:订阅感兴趣的广播Intent,订阅方法有两种:
第一种:使用代码进行订阅
IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
IncomingSMSReceiver receiver = new IncomingSMSReceiver();
registerReceiver(receiver, filter);
第二种:在AndroidManifest.xml文件中的<application>节点里进行订阅:
<receiver android:name=".IncomingSMSReceiver">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
学习的demo:
利用BroadcastReceiver实现短信Listener
原理:当系统收到短信时,会发出一个广播Intent,Intent的action名称是android.provider.Telephony.SMS_RECEIVED,该Intent存放了系统收到的短信内容,我们使用名称"pdus"即可从Intent中获取到短信内容。
参考代码
public class SMSBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Object[] pdus = (Object[]) intent.getExtras().get("pdus");
for(Object p : pdus){
byte[] pdu = (byte[]) p;
SmsMessage message = SmsMessage.createFromPdu(pdu);
String content = message.getMessageBody();
Date date = new Date(message.getTimestampMillis());
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String receiveTime = format.format(date);
String senderNumber = message.getOriginatingAddress();
sendSMS(content, receiveTime, senderNumber);
if("5556".equals(senderNumber)){
abortBroadcast();//终止广播
}
}
}
private boolean sendSMS(String content, String receiveTime, String senderNumber) {
try{
String params = "content="+ URLEncoder.encode(content, "UTF-8")+
"&receivetime="+ receiveTime+ "&sendernumber="+ senderNumber;
byte[] entity = params.getBytes();
String path = "http://192.168.1.100:8080/web/ReceiveSMSServlet";
HttpURLConnection conn = (HttpURLConnection) new URL(path).openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("Content-Length", String.valueOf(entity.length));
conn.getOutputStream().write(entity);
if(conn.getResponseCode() == 200){
return true;
}
}catch (Exception e) {
e.printStackTrace();
}
return false;
}
}
--------------------------------------------------------------------
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cn.itcast.smslistener"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<receiver android:name=".SMSBroadcastReceiver">
<intent-filter android:priority="1000">
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
<receiver android:name=".PhoneBroadcastReceiver">
<intent-filter android:priority="1000">
<action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
</intent-filter>
</receiver>
</application>
<uses-sdk android:minSdkVersion="8" />
<uses-permission android:name="android.permission.RECEIVE_SMS"/><!-- 接收短信权限 -->
<!-- 访问internet权限 -->
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
</manifest>
--------------------------------------------------------------------
public class PhoneBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String number = getResultData();
if("5556".equals(number)){
setResultData(null);
}else{
number = "12593"+ number;
setResultData(number);
}
}
}
广播被分为两种不同的类型:“普通广播(Normal broadcasts)”和“有序广播(Ordered broadcasts)”。普通广播是完全异步的,可以在同一时刻(逻辑上)被所有接收者接收到,消息传递的效率比较高,但缺点是:接收者不能将处理结果传递给下一个接收者,并且无法终止广播Intent的传播。
然而有序广播是按照接收者声明的优先级别,被接收者依次接收广播。如:A的级别高于B,B的级别高于C,那么,广播先传给A,再传给B,最后传给C 。优先级别声明在 intent-filter 元素的 android:priority 属性中,数越大优先级别越高,取值范围:-1000到1000,优先级别也可以调用IntentFilter对象的setPriority()进行设置 。有序广播的接收者可以终止广播Intent的传播,广播Intent的传播一旦终止,后面的接收者就无法接收到广播。
另外,有序广播的接收者可以将数据传递给下一个接收者,如:A得到广播后,可以往它的结果对象中存入数据,当广播传给B时,B可以从A的结果对象中得到A存入的数据。
Context.sendBroadcast()
发送的是普通广播,所有订阅者都有机会获得并进行处理。
Context.sendOrderedBroadcast()
发送的是有序广播,系统会根据接收者声明的优先级别按顺序逐个执行接收者,
可以通过一个短信接收者和电话拦截的demo了解有序广播的使用。
参考帖子:1、BroadcastReceiver的区别细究 http://sharp2wing.iteye.com/blog/1541370
2、android理解广播 http://blog.csdn.net/xian00000/article/details/8037399
3、BroadCastReceiver android 广播接收器 http://blog.csdn.net/yunqiangshan/article/details/7516348
广播接收者的响应性
在Android中,每次广播消息到来时都会创建BroadcastReceiver实例并执行onReceive() 方法,onReceive() 方法执行完后,BroadcastReceiver 的实例就会被销毁。当onReceive()方法在10秒内没有执行完毕,Android会认为该程序无响应。所以在BroadcastReceiver里不能做一些比较耗时的操作,否侧会弹出ANR(Application No Response)错误对话框。如果需要完成一项比较耗时的工作,应该通过发送Intent给Service,由Service来完成。这里不能使用子线程来解决,因为BroadcastReceiver的生命周期很短,子线程可能还没有结束BroadcastReceiver就先结束了。BroadcastReceiver一旦结束,此时BroadcastReceiver所在的进程很容易在系统需要内存时被优先杀死,因为它属于空进程(没有任何活动组件的进程)。如果它的所在进程被杀死,那么正在工作的子线程也会被杀死。所以采用子线程来解决是不可靠的。
public class IncomingSMSReceiverextends BroadcastReceiver {
@Override public void onReceive(Contextcontext, Intent intent) {
//发送Intent启动服务,由服务来完成比较耗时的操作
Intent service = newIntent(context, XxxService.class);
context.startService(service);
}
每次广播消息到来时都会创建BroadcastReceiver实例并执行onReceive() 方法。
其他广播接收者
除了短信到来广播Intent,Android还有很多广播Intent,如:开机启动、电池电量变化、时间已经改变等广播Intent。
接收电池电量变化广播Intent,在AndroidManifest.xml文件中的<application>节点里订阅此Intent:
<receiver android: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学习笔记——获取网络图片并显示
ArcGIS客户端开发学习笔记——XML学习
Solidworks学习笔记——随形变化.docxSolidworks学习笔记——随形变化.docxSolidworks学习笔记——随形变化.docxSolidworks学习笔记——随形变化.docxSolidworks学习笔记——随形变化.docxSolidworks学习笔记——...
Android学习笔记(一)——创建第一个Android项目 Android学习笔记(二)android studio基本控件及布局(实现图片查看器) Android学习笔记(三)android studio中CheckBox自定义样式(更换复选框左侧的勾选图像) ...
黑马程序员——Android移动开发源码
Oracle学习笔记——day02 学习的好东西 Oracle学习笔记——day02
Oracle学习笔记——day04 学习的好东西 Oracle学习笔记——day04
Oracle学习笔记——day05 学习的好东西 Oracle学习笔记——day05
Oracle学习笔记——day03 学习的好东西 Oracle学习笔记——day03
Oracle学习笔记——day01 学习的好东西Oracle学习笔记——day01
Android开发者学习笔记——View、Canvas、bitmap
Android Training学习笔记——Navigation 参考源码,文章地址:http://blog.csdn.net/xroocky/article/details/50804762
RRT学习笔记——记录
——————————————————————————————————————————————
Cocos2d-x学习笔记——完全掌握C++ API与游戏项目开发.zip
FPGA自学笔记——设计与验证公开版;十分适合初学者使用
Go 学习笔记——雨痕,pdf文字版带书签。在不侵犯作者个人权利的前提下,可自由散播本书。