广播是一种广泛的应用程序之间传输信息的机制。BroadcastReceiver 是对发送出来的广播进行过滤接收并响应的一类组件。广播接收者( BroadcastReceiver )用于接收广播 Intent ,广播 Intent 的发送是通过调用Context.sendBroadcast() 、 Context.sendOrderedBroadcast() 来实现的。通常一个广播 Intent 可以被订阅了此Intent 的多个广播接收者所接收。
在 Android 里面有各种各样的广播,比如电池的使用状态,电话的接收和短信的接收都会产生一个广播,应用程序开发者可以实现一个广播接收者监听这些广播并做出程序逻辑的处理。
广播的简单示意图如下:
广播的实现由两种方式:
静态广播,其实现的方式如下:
<span style="font-size:18px;">public class MyBroadcastReceiver extends BroadcastReceiver {
String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED" ;//接收系统短信广播
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals( SMS_RECEIVED )) {
// 相关处理 : 地域变换、电量不足、来电来信;
}
}
}
//系统注册:在 AndroidManifest.xml 中注册
< receiver android:name = ".MyBroadcastReceiver" >
< intent-filter android:priority = "1000" >
< action android:name = "android.provider.Telephony.SMS_RECEIVED" />
</ intent-filter >
</ receiver > 当然了需要权限 :
< uses-permission android:name = "android.permission.RECEIVE_SMS" />
< uses-permission android:name = "android.permission.SEND_SMS" />
</span>
动态广播,其实现方式如下:
<span style="font-size:18px;">
// 广播接收者 - 广播的接收
private BroadcastReceiver myBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// 相关处理,如收短信,监听电量变化信息
}
};
代码中注册:
IntentFilter intentFilter = new IntentFilter( "android.provider.Telephony.SMS_RECEIVED " );
registerReceiver( mBatteryInfoReceiver , intentFilter);
</span>
广播生命周期
生命周期只有十秒左右,如果在 onReceive() 内做超过十秒内的事情,就会报错 。
每次广播到来时 , 会重新创建 BroadcastReceiver 对象 , 并且调用 onReceive() 方法 ,执行完以后,该对象即被销毁。当 onReceive() 方法在 10 秒内没有执行完毕, Android 会认为该程序无响应。所以在BroadcastReceiver 里不能做一些比较耗时的操作,否侧会弹出 ANR(Application NoResponse) 的对话框 。
怎么用好 BroadcastReceiver?
如果需要完成一项比较耗时的工作,应该通过发送 Intent 给 Service,由 Service 来完成。这里不能使用子线程来解决,因为 BroadcastReceiver 的生命周期很短,子线程可能还没有结束BroadcastReceiver 就先结束了 。BroadcastReceiver 一旦结束,此时 BroadcastReceiver 的所在进程很容易在系统需要内存时被优先杀死,因为它属于空进程 ( 没有任何活动组件的进程 )。如果它的宿主进程被杀死,那么正在工作的子线程也会被杀死。所以采用子线程来解决是不可靠的。
广播类型
普通广播(无序广播) (Normal broadcasts):发送一个广播,所有监听该广播的广播接收者都可以监听到该广播。
有序广播 (Ordered broadcasts):按照接收者的优先级顺序接收广播,优先级别在 intent-filter 中的 priority 中声明,-1000 到1000 之间,值越大,优先级越高。可以终止广播意图的继续传播,接收者可以篡改内容。 abortBroadcast();//中止有序广播向下传播
异步广播(粘性消息):sendStickyBroadcast(intent);
广播的收发
首先在需要发送信息的地方 ,把要发送的信息和用于过滤的信息 ( 如 Action 、 Category) 装入一个 Intent 对象,然后通过调用 Context.sendBroadcast() 、 sendOrderBroadcast() 或 sendStickyBroadcast() 方法,把 Intent对象以广播方式发送出去。使用 sendBroadcast() 或 sendStickyBroadcast() 方法发出去的 Intent ,所有满足条件的 BroadcastReceiver 都会随机地执行其 onReceive() 方法。
普通广播的发送和接收:
sendBroadcast(intent);
Intent intent = new Intent( "cn.warmtel.xinhua" );
sendBroadcast(intent);
priority :这个是 AndroidManifest.xml 中 intent-filter 的参数。
< receiver android:name = ".MyBroadcastReceiver" >
< intent-filter android:priority = "1000" >
< action android:name = "cn.warmtel.xinhua />
</ intent-filter >
</ receiver >
1 ,android:priority 他决定该广播的级别,级别数值是在 -1000 到 1000 之间 , 值越大 , 优先级越高;
2 ,同级别接收是先后是随机的;级别低的后收到广播;
3 ,在 android 系统中只要监听该广播的接收者,都能够收到 sendBroadcast(intent) 发出的广播 ;
4 ,不能截断广播的继续传播,
5 ,实验现象,在这个方法发来的广播中,代码注册方式中,收到的广播的先后和注明优先级最高的他们的先后是随机。如果都没有优先级,代码注册收到为最先。
有序广播的发送和接收:
sendOrderedBroadcast(intent, receiverPermission);
sendOrderedBroadcast(intent, receiverPermission, resultReceiver,scheduler, initialCode, initialData, initialExtras)
意图,广播,所有匹配的这一意图将接收机接收广播。receiverPermission 这是权限,一个接收器必须持以接收您的广播。如果为 null ,不经许可的要求。 resultReceiver 您自己 BroadcastReceiver 来当作最后的广播接收器。 调度自定义处理程序,用以安排 resultReceiver 回调 ; 如果为 null 将语境中的主线程举行。 initialCode 一种结果代码的初始值。通常为 Activity.RESULT_OK 。这个值是 -1 ;为其他 int 型 也可以,如 0,1,2; initialData 一种结果数据的初始值。通常情况下为空 , 是 String 类型 ;initialExtras 一种结果额外的初始值。通常情况下为空 , 是 Bundle;
1, 该广播的级别有级别之分,级别数值是在 -1000 到 1000 之间 , 值越大 , 优先级越高;
2, 同级别接收是先后是随机的,再到级别低的收到广播;
3, 同级别接收是先后是随机的,如果先接收到的把广播截断了,同级别的例外的接收者是无法收到该广播的。(abortBroadcast() )
4 ,能截断广播的继续传播,高级别的广播收到该广播后,可以决定把该钟广播是否截断掉。
5 ,实验现象,在这个方法发来的广播中,代码注册方式中,收到广播先后次序为:注明优先级的、代码注册的、没有优先级的;如果都没有优先级,代码注册收到为最先。
广播注册与注销
代码中注册广播方法一:registerReceiver(BroadcastReceiver receiver, IntentFilter filter)第一个参数是我们要处理广播的 BroadcastReceiver (广播接收者,可以是系统的,也可以是自定义的);第二个参数是意图过滤器。
代码中注册广播方法二: registerReceiver(receiver, filter, broadcastPermission, scheduler)
第一个参数是BroadcastReceiver (广播接收者,可以是系统的,也可以是自定义的);第二个参数是意图过滤器;第三个参数是广播权限;第四个参数是 Hander ;
注意:权限重复现象,如果功能清单文件里注册了权限,在该方法再注册,则 receiver 无法收到广播,如果 功能清单文件里没有注册了权限,该方法注册也无法收到。当该方法没有注册权限,功能清单里注册的时候, receiver 能收到广播。在 Activity 中代码注册广播建议在: onResume() 中注册。
代码中注销广播:unregisterReceiver(mBatteryInfoReceiver);在 Activity 中代码注销广播建议在: onPuase() 中注销;
通过下面的代码实例来进行操作:
/**
* BroadcastReceiver作用 :接收过滤响应广播(intent对象)
* 实现步骤
* 1.定义BroadcastReceiver
* 2.注册BroadcastReceiver
*
*
*/
public class SmsBroadCastReceiver extends BroadcastReceiver {
private static boolean incomingFlag = false;
private static String incoming_number = null;
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals("android.provider.Telephony.SMS_RECEIVED")) {
Toast.makeText(context, "接收短消息静态广播", Toast.LENGTH_SHORT).show();
Logs.v("接收短消息静态广播 >>>>>>>>>>>>>>>> ");
} else if (action.equals(MyReceiverActivity.ACTION_SCXH)) {
Toast.makeText(context, "自定义静态广播接收到", Toast.LENGTH_SHORT).show();
Logs.v("自定义静态广播 >>>>>>>>>>>>>>>> ");
} else if (action.equals("android.intent.action.NEW_OUTGOING_CALL")) {
//如果是拨打电话
incomingFlag = false;
String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
Logs.i("拨打电话:" + phoneNumber);
} else if (action.equals("android.intent.action.PHONE_STATE")) {
// 如果是来电
TelephonyManager tm = (TelephonyManager) context.getSystemService(Service.TELEPHONY_SERVICE);
switch (tm.getCallState()) {
case TelephonyManager.CALL_STATE_RINGING:
incomingFlag = true;// 标识当前是来电
incoming_number = intent.getStringExtra("incoming_number");
Logs.i("来电 :" + incoming_number);
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
if (incomingFlag) {
Logs.i("摘机(正在通话中) :" + incoming_number);
}
break;
case TelephonyManager.CALL_STATE_IDLE:
if (incomingFlag) {
Logs.i("空闲 >>>>>");
}
break;
}
}
}
}
系统注册:在 AndroidManifest.xml 中注册,其代码如下:
<receiver android:name="com.warmtel.android.receiver.systemreceiver.SmsBroadCastReceiver" >
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
<action android:name="android.intent.action.PHONE_STATE" />
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
<action android:name="com.warmtel.android.receiver_ACTION_XH" />
</intent-filter>
</receiver>
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
自定义广播发送,其代码如下:
Intent intent = new Intent(""com.warmtel.android.receiver_ACTION_XH"");
sendBroadcast(intent);
实现电话的监听,其代码如下:
private void receiverPhoneStateListener(){
// 获取电话通讯服务
TelephonyManager tpm = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
// 创建一个监听对象,监听电话状态改变事件
tpm.listen(new MyPhoneStateListener(),PhoneStateListener.LISTEN_CALL_STATE);
}
class MyPhoneStateListener extends PhoneStateListener {
@Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_IDLE: // 空闲
Logs.d("空闲 >>>>> ");
break;
case TelephonyManager.CALL_STATE_RINGING: // 来电
Logs.v("来电 >>>>> ");
break;
case TelephonyManager.CALL_STATE_OFFHOOK: // 摘机(正在通话中)
Logs.w("摘机(正在通话中) >>>>> ");
break;
}
}
}