BroadCastReceiver 源码位于: framework/base/core/java/android.content.BroadcastReceiver.java java
广播接收者( BroadcastReceiver )用于接收广播 Intent ,广播 Intent 的发送是经过调用 Context.sendBroadcast() 、 Context.sendOrderedBroadcast() 来实现的。一般一个广播 Intent 能够被订阅了此 Intent 的多个广播接收者所接收。android
广播是一种普遍运用的在应用程序之间传输信息的机制 。而 BroadcastReceiver 是对发送出来的广播进行过滤接收并响应的一类组件;缓存
来自普通应用程序,如一个应用程序通知其余应用程序某些数据已经下载完毕。异步
BroadcastReceiver 自身并不实现图形用户界面,可是当它收到某个通知后, BroadcastReceiver 能够启动 Activity 做为响应,或者经过 NotificationMananger 提醒用户,或者启动 Service 等等。ide
在 Android 里面有各类各样的广播,好比电池的使用状态,电话的接收和短信的接收都会产生一个广播,应用程序开发者也能够监听这些广播并作出程序逻辑的处理。如图: ui
用接收短信举例:this
第一种方式 :spa
实现 线程
public class MyBroadcastReceiver extends BroadcastReceiver { debug
// action 名称
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" />
第二种方式:
// 广播接收者 - 广播的接收
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);
描述了 Android 中广播的生命周期,其次它并不像 Activity 同样复杂,运行原理很简单以下图:
生命周期只有十秒左右,若是在 onReceive() 内作超过十秒内的事情,就会报错 。
每次广播到来时 , 会从新建立 BroadcastReceiver 对象 , 而且调用 onReceive() 方法 , 执行完之后 , 该对象即被销毁 . 当 onReceive() 方法在 10 秒内没有执行完毕, Android 会认为该程序无响应 . 因此在
BroadcastReceiver 里不能作一些比较耗时的操做 , 否侧会弹出 ANR(Application No
Response) 的对话框 . 。(如图):
怎么用好 BroadcastReceiver ?
若是须要完成一项比较耗时的工做 , 应该经过发送 Intent 给 Service, 由 Service 来完成 . 这里不能使用子线程来解决 , 由于 BroadcastReceiver 的生命周期很短 , 子线程可能尚未结束
BroadcastReceiver 就先结束了 .BroadcastReceiver 一旦结束 , 此时 BroadcastReceiver 的
所在进程很容易在系统须要内存时被优先杀死 , 由于它属于空进程 ( 没有任何活动组件的进程 ). 若是它的宿主进程被杀死 , 那么正在工做的子线程也会被杀死 . 因此采用子线程来解决是不可靠的 .
普通广播 (Normal broadcasts)
发送一个广播,因此监听该广播的广播接收者均可以监听到改广播。
异步广播 , 当处理完以后的Intent ,依然存在,这时候registerReceiver(BroadcastReceiver, IntentFilter) 还能收到他的值,直到你把它去掉 , 不能将处理结果传给下一个接收者 , 没法终止广播 .
有序广播 (Ordered broadcasts)
按照接收者的优先级顺序接收广播 , 优先级别在 intent-filter 中的 priority 中声明 ,-1000 到
1000 之间 , 值越大 , 优先级越高 . 能够终止广播意图的继续传播 . 接收者能够篡改内容 .
该组件接收被广播的 intent,Context 能够经过 sendBroadcast() 和 sendOrderedBroadcast()
方法实现广播的发送 .
首先在须要发送信息的地方 ,把要发送的信息和用于过滤的信息 ( 如 Action 、 Category) 装入一个 Intent 对象 ,而后经过调用 Context.sendBroadcast() 、 sendOrderBroadcast() 或 sendStickyBroadcast() 方法,把 Intent 对象以广播方式发送出去。
使用 sendBroadcast() 或 sendStickyBroadcast() 方法发出去的 Intent ,全部知足条件的 BroadcastReceiver 都会随机地执行其 onReceive() 方法
sendBroadcast(intent);
Intent intent = new Intent( "cn.lenovo.yangguangf " );
sendBroadcast(intent);
priority :这个是 AndroidManifest.xml 中 intent-filter 的参数。
< receiver android:name = ".MyBroadcastReceiver" >
< intent-filter android:priority = "1000" >
< action android:name = "cn.lenovo.yangguangfu" />
</ intent-filter >
</ receiver >
sendOrderedBroadcast(intent, receiverPermission);
1 ,他决定该广播的级别,级别数值是在 -1000 到 1000 之间 , 值越大 , 优先级越高;
2 ,同级别接收是前后是随机的;级别低的收到广播;
3 ,在 android 系统中只要监听该广播的接收者,都可以收到 sendBroadcast(intent) 发出的广播 ;
3 ,不能截断广播的继续传播,
4 ,实验现象,在这个方法发来的广播中,代码注册方式中,收到的广播的前后和注明优先级最高的他们的前后是随机。若是都没有优先级,代码注册收到为最早。
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;
intent The Intent to broadcast; all receivers matching this Intent will receive the broadcast.
receiverPermission String naming a permissions that a receiver must hold in order to receive your broadcast. If null, no permission is required.
resultReceiver Your own BroadcastReceiver to treat as the final receiver of the broadcast.
scheduler A custom Handler with which to schedule the resultReceiver callback; if null it will be scheduled in the Context's main thread.
initialCode An initial value for the result code. Often Activity.RESULT_OK.
initialData An initial value for the result data. Often null.
initialExtras An initial value for the result extras. Often null.
1, 该广播的级别有级别之分,级别数值是在 -1000 到 1000 之间 , 值越大 , 优先级越高;
2, 同级别接收是前后是随机的,再到级别低的收到广播;
3, 同级别接收是前后是随机的,若是先接收到的把广播截断了,同级别的例外的接收者是没法收到该广播的。( abortBroadcast() )
4 ,能截断广播的继续传播,高级别的广播收到该广播后,能够决定把该钟广播是否截断掉。
5 ,实验现象,在这个方法发来的广播中,代码注册方式中,收到广播前后次序为:注明优先级的、代码注册的、没有优先级的;若是都没有优先级,代码注册收到为最早。
sendStickyBroadcast(intent);
当处理完以后的Intent ,依然存在,直到你把它去掉。
发这个广播须要权限<uses-permission android:name="android.permission.BROADCAST_STICKY" />
去掉是用这个方法removeStickyBroadcast(intent); 但别忘了在执行这个方法的应用里面 AndroidManifest.xml 一样要加上面的权限;
sendStickyOrderedBroadcast(intent, resultReceiver, scheduler,
initialCode, initialData, initialExtras)
这个方法具备有序广播的特性也有异步广播的特性;
发送这个广播要: <uses-permission android:name="android.permission.BROADCAST_STICKY" /> 这个权限。才能使用这个方法。若是您并不拥有该权限,将抛出 SecurityException 的。
实验现象( sendStickyOrderedBroadcast ()中),在这个方法发来的广播中,代码注册方式中,收到广播前后次序为:注明优先级的、代码注册的、没有优先级的;若是都没有优先级,代码注册收到为最早。
注册广播方法一: registerReceiver(BroadcastReceiver receiver, IntentFilter filter) ,第一个参数是咱们要处理广播的 BroadcastReceiver (广播接收者,能够是系统的,也能够是自定义的);第二个参数是意图过滤器。
注册广播方法二: registerReceiver(receiver, filter, broadcastPermission, scheduler) ,第一个参数是 BroadcastReceiver (广播接收者,能够是系统的,也能够是自定义的);第二个参数是意图过滤器;第三个参数是广播权限;第四个参数是 Hander ;
注意:权限重复现象,若是功能清单文件里注册了权限,在该方法再注册,则 receiver 没法收到广播,若是 功能清单文件里没有注册了权限,该方法注册也没法收到。当该方法没有注册权限,功能清单里注册的时候, receiver 能收到广播。
总结:在 Activity 中代码注册广播建议在: onResume() 中注册;
思惟拓展: 1 ,若是在代码调用 registerReceiver(BroadcastReceiver receiver, IntentFilter filter) 十次( receiver , filter 的参数是同一参数),那么是否当该广播发送来的时候会收到十次呢?
2 ,注销是否也要注销十次才能把广播所有注销呢?
< receiver android:name = ".MyBroadcastReceiver" >
< intent-filter android:priority = "900" >
< action android:name = "cn.lenovo.yangguangfu" />
</ intent-filter >
</ receiver >
有时候还要根据发送广播是否指定权限,来决定是否要权限;
// 代码中注销广播
/unregisterReceiver(mBatteryInfoReceiver);
在 Activity 中代码注销广播建议在: onPuase() 中注销;
不要这这里面注销 Activity.onSaveInstanceState(), 由于这个方法是保存 Intent 状态的。
这个方法能够截获由 sendOrderedBroadcast () 发送来的 广播,让其它广播接收者没法收到这个广播。
这个方法是针对上面的 abortBroadcast() 方法的,用于取消截获广播。这样它的下一级广播接收者就可以收到该广播了。
这个方法做用是:判断是否调用了 abortBroadcast (),若是先调用 abortBroadcast (),接着再调用 getAbortBroadcast (),将返回 true; 若是在调用 abortBroadcast() 、 clearAbortBroadcast ()
getAbortBroadcast (),将返回 false;
Since: API Level 1
Return the last value given to setDebugUnregister(boolean)
.
若是用下面四个方法发送得广播,返回码为: -1 ;
// sendBroadcast(intent);
// sendBroadcast(intent, receiverPermission);
// sendOrderedBroadcast(intent, receiverPermission);
// sendStickyBroadcast(intent);
若是用下面两个方法发送得广播,返回码为:根据你设置 initialCode 的数字是多少就是多少;
// sendStickyOrderedBroadcast(intent, resultReceiver, scheduler,
// initialCode, initialData, initialExtras)
// sendOrderedBroadcast(intent, receiverPermission, resultReceiver,
// scheduler, initialCode, initialData, initialExtras)
获得发送广播时设置的 initialData 的数据;
If true then a new empty Map will be made for you if the current Map is null; if false you should be prepared to receive a null Map.
获得由
sendStickyOrderedBroadcast(intent, resultReceiver, scheduler,
// initialCode, initialData, initialExtras) ;
// sendOrderedBroadcast(intent, receiverPermission, resultReceiver,
// scheduler, initialCode, initialData, initialExtras)
中 initialExtras 传入的参数。
实验:我用上面两个方法发了 initialExtras (这个一个 Bundle )传入的参数时,只要不为空,那么 makeMap 是否为 true 和 false 都可以获得数据。
Returns true if the receiver is currently processing the initial value of a sticky broadcast -- that is, the value that was last broadcast and is currently held in the sticky cache, so this is not directly the result of a broadcast right now.
若是广播接收者是目前处理的一个宿主的广播的初始值,将返回 true , - 也就是说,这个值是最后的广播出的值,目前正在举行的宿主缓存,因此这并非直接致使了如今的广播。
实验:在第三个应用中调用这个方法,不管你用哪一种方式发送广播,这个方法获得的老是 false ;在发送广播 的 resultReceiver 广播接收者里面调用,获得的也是 false ;
sendStickyOrderedBroadcast(intent, resultReceiver, scheduler,
initialCode, initialData, initialExtras)
上面这个方法发送时,获得的是 true;
判断是不是有序广播;
Provide a binder to an already-running service. This method is synchronous and will not start the target service if it is not present, so it is safe to call from onReceive.
Parameters:
myContext The Context that had been passed to onReceive(Context, Intent)
service The Intent indicating the service you wish to use. See Context.startService(Intent) for more information.
Control inclusion of debugging help for mismatched calls to {@ Context#registerReceiver(BroadcastReceiver, IntentFilter) Context.registerReceiver()}. If called with true, before given to registerReceiver(), then the callstack of the following Context.unregisterReceiver()
call is retained, to be printed if a later incorrect unregister call is made. Note that doing this requires retaining information about the BroadcastReceiver for