BroadcastReceiver用于接收程序(包括系统程序和通常应用)经过sendBroadcast()方法发出的Broadcast intents。java
1) 建立须要启动BroadcastReceiver的Intent。android
2) 调用Context的sendBroadcast
()或sendOrderedBroadcast
()方法来启动指定的BroadcastReceiver。其中sendBroadcast
发送的是普通广播,sendOrderedBroadcast发送的是有序广播。缓存
当应用发出一个Broadcast Intent以后所匹配该Intent的组件均可能被启动。异步
第一步:建立BroadcastReceiver的子类:ide
因为BroadcastReceiver本质上是一种监听器,因此建立BroadcastReceiver的方法也很是简单,只须要建立一个BroadcastReceiver的子类而后重写onReceive (Context context, Intentintent)方法便可。ui
具体代码以下:this
public class MyBroadcastReceiver extends BroadcastReceiver { public static final String TAG = "BroadcastReceiverDemo" ; @Override public void onReceive(Context context, Intent intent) { String msg=intent.getExtras().get("msg").toString(); Log.i(TAG, "msg:"+msg); } }
第二步:注册BroadcastReceiverspa
一旦实现了BroadcastReceiver,接下就应该指定该BroadcastReceiver能匹配的Intent即注册BroadcastReceiver。注册BroadcastReceiver的方式有两种:.net
①静态注册:这种方法是在配置AndroidManifest.xml配置文件中注册,经过这种方式注册的广播为常驻型广播,也就是说若是应用程序关闭了,有相应事件触发,程序仍是会被系统自动调用运行。例如:debug
<!-- 在配置文件中注册BroadcastReceiver可以匹配的Intent --> <receiver android:name=".MyBroadcastReceiver"> <intent-filter> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </receiver>
②动态注册:这种方法是经过代码在.Java文件中进行注册。经过这种方式注册的广播为很是驻型广播,即它会跟随Activity的生命周期,因此在Activity结束前咱们须要调用unregisterReceiver(receiver)方法移除它。例如:
//经过代码的方式动态注册MyBroadcastReceiver MyBroadcastReceiver receiver=new MyBroadcastReceiver(); IntentFilter filter=new IntentFilter(); filter.addAction("android.intent.action.MyBroadcastReceiver"); //注册receiver registerReceiver(receiver, filter);
注意:若是咱们在Activity中注册了BroadcastReceiver,当这个Activity销毁的时候要主动撤销注册不然会出现异常。方法以下:
@Override protected void onDestroy() { super.onDestroy(); //当Activity销毁的时候取消注册BroadcastReceiver unregisterReceiver(receiver); }
BroadcastReceiver的生命周期,从对象调用它开始,到onReceiver方法执行完成以后结束。另外,每次广播被接收后会从新建立BroadcastReceiver对象,并在onReceiver方法中执行完就销毁,若是BroadcastReceiver的onReceiver方法中不能在10秒内执行完成,Android会出现ANR异常。因此不要在BroadcastReceiver的onReceiver方法中执行耗时的操做。
若是须要在BroadcastReceiver中执行耗时的操做,能够经过Intent启动Service来完成。但不能绑定Service。
特别是,您可能没法从一个BroadcastReceiver中显示一个对话框,或绑定到服务。对于前者,则应该使用NotificationManager的API。对于后者,你可使用Context.startService()来启动一个Service。
Broadcast的类型有两种:普通广播和有序广播。
Normal broadcasts(普通广播):Normal broadcasts是彻底异步的能够同一时间被全部的接收者接收到。消息的传递效率比较高。但缺点是接收者不能讲接收的消息的处理信息传递给下一个接收者也不能中止消息的传播。
Ordered broadcasts(有序广播):Ordered broadcasts的接收者按照必定的优先级进行消息的接收。如:A,B,C的优先级依次下降,那么消息先传递给A,在传递给B,最后传递给C。优先级别声明在中,取值为[-1000,1000]数值越大优先级别越高。优先级也可经过filter.setPriority(10)方式设置。 另外Ordered broadcasts的接收者能够经过abortBroadcast()的方式取消广播的传播,也能够经过setResultData和setResultExtras方法将处理的结果存入到Broadcast中,传递给下一个接收者。而后,下一个接收者经过getResultData()和getResultExtras(true)接收高优先级的接收者存入的数据。
1)静态注册 发送广播:
public class MainActivity extends Activity implements OnClickListener{ private Button btnSend,btnSend2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_broadcast); btnSend = (Button)findViewById(R.id.btnSend); btnSend2 = (Button)findViewById(R.id.btnSend2); btnSend.setOnClickListener(this); btnSend2.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btnSend: //没法经过abortBroadcast()的方式中止广播的传播, //也没法往Broadcast中存入数据由于它是异步的 //若是往Broadcast中存入数据会抛异常 Intent intent=new Intent(); intent.setAction("android.intent.action.MyBroadcastReceiver"); intent.putExtra("msg", "这是一个普通的广播"); sendBroadcast(intent); break; case R.id.btnSend2: //1.能够经过abortBroadcast可终止广播的传播 //2.按优先级的不一样,优先接收到Broadcast的Receiver可经过 //setResultExtras(Bundle)方法将处理结果存入Broadcast中, //下一个Receiver 经过 Bundle bundle=getResultExtras(true)方法 //获取上一个 Receiver传来的数据. Intent intent2=new Intent(); intent2.setAction("android.intent.action.OrderedBroadcastReceiver"); intent2.putExtra("msg", "这是一个有序的广播"); sendOrderedBroadcast(intent2, null); break; default: break; } } }
MyBroadcastReceiver.java:接收广播
public class MyBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String msg=intent.getExtras().get("msg").toString(); System.out.println("MyBroadcastReceiver收到Action名为:"+intent.getAction().toString() + "\n消息的内容是:"+msg); } }
FirstBroadcastReceiver.java接收广播
public class FirstBroadcastReceiver extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { String msg=intent.getExtras().get("msg").toString(); setResultData("你好我是第一个广播!"); System.out.println("FirstBroadcastReceiver收到Action名为:" + intent.getAction().toString() + "\n消息的内容是:"+msg); //中止广播 //abortBroadcast(); } }
SecondBroadcastReceiver.java接收广播
public class SecondBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String msg=intent.getExtras().get("msg").toString(); String result=getResultData(); System.out.println("SecondBroadcastReceiver收到Action名为:"+intent.getAction().toString() +"\n消息的内容是:"+msg+"\n上一个接受者传来的reult:"+result); } }
配置文件AndroidManifest.xml:
<!-- 在配置文件中注册MyBroadcastReceiver可以匹配的Intent --> <receiver android:name=".MyBroadcastReceiver"> <intent-filter> <action android:name="android.intent.action.MyBroadcastReceiver"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </receiver> <!-- 在配置文件中注册SecondBroadcastReceiver可以匹配的Intent --> <!--优先级的设定 FirstBroadcastReceiver大于SecondBroadcastReceiver,优先级的范围-1000~1000 --> <receiver android:name=".FirstBroadcastReceiver"> <intent-filter android:priority="200"> <action android:name="android.intent.action.OrderedBroadcastReceiver"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </receiver> <receiver android:name=".SecondBroadcastReceiver"> <intent-filter android:priority="100"> <action android:name="android.intent.action.OrderedBroadcastReceiver"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </receiver>
界面:
日志打印:
点击普通广播
点击有序广播
2)动态注册 发送广播 以短信接收为例:
public class MainActivity extends ActionBarActivity { private MyBroadcastReceiver myBroadcastReceiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); myBroadcastReceiver = new MyBroadcastReceiver(); findViewById(R.id.btn1).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { IntentFilter filter=new IntentFilter(); filter.addAction("android.provider.Telephony.SMS_RECEIVED"); registerReceiver(myBroadcastReceiver, filter); System.out.println("注册了广播"); } }); findViewById(R.id.btn2).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { unregisterReceiver(myBroadcastReceiver); System.out.println("销毁了广播"); } }); } }
public class MyBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { System.out.println("MyBroadcastReceiver收到Action名为:"+intent.getAction().toString()); } }
不须要在AndroidManifest.xml配置文件中注册,不过使用带短信,须要加上短信权限
<uses-permission android:name="android.permission.RECEIVE_SMS"/
效果图:
先注册广播,而后在Emulator Control中发短信:
若是不知道这步在哪里,请看 Android模拟器用命令和DDMS模拟来电和短信
日志打印:
如:ACTION_TIME_TICK,系统时钟广播,系统每分钟都会发送一个这样的广播,若是在应用开发中,有些逻辑依赖于系统时钟,能够注册一个广播接收者。这是一个受保护的action,只有系统才能发送这个广播,而且,在manifest文件中注册的广播接收者不能接收到该广播,若要接收该广播,必须在代码中注册广播接收者
registerReceiver(new BroadcastReceiver(){ @Override public void onReceive(Context context, Intent intent) { Log.i("xxxx", "TIME_TICK"); } },new IntentFilter(Intent.ACTION_TIME_TICK));
Intent.ACTION_AIRPLANE_MODE_CHANGED
//关闭或打开飞行模式时的广播
Intent.ACTION_BATTERY_CHANGED
//充电状态,或者电池的电量发生变化
//电池的充电状态、电荷级别改变,不能经过组建声明接收这个广播,只有经过Context.registerReceiver()注册
Intent.ACTION_BATTERY_LOW
//表示电池电量低
Intent.ACTION_BATTERY_OKAY
//表示电池电量充足,即从电池电量低变化到饱满时会发出广播
Intent.ACTION_BOOT_COMPLETED
//在系统启动完成后,这个动做被广播一次(只有一次)。
Intent.ACTION_CAMERA_BUTTON
//按下照相时的拍照按键(硬件按键)时发出的广播
Intent.ACTION_CLOSE_SYSTEM_DIALOGS
//当屏幕超时进行锁屏时,当用户按下电源按钮,长按或短按(无论有没跳出话框),进行锁屏时,android系统都会广播此Action消息
Intent.ACTION_CONFIGURATION_CHANGED
//设备当前设置被改变时发出的广播(包括的改变:界面语言,设备方向,等,请参考Configuration.java)
Intent.ACTION_DATE_CHANGED
//设备日期发生改变时会发出此广播
Intent.ACTION_DEVICE_STORAGE_LOW
//设备内存不足时发出的广播,此广播只能由系统使用,其它APP不可用?
Intent.ACTION_DEVICE_STORAGE_OK
//设备内存从不足到充足时发出的广播,此广播只能由系统使用,其它APP不可用?
Intent.ACTION_DOCK_EVENT
//发出此广播的地方frameworks\base\services\java\com\android\server\DockObserver.java
Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
//移动APP完成以后,发出的广播(移动是指:APP2SD)
Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE
//正在移动APP时,发出的广播(移动是指:APP2SD)
Intent.ACTION_GTALK_SERVICE_CONNECTED
//Gtalk已创建链接时发出的广播
Intent.ACTION_GTALK_SERVICE_DISCONNECTED
//Gtalk已断开链接时发出的广播
Intent.ACTION_HEADSET_PLUG
//在耳机口上插入耳机时发出的广播
Intent.ACTION_INPUT_METHOD_CHANGED
//改变输入法时发出的广播
Intent.ACTION_LOCALE_CHANGED
//设备当前区域设置已更改时发出的广播
Intent.ACTION_MANAGE_PACKAGE_STORAGE
//
Intent.ACTION_MEDIA_BAD_REMOVAL
//未正确移除SD卡(正确移除SD卡的方法:设置--SD卡和设备内存--卸载SD卡),但已把SD卡取出来时发出的广播
//广播:扩展介质(扩展卡)已经从 SD 卡插槽拔出,可是挂载点 (mount point) 还没解除 (unmount)
Intent.ACTION_MEDIA_BUTTON
//按下"Media Button" 按键时发出的广播,假若有"Media Button"按键的话(硬件按键)
Intent.ACTION_MEDIA_CHECKING
//插入外部储存装置,好比SD卡时,系统会检验SD卡,此时发出的广播?
Intent.ACTION_MEDIA_EJECT
//已拔掉外部大容量储存设备发出的广播(好比SD卡,或移动硬盘),无论有没有正确卸载都会发出此广播?
//广播:用户想要移除扩展介质(拔掉扩展卡)。
Intent.ACTION_MEDIA_MOUNTED
//插入SD卡而且已正确安装(识别)时发出的广播
//广播:扩展介质被插入,并且已经被挂载。
Intent.ACTION_MEDIA_NOFS
//
Intent.ACTION_MEDIA_REMOVED
//外部储存设备已被移除,无论有没正确卸载,都会发出此广播?
// 广播:扩展介质被移除。
Intent.ACTION_MEDIA_SCANNER_FINISHED
//广播:已经扫描完介质的一个目录
Intent.ACTION_MEDIA_SCANNER_SCAN_FILE
//
Intent.ACTION_MEDIA_SCANNER_STARTED
//广播:开始扫描介质的一个目录
Intent.ACTION_MEDIA_SHARED
// 广播:扩展介质的挂载被解除 (unmount),由于它已经做为 USB 大容量存储被共享。
Intent.ACTION_MEDIA_UNMOUNTABLE
//
Intent.ACTION_MEDIA_UNMOUNTED
// 广播:扩展介质存在,可是尚未被挂载 (mount)。
Intent.ACTION_NEW_OUTGOING_CALL
//
Intent.ACTION_PACKAGE_ADDED
//成功的安装APK以后
//广播:设备上新安装了一个应用程序包。
//一个新应用包已经安装在设备上,数据包括包名(最新安装的包程序不能接收到这个广播)
Intent.ACTION_PACKAGE_CHANGED
//一个已存在的应用程序包已经改变,包括包名
Intent.ACTION_PACKAGE_DATA_CLEARED
//清除一个应用程序的数据时发出的广播(在设置--应用管理--选中某个应用,以后点清除数据时?)
//用户已经清除一个包的数据,包括包名(清除包程序不能接收到这个广播)
Intent.ACTION_PACKAGE_INSTALL
//触发一个下载而且完成安装时发出的广播,好比在电子市场里下载应用?
//
Intent.ACTION_PACKAGE_REMOVED
//成功的删除某个APK以后发出的广播
//一个已存在的应用程序包已经从设备上移除,包括包名(正在被安装的包程序不能接收到这个广播)
Intent.ACTION_PACKAGE_REPLACED
//替换一个现有的安装包时发出的广播(无论如今安装的APP比以前的新仍是旧,都会发出此广播?)
Intent.ACTION_PACKAGE_RESTARTED
//用户从新开始一个包,包的全部进程将被杀死,全部与其联系的运行时间状态应该被移除,包括包名(从新开始包程序不能接收到这个广播)
Intent.ACTION_POWER_CONNECTED
//插上外部电源时发出的广播
Intent.ACTION_POWER_DISCONNECTED
//已断开外部电源链接时发出的广播
Intent.ACTION_PROVIDER_CHANGED
//
Intent.ACTION_REBOOT
//重启设备时的广播
Intent.ACTION_SCREEN_OFF
//屏幕被关闭以后的广播
Intent.ACTION_SCREEN_ON
//屏幕被打开以后的广播
Intent.ACTION_SHUTDOWN
//关闭系统时发出的广播
Intent.ACTION_TIMEZONE_CHANGED
//时区发生改变时发出的广播
Intent.ACTION_TIME_CHANGED
//时间被设置时发出的广播
Intent.ACTION_TIME_TICK
//广播:当前时间已经变化(正常的时间流逝)。
//当前时间改变,每分钟都发送,不能经过组件声明来接收,只有经过Context.registerReceiver()方法来注册
Intent.ACTION_UID_REMOVED
//一个用户ID已经从系统中移除发出的广播
//
Intent.ACTION_UMS_CONNECTED
//设备已进入USB大容量储存状态时发出的广播?
Intent.ACTION_UMS_DISCONNECTED
//设备已从USB大容量储存状态转为正常状态时发出的广播?
Intent.ACTION_USER_PRESENT
//
Intent.ACTION_WALLPAPER_CHANGED
//设备墙纸已改变时发出的广播
例子1:Android开机广播和关机广播
编写一个继承BroadcastReceiver的类,接受系统启动关闭广播。代码以下:
public class LaunchReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { System.out.println("系统启动完毕"); } }
public class ShutdownReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { System.out.println("系统要关闭了"); } }
<receiver android:name=".LaunchReceiver"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED"/> </intent-filter> </receiver> <receiver android:name=".ShutdownReceiver"> <intent-filter> <action android:name="android.intent.action.ACTION_SHUTDOWN"/> </intent-filter> </receiver>
同时应添加所须要的权限:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
关机日志打印:
开机日志打印:
例子2:经过终止广播 阻止用户收到短信
系统收到短信,发出的广播属于有序广播。若是想阻止用户收到短信,可自定义Receiver,设置高优先级,率先得到接收短信的广播,并终止广播。接收短信的广播名android.provider.Telephony.SMS_RECEIVED。注意:程序一旦在某个模拟器运行,将一直阻止短信,只有注释掉abortBroadcast(),从新运行,方可正常。
public class MySmsResevicer extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { System.out.println("on receive"); abortBroadcast(); } }
<receiver android:name=".MySmsResevicer"> <intent-filter android:priority="1000"> <action android:name="android.provider.Telephony.SMS_RECEIVED"/> </intent-filter> </receiver>
abortBroadcast ():
这个方法能够截获由 sendOrderedBroadcast () 发送来的 广播,让其它广播接收者没法收到这个广播。
clearAbortBroadcast ()
这个方法是针对上面的 abortBroadcast() 方法的,用于取消截获广播。这样它的下一级广播接收者就可以收到该广播了。
getAbortBroadcast ()
这个方法做用是:判断是否调用了 abortBroadcast (),若是先调用 abortBroadcast (),接着再调用 getAbortBroadcast (),将返回 true; 若是在调用 abortBroadcast() 、 clearAbortBroadcast ()
getAbortBroadcast (),将返回 false;
public final boolean getDebugUnregister ()
Since: API Level 1
Return the last value given to setDebugUnregister(boolean) .
getResultCode ()
若是用下面四个方法发送得广播,返回码为: -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)
getResultData ()
获得发送广播时设置的 initialData 的数据;
getResultExtras (boolean makeMap)
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 都可以获得数据。
isInitialStickyBroadcast ()
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 ;
isOrderedBroadcast ()
sendStickyOrderedBroadcast(intent, resultReceiver, scheduler,
initialCode, initialData, initialExtras)
上面这个方法发送时,获得的是 true;
判断是不是有序广播;
onReceive (Context context, Intent intent)
public IBinder peekService (Context myContext, Intent service)
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.
setDebugUnregister (boolean debug)
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