作为android的四大组件之一,broadcastReceiver在某些地方有其独特的用法,下面我们就一起来学习一下broadcastReceiver的基本用法吧
1.概念
broadcastReceiver包括两个概念:广播发送者和广播接收者。这里的广播其实就是指的Intent,程序可以自己发送广播自己接收,也可以接收系统或其他应用的广播或是发送广播给其他应用程序。
2.注册
注册广播有两种形式,即静态注册和动态注册。
静态注册:通过在xml文件声明,格式如下:
<receiver android:name="com.example.sdbroadcast.SdCardBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.MEDIA_MOUNTED" />
</intent-filter>
</receiver>
动态注册:使用代码块来进行编写,基本代码如下:
NetworkStateReceiver mReceiver = new NetworkStateReceiver();
IntentFilter mFilter = new IntentFilter();
mFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(mReceiver, mFilter);
需要注意的是在使用动态注册的时候需要在所属的activity销毁的时候使用
unregisterReceiver(broadcastReceiver);
否则会抛出异常。
那么这两种注册方式在使用的时候有什么区别呢?
a. 手动控制。registerReceiver为动态注册,自己可以手动注册或是取消注册;<receiver>标签为静态注册,由系统开机时自动扫描注册,所以无法手动控制,开机一直运行中。
b. 资源消耗不同。registerReceiver可以手动控制,所以适当的注册和取消注册能节省系统资源,<receiver>标签系统开机后一直有效。
c. 有效期不同。通过registerReceiver注册的BroadcastReceiver在对其进行注册的Context对象"销毁"了或者调用了unregisterReceiver方法时也就失效了,而通过<receiver>标签注册的BroadcastReceiver只要应用程序没有被删除就一直有效。
d. 对registerReceiver函数的调用许可不同。通过registerReceiver注册的BroadcastReceiver在其onReceive函数中可以再次调用某个Context的registerReceiver函数,而通过<receiver>标签注册的BroadcastReceiver不允许再调用某个Context的registerReceiver函数 。
e. 使用情况不同。对于自己发送和接受的广播可以通过registerReceiver注册,对于系统常用广播的接收通常用<receiver>标签注册。
3.使用
Intent intent = new Intent();
intent.setAction("android.intent.action.MyBroadcastReceiver");
intent.putExtra("msg", "发送无序的广播,顺便传递的数据");
sendBroadcast(intent);
在这里顺便提一下,对于一些系统级的广播,我们只需要进行注册,接收即可,发送功能由系统进行发送。而对于我们自己自定义的广播需要我们自己进行发送。
总结为:
a. 新建BroadcastReceiver只需要继承BroadcastReceiver并重写OnReceiver函数,加上自己的处理逻辑。
b. 通过registerReceiver注册广播,通过unregisterReceiver取消注册广播,通过sendBroadcast发送广播。
其中注册和取消注册广播放在了OnResume和OnPause函数中可以有效的节省系统消耗。如果希望广播一直运行中可以在Activity的OnCreate函数中注册,在OnDestrory函数中取消注册。
4.生命周期
BroadcastReceiver的生命周期比较短,当调用的onReceive方法结束时,表示生命周期结束。所以不适合在onReceive中做绑定服务操作,即不合适调用bindService,但是可以调用startService。结束后若某个进程只含有该BroadcastReceiver,则优先级将降低可能被系统回收,所以BroadcastReceiver中不适合做一些异步操作,如新建线程下载数据,BroadcastReceiver结束后可能在异步操作完成前进程已经被系统kill。同时由于ANR限制(10s)导致在onReceive里面不适合做一些比较耗时的操作
5.安全性
因为broadcastReceive的设计初衷就是为了可以方便应用程序和系统、应用程序之间、应用程序内的通信,所以对单个应用程序而言BroadcastReceiver是存在安全性问题的,对此有以下几个解决方案:
a) 当应用程序发送某个广播时系统会将发送的Intent与系统中所有注册的BroadcastReceiver的IntentFilter进行匹配,若匹配成功则执行相应的onReceive函数。可以通过类似sendBroadcast(Intent, String)的接口在发送广播时指定接收者必须具备的permission。或通过Intent.setPackage设置广播仅对某个程序有效。
b)当应用程序注册了某个广播时,即便设置了IntentFilter还是会接收到来自其他应用程序的广播进行匹配判断。对于动态注册的广播可以通过类似registerReceiver(BroadcastReceiver, IntentFilter, String, android.os.Handler)的接口指定发送者必须具备的permission,对于静态注册的广播可以通过android:exported="false"属性表示接收者对外部应用程序不可用,即不接受来自外部的广播
c)上面两个问题其实都可以通过LocalBroadcastManager来解决,LocalBroadcastManager只会将广播限定在当前应用程序中,具体见下面6特殊的BroadcastReceiver中的介绍
6.分类(有序广播和无序广播)
无序广播:即sendBroadcast();对于普通广播接收者而言,接收广播是无序的,因此无法对广播的内容做处理,也无法终止广播的发送。
有序广播:即sendOrderBroadcast();与普通广播不同,接收广播是有序的,这也意味着对于接收到的广播可以进行处理然后再向下进行发送或者终止广播的发送。系统根据接收者定义的优先级顺序决定哪个接收者先接收到它,接收者处理完后可以将结果传递给优先级低的接收者也可以停止广播使得其他优先级低的接收者无法接收到该广播。优先级通过android:priority属性定义,数值越大优先级别越高,取值范围:-1000到1000,Android系统收到短信、接到电话后发送的广播都是有序广播,所以可以进行短信或电话的拦截,即取消广播。
在这里不得不提的概念:abortBroadcast,
有序广播可以在onReceive函数中通过BroadcastReceiver的abortBroadcast接口(这个接口对sendBroadcast发送广播无效)取消广播,通过接口sendOrderedBroadcast(Intent, String, BroadcastReceiver, android.os.Handler, int, String, Bundle)发送的广播即便优先级高的广播取消了广播,接口参数中指定的BroadcastReceiver依然可以在其他接收者处理完后接收到广播。通过BroadcastReceiver的getResultExtras接口获得结果的Bundle再通过Bundle的putString和getString方法修改或获取数据
最后小结:
1.广播接收者的生命周期是非常短暂的,在接收到广播的时候创建,onReceive()方法结束之后销毁
2.广播接收者中不要做一些耗时的工作,否则会弹出Application No Response错误对话框
3.最好也不要在广播接收者中创建子线程做耗时的工作,因为广播接收者被销毁后进程就成为了空进程,很容易被系统杀掉
4.耗时的较长的工作最好放在服务中完成
5.广播由于是一种全局监听,因此比较耗内存