
以下广播简称Broadcast
是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接收开机广播,需要用到播广播接收者BroadcastReceiver组件。
具体代码:
在配置文件AndroidManifest.xml中向系统注册receiver
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
需要添加相应权限
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
在Receiver中就可以添加开机需要进行的 *** 作
public class BootCompletedReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
}
}
要注册接受广播的处理程序, 有两种方式
在AndroidManifest.xml重注册, 比如监听系统的开机广播和屏幕解锁广播
<receiver android:name="com.bestjoy.app.common.update.BootCompletedReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.USER_PRESENT" />
</intent-filter>
</receiver>
这样, 一旦有定义的action发出来, BootCompletedReceiver的onReceive方法就会回调了,这样的监听,不需要你的app已经在运行。
2. 在程序中动态创建监听器, 比如还是解锁广播,
在Activity的onCreate()中生成一个IntentFilter对象
IntentFilter filter=new IntentFilter()
//为IntentFilter添加一个Action
filter.addAction("android.intent.action.USER_PRESENT")
bootCompletedReceiver = new UserPresentReceiver()
registerReceiver(smsReceiver, filter)
在onDestroy的时候去注册
unregisterReceiver(bootCompletedReceiver)
这样的方式只有在Activity生命周期onCreate()-onDestroy()之间有效。
对于一些特俗的系统级别的广播,即使你按照上面的任何一种方式做了, 也可能监听不到, 这是android 系统做了保护了, 网上查一下就知道了。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)