以下广播简称Broadcast
成都创新互联云计算的互联网服务提供商,拥有超过13年的服务器租用、双线服务器托管、云服务器、网站空间、网站系统开发经验,已先后获得国家工业和信息化部颁发的互联网数据中心业务许可证。专业提供云主机、网站空间、域名申请、VPS主机、云服务器、香港云服务器、免备案服务器等。
是Android四大组件之一,在四大组件的另外两个组件 和 拥有发送和接收广播的能力。Android 是在 进程间通信机制的基础上实现的,内部基于消息发布和订阅的事件驱动模型,广播发送者负责发送消息,广播接收者需要先订阅消息,然后才能收到消息。 进程间通信与 的区别在于:
有三种类型
存在一个注册中心,也可以说是一个调度中心,即 。广播接收者将自己注册到 中,并指定要接收的广播类型;广播发送者发送广播时,发送的广播首先会发送到 , 根据广播的类型找到对应的 ,找到后边将广播发送给其处理。
这里以普通广播为例子, 接收者有两种注册方式,一种是 ,一种是 :
(广播的发送分为 两种,这里针对有序的广播) 中的android:priority=""和 中的IntentFilter.setPriority(int)可以用来设置广播接收者的优先级,默认都是0 , 范围是[-1000, 1000],值越大优先级越高,优先级越高越早收到。
在相同优先级接收同个类型广播时, 的广播接收器比 的广播接收者更快的接收到对应的广播,这个之后会进行分析。
注:以下源码基于rk3399_industry Android7.1.2
的流程可分为 , 和 三个部分,这里依次分析下
在Android系统的 机制中,前面提到, 作为一个注册和调度中心负责注册和转发 。所以 的注册过程就是把它注册到 的过程。
这里我们分析 广播的过程, 和 有一个共同的父类 ,所以它们对应的注册过程其实是调用 ,接下来我们按照流程逐步分析调用流程的源码。
frameworks/base/core/java/android/content/ContextWrapper.java
在之前的 Android应用程序启动入口ActivityThread.main流程分析 分析过,在我们启动 Activity 时会创建一个 对象,然后通过 传给我们启动的 ,其内部就会将该对象赋值给 ; 的 方法也是类似的赋值流程,这里放个简易的源码应该更好理解
可以看到最后都会将生成的 对象赋值给对应的
对象。接下来继续分析 , 即 函数。
/frameworks/base/core/java/android/app/ContextImpl.java
这里我们首先看下如何将广播接收者 封装成一个 接口的 本地对象
/frameworks/base/core/java/android/app/LoadedApk.java
每一个注册过广播接收者的 或 组件在font color='Crimson' LoadedApk /font类中都有个对应的 对象,该对象负责将 与 组件关联起来。这些对象,以关联的 作为关键字保存在一个 中。之后对应的 又以 的 作为关键字保存在 的成员变量 对象中。最后通过 对应的 方法获得其 接口的 本地对象。之后再回到 注册方法内,将 对象发给 进行注册。
/frameworks/base/core/java/android/app/ActivityManagerNative.java
/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
在的 或 注册一个 时,并不是将其注册到font color='OrangeRed'AMS/font中,而是将与它关联的font color='OrangeRed'InnerReceiver/font对象注册到font color='OrangeRed'AMS/font中,当font color='OrangeRed'AMS/font接收到广播时,会根据 在内部找到对应的font color='OrangeRed'InnerReceiver/font对象,然后在通过这个对象将这个广播发送给对应的 处理。
注册过程这边画了一个简单的流程图:
font color='OrangeRed'Broadcast/font的发送过程可简单描述为以下几个过程:
frameworks/base/core/java/android/content/ContextWrapper.java
/frameworks/base/core/java/android/app/ContextImpl.java
/frameworks/base/core/java/android/app/ActivityManagerNative.java
/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
android的广播概念和我们日常生活中的电台有相通之处,空气中有不同频段,不同电台的广播,而android系统中就有对应的电池的电量,来电,短信还有例如sd卡拔插等等这些广播的消息发出,这些消息就对应着用收音机调频时,不同电台的节目。而我们注册的广播就类似于我收听某个电台的节目,比如一个注册广播收听交通广播,另一个注册的广播收听音乐广播,那么怎么区分是交通广播还是音乐广播呢,这就要通过前一章提到的Intent的action来判断。
(a).动态注册 在UI中注册的广播,例如:
(b).静态注册
需要在manifest中进行注册(在安卓8.0后系统废除了大部分静态广播,最好使用动态注册)。
(a).系统广播
系统中已经定义的广播,此类广播只能由系统发出,并且需要在intent-filter中加上系统已经写的action。
(b).自定义广播
顾名思义,是用户自己定义的广播。
(a)我们首先需要一个广播接收类
(b)其次注册动态广播
(c)最后需要通过send方法发送一个广播供广播接收者接受
另外还有有序广播和无序广播,这篇博客写的比较详细,供大家参考: Android的有序广播和无序广播(解决安卓8.0版本之后有序广播的接收问题) - ming3 - 博客园 (cnblogs.com)
为了解决广播的安全性问题,Android引入了本地广播机制,使用该机制发出的广播只能在应用程序的内部进行传递,并且广播接收器也只能接收来自本应用程序发出的广播。
本地广播是无法通过静态注册的方式来接收的。我们知道静态注册主要是为了在程序未启动的情况下能接收广播,而当我们发送本地广播的时候,程序肯定是已经启动的了,所以我们需要动态注册方式创建接收器。
在这里我们创建一个继承于BroadcastReceiver的类LocalReceiver。onReceive()处理你接收到的广播内容,在这里我用Toast来创建一个提示接收到消息的弹窗
在activity_main.xml文件创建一个用于发送广播的按钮
首先通过本地广播管理器LocalBroadcastManager的getInstance()方法获取一个实例,并分别创建过滤器IntentFilter和自定义接收器LocalReceiver的实例。给IntentFilter的实例添加一个action:localbroadcast(接收的广播的名称),然后调用LocalBroadcastManager的registerReceiver()方法进行注册,并将LocalReceiver的实例和IntentFilter的实例都传进去。这样本地监听器就创建完成了。
调用LocalBroadcastManager的sendBroadcast()发送本地广播。运行程序,点击Send Button按钮,我们可以看到弹窗显示“This is in LocalReceiver”,说明本地广播发送和接收成功了。
当然,我们最后一定不要忘了取消注册。我们可以通过调用unregisterReceiver()方法来实现。至此,Android的标准广播发送就完成了。
1.发送的广播只能在本程序内传递,不必担心数据泄露
2.其它程序广播无法发送到本程序的内部,不必担心安全漏洞隐患
3.本地广播比系统全局广播更加高效
android的粘性广播,是指广播接收器一注册马上就能接收到广播的一种机制,当然首先系统要存在广播。而普通广播就是要先注册广播接收器,然后广播被发送到系统,广播接收器才能接收到广播。
所以他们的区别是:
粘性广播调用registerReceiver能马上接受广播,而普通广播不行。
对于粘性广播:
1.系统首先存在粘性广播
2.注册广播接收器
3.处理广播
下面用一个例子展示下他们的区别
主Acitivity
布局
布局有两个按钮,一个是注册粘性广播,一个是注册普通广播。点击注册粘性广播按钮会马上返回结果。而点击注册普通广播按钮则没有反应
两种方式:静态注册和动态注册
动态注册:
1)动态注册:需要定义一个继承自BroadcastReceiver类的子类,该接收器需要在Activity中的onDestroy中注销
2)静态注册:通过在AndroidManifest.xml中配置
两种广播形式:有序广播和无序广播
1)无序广播:接受标准广播的接收器将同时收到广播消息,异步执行,没有先后顺序 sendBroadCast
2)有序广播:sendOrderedBroadCast,按照一定顺序先后被接受顺序,由priority属性决定,abortBroadCast中断广播
如果只想在本应用中发送和接受广播,使用LocalBroadcastReceiver来对广播进行管理
本地广播不支持静态注册
优点 :安全高效
Service是Android中的一种组件,和Activity的级别一致,但不能自己运行,只能后台运行,和其他组件交互,服务必须注册才能使用
本地服务:服务依附在主线程中,节约资源,主线程死掉服务终止
远程服务:服务在独立进程中,灵活性好 ,占用资源高
两种服务的启动模式:
1)start方式:调用者和服务之间没有关联,调用者退出不会影响服务,startService启动服务,如果服务不存在,调用onCreat方法,然后onStartCommand被调用。stopService关闭服务,onDestroy方法被调用
2)bind方式:调用者和服务绑定,调用者退出,服务终止bindService启动服务,onCreate方法创建服务,onBind方法绑定服务,onUnbind方法解绑,onDestory在服务结束时调用