1、BroadcastReceiver简介:

BroadcastReceiver用于接收程序(包括系统程序和一般应用)通过sendBroadcast()方法发出的Broadcast intents。

2、程序启动BroadcastReceiver的步骤(发出广播):

1) 创建需要启动BroadcastReceiver的Intent。

2) 调用Context的sendBroadcast()或sendOrderedBroadcast()方法来启动指定的BroadcastReceiver。其中sendBroadcast发送的是普通广播,sendOrderedBroadcast发送的是有序广播。

当应用发出一个Broadcast Intent之后所匹配该Intent的组件都可能被启动。

3、创建BroadcastReceiver的步骤:

第一步:创建BroadcastReceiver的子类:

由于BroadcastReceiver本质上是一种监听器,所以创建BroadcastReceiver的方法也非常简单,只需要创建一个BroadcastReceiver的子类然后重写onReceive (Context context, Intentintent)方法即可。

具体代码如下:

publicclassMyBroadcastReceiverextendsBroadcastReceiver{publicstaticfinalStringTAG="BroadcastReceiverDemo";@OverridepublicvoidonReceive(Contextcontext,Intentintent){Stringmsg=intent.getExtras().get("msg").toString();Log.i(TAG,"msg:"+msg);}}

第二步:注册BroadcastReceiver

一旦实现了BroadcastReceiver,接下就应该指定该BroadcastReceiver能匹配的Intent即注册BroadcastReceiver。注册BroadcastReceiver的方式有两种:

①静态注册:这种方法是在配置AndroidManifest.xml配置文件中注册,通过这种方式注册的广播为常驻型广播,也就是说如果应用程序关闭了,有相应事件触发,程序还是会被系统自动调用运行。例如:

<!--在配置文件中注册BroadcastReceiver能够匹配的Intent--><receiverandroid:name=".MyBroadcastReceiver"><intent-filter><categoryandroid:name="android.intent.category.DEFAULT"/></intent-filter></receiver>

动态注册:这种方法是通过代码在.Java文件中进行注册。通过这种方式注册的广播为非常驻型广播,即它会跟随Activity的生命周期,所以在Activity结束前我们需要调用unregisterReceiver(receiver)方法移除它。例如:

//通过代码的方式动态注册MyBroadcastReceiverMyBroadcastReceiverreceiver=newMyBroadcastReceiver();IntentFilterfilter=newIntentFilter();filter.addAction("android.intent.action.MyBroadcastReceiver");//注册receiverregisterReceiver(receiver,filter);

注意:如果我们在Activity中注册了BroadcastReceiver,当这个Activity销毁的时候要主动撤销注册否则会出现异常。方法如下:

@OverrideprotectedvoidonDestroy(){super.onDestroy();//当Activity销毁的时候取消注册BroadcastReceiverunregisterReceiver(receiver);}

4、BroadcastReceiver的生命周期:

BroadcastReceiver的生命周期,从对象调用它开始,到onReceiver方法执行完成之后结束。另外,每次广播被接收后会重新创建BroadcastReceiver对象,并在onReceiver方法中执行完就销毁,如果BroadcastReceiver的onReceiver方法中不能在10秒内执行完成,Android会出现ANR异常。所以不要在BroadcastReceiver的onReceiver方法中执行耗时的操作。

如果需要在BroadcastReceiver中执行耗时的操作,可以通过Intent启动Service来完成。但不能绑定Service。

特别是,您可能无法从一个BroadcastReceiver中显示一个对话框,或绑定到服务。对于前者,则应该使用NotificationManager的API。对于后者,你可以使用Context.startService()来启动一个Service。

5、广播的类型:

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)接收高优先级的接收者存入的数据。

6、应用实例:

1)静态注册 发送广播:

publicclassMainActivityextendsActivityimplementsOnClickListener{privateButtonbtnSend,btnSend2;@OverrideprotectedvoidonCreate(BundlesavedInstanceState){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);}@OverridepublicvoidonClick(Viewv){switch(v.getId()){caseR.id.btnSend://无法通过abortBroadcast()的方式停止广播的传播,//也无法往Broadcast中存入数据因为它是异步的//如果往Broadcast中存入数据会抛异常Intentintent=newIntent();intent.setAction("android.intent.action.MyBroadcastReceiver");intent.putExtra("msg","这是一个普通的广播");sendBroadcast(intent);break;caseR.id.btnSend2://1.可以通过abortBroadcast可终止广播的传播//2.按优先级的不同,优先接收到Broadcast的Receiver可通过//setResultExtras(Bundle)方法将处理结果存入Broadcast中,//下一个Receiver通过Bundlebundle=getResultExtras(true)方法//获取上一个Receiver传来的数据.Intentintent2=newIntent();intent2.setAction("android.intent.action.OrderedBroadcastReceiver");intent2.putExtra("msg","这是一个有序的广播");sendOrderedBroadcast(intent2,null);break;default:break;}}}

MyBroadcastReceiver.java:接收广播

publicclassMyBroadcastReceiverextendsBroadcastReceiver{@OverridepublicvoidonReceive(Contextcontext,Intentintent){Stringmsg=intent.getExtras().get("msg").toString();System.out.println("MyBroadcastReceiver收到Action名为:"+intent.getAction().toString()+"\n消息的内容是:"+msg);}}

FirstBroadcastReceiver.java接收广播

publicclassFirstBroadcastReceiverextendsBroadcastReceiver{@OverridepublicvoidonReceive(Contextcontext,Intentintent){Stringmsg=intent.getExtras().get("msg").toString();setResultData("你好我是第一个广播!");System.out.println("FirstBroadcastReceiver收到Action名为:"+intent.getAction().toString()+"\n消息的内容是:"+msg);//停止广播//abortBroadcast();}}

SecondBroadcastReceiver.java接收广播

publicclassSecondBroadcastReceiverextendsBroadcastReceiver{@OverridepublicvoidonReceive(Contextcontext,Intentintent){Stringmsg=intent.getExtras().get("msg").toString();Stringresult=getResultData();System.out.println("SecondBroadcastReceiver收到Action名为:"+intent.getAction().toString()+"\n消息的内容是:"+msg+"\n上一个接受者传来的reult:"+result);}}

配置文件AndroidManifest.xml:

<!--在配置文件中注册MyBroadcastReceiver能够匹配的Intent--><receiverandroid:name=".MyBroadcastReceiver"><intent-filter><actionandroid:name="android.intent.action.MyBroadcastReceiver"/><categoryandroid:name="android.intent.category.DEFAULT"/></intent-filter></receiver><!--在配置文件中注册SecondBroadcastReceiver能够匹配的Intent--><!--优先级的设定FirstBroadcastReceiver大于SecondBroadcastReceiver,优先级的范围-1000~1000--><receiverandroid:name=".FirstBroadcastReceiver"><intent-filterandroid:priority="200"><actionandroid:name="android.intent.action.OrderedBroadcastReceiver"/><categoryandroid:name="android.intent.category.DEFAULT"/></intent-filter></receiver><receiverandroid:name=".SecondBroadcastReceiver"><intent-filterandroid:priority="100"><actionandroid:name="android.intent.action.OrderedBroadcastReceiver"/><categoryandroid:name="android.intent.category.DEFAULT"/></intent-filter></receiver>

界面:

日志打印:

点击普通广播

点击有序广播

2)动态注册 发送广播以短信接收为例:

publicclassMainActivityextendsActionBarActivity{privateMyBroadcastReceivermyBroadcastReceiver;@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);myBroadcastReceiver=newMyBroadcastReceiver();findViewById(R.id.btn1).setOnClickListener(newOnClickListener(){@OverridepublicvoidonClick(Viewv){IntentFilterfilter=newIntentFilter();filter.addAction("android.provider.Telephony.SMS_RECEIVED");registerReceiver(myBroadcastReceiver,filter);System.out.println("注册了广播");}});findViewById(R.id.btn2).setOnClickListener(newOnClickListener(){@OverridepublicvoidonClick(Viewv){unregisterReceiver(myBroadcastReceiver);System.out.println("销毁了广播");}});}}
publicclassMyBroadcastReceiverextendsBroadcastReceiver{@OverridepublicvoidonReceive(Contextcontext,Intentintent){System.out.println("MyBroadcastReceiver收到Action名为:"+intent.getAction().toString());}}

不需要在AndroidManifest.xml配置文件中注册,不过使用带短信,需要加上短信权限

<uses-permissionandroid:name="android.permission.RECEIVE_SMS"/

效果图:

先注册广播,然后在Emulator Control中发短信:


如果不知道这步在哪里,请看Android模拟器用命令和DDMS模拟来电和短信

日志打印:

7、系统定义的BroadcastIntent Action常量:

如:ACTION_TIME_TICK,系统时钟广播,系统每分钟都会发送一个这样的广播,如果在应用开发中,有些逻辑依赖于系统时钟,可以注册一个广播接收者。这是一个受保护的action,只有系统才能发送这个广播,并且,在manifest文件中注册的广播接收者不能接收到该广播,若要接收该广播,必须在代码中注册广播接收者

registerReceiver(newBroadcastReceiver(){@OverridepublicvoidonReceive(Contextcontext,Intentintent){Log.i("xxxx","TIME_TICK");}},newIntentFilter(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的类,接受系统启动关闭广播。代码如下:

publicclassLaunchReceiverextendsBroadcastReceiver{@OverridepublicvoidonReceive(Contextcontext,Intentintent){System.out.println("系统启动完毕");}}
publicclassShutdownReceiverextendsBroadcastReceiver{@OverridepublicvoidonReceive(Contextcontext,Intentintent){System.out.println("系统要关闭了");}}

<receiverandroid:name=".LaunchReceiver"><intent-filter><actionandroid:name="android.intent.action.BOOT_COMPLETED"/></intent-filter></receiver><receiverandroid:name=".ShutdownReceiver"><intent-filter><actionandroid:name="android.intent.action.ACTION_SHUTDOWN"/></intent-filter></receiver>

同时应添加所需要的权限:

<uses-permissionandroid:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

关机日志打印:

开机日志打印:

例子2:通过终止广播 阻止用户收到短信

系统收到短信,发出的广播属于有序广播。如果想阻止用户收到短信,可自定义Receiver,设置高优先级,率先获得接收短信的广播,并终止广播。接收短信的广播名android.provider.Telephony.SMS_RECEIVED。注意:程序一旦在某个模拟器运行,将一直阻止短信,只有注释掉abortBroadcast(),重新运行,方可正常。

publicclassMySmsResevicerextendsBroadcastReceiver{@OverridepublicvoidonReceive(Contextcontext,Intentintent){System.out.println("onreceive");abortBroadcast();}}
<receiverandroid:name=".MySmsResevicer"><intent-filterandroid:priority="1000"><actionandroid:name="android.provider.Telephony.SMS_RECEIVED"/></intent-filter></receiver>

8、BroadCastReceiver 的 API:

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

更多相关文章

  1. 详解Android中通过Intent类实现组件间调用的方法
  2. android 中 startActivityForResult 的使用方法
  3. Android系统编译so库提示error undefined reference to '__andro
  4. Android(java)学习笔记108:通过反射获取私有构造方法并且使用
  5. 在Android中启动执行java程序
  6. Android(安卓)Studio 太卡解决方法
  7. Android开发者指南(15) ―― Managing Virtual Devices
  8. Android(安卓)Studio 快捷键整理分享-SadieYu
  9. Android(安卓)APP安装后不在桌面显示图标的应用场景举例和实现方

随机推荐

  1. android 调用系统应用
  2. ch02 Android TextView与EditView
  3. android studio更新到1.5后遇到的问题
  4. android实现调用系统音乐播放器
  5. android 两点缩放字体
  6. 九宫格
  7. Android 2D绘图总结
  8. android WebView java与js相互调用
  9. EditText对行光标默认第一行问题
  10. Android 中的 R.class,减小 Apk 包大小