1. android中的广播是什么意思
android的广播概念和我们日常生活中的电台有相通之处,空气中有不同频段,不同电台的广播,而android系统中就有对应的电池的电量,来电,短信还有例如sd卡拔插等等这些广播的消息发出,这些消息就对应着用收音机调频时,不同电台的节目。而我们注册的广播就类似于我收听某个电台的节目,比如一个注册广播收听交通广播,另一个注册的广播收听音乐广播,那么怎么区分是交通广播还是音乐广播呢,这就要通过前一章提到的Intent的action来判断。
2. android 如何自定义常驻广播
Android广播机制指的是,在一个应用程序运行的时候可以自定义一个消息类型,让相应的接收器去处理这个消息或者是系统消息,比如来电话了、来短信了、手机没电了等等系统发送的消息。系统发送的消息也可以通过广播的方式通知给应用程序,这样子就避免了新开一个Thread去监听系统或其他应用发送过来的消息的状态。
Android广播的分类:
1、 普通广播:这种广播可以依次传递给各个处理器去处理
2、 有序广播:这种广播在处理器端的处理顺序是按照处理器的不同优先级来区分的,高优先级的处理器会优先截获这个消息,并且可以将这个消息删除
3、 粘性消息:粘性消息在发送后就一直存在于系统的消息容器里面,等待对应的处理器去处理,如果暂时没有处理器处理这个消息则一直在消息容器里面处于等待状态。
注意:普通广播和粘性消息不同被截获,而有序广播是可以被截获的
处理器的注册:
1、 在代码中用函数代码动态的方式注册。动态注册的处理器必须用代码动态的销毁,每次用来处理消息的就一个实例对象
2、 在配置文件里面静态注册,静态注册有个特点,那就是一旦注册就会一直存在于系统里面,无论应用是否关闭或开关机。(简直就是一个流氓软件病毒啊~)。静态注册每次有处理消息就由系统new一个处理器处理,并销毁
下面具体看看Android广播消息的发送、注册、处理过程:
① 自定义处理器类:
public class MyBroadcastReceiver4 extends BroadcastReceiver {
public MyBroadcastReceiver4() {
System.out.println("创建了一个由registerReceiver()注册的广播接收器");
}
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
System.out.println("MyBroadcastReceiver4收到了一个" + action + "消息");
if (isOrderedBroadcast()) {
System.out.println("这是一个有序广播,已经被拦截了。");
this.abortBroadcast();
} else {
System.out.println("这不是一个有序广播");
}
Bundle bundle = intent.getExtras();
if (bundle != null) {
System.out.println("该消息携带的数据如下:");
// 获得bundle的一个key的集合
Set set = bundle.keySet();
// 获得上述集合的迭代器
Iterator iterator = set.iterator();
// 用迭代器遍历集合
while (iterator.hasNext()) {
// 取得集合中的一个内容
String str = (String) iterator.next();
// 取得Bundle中的内容
System.out.println(str + "--->" + bundle.get(str));
}
} else {
System.out.println("该消息没有携带数据");
}
Toast toast = Toast.makeText(context, "MyBroadcastReceiver4收到了一个"
+ action + "消息", Toast.LENGTH_LONG);
toast.show();
//将这个消息截获(从消息容器移除)这样其他处理器就没法接收到这个消息
this.abortBroadcast();
}
}
② 发送广播消息
⑴、 发送普通广播:
// 发送一个普通消息
Intent intent = new Intent(); intent.setAction("asdfasdf");
Android_09_10Activity.this.sendBroadcast(intent);
⑵、 发送有序广播:
// 发送一个有序消息
Intent intent = new Intent();
intent.setAction("asdfasdf"); Android_09_10Activity.this.sendOrderedBroadcast(intent,
null);
⑶、 发送粘性广播:
// 发送一个粘性消息
Intent intent = new Intent();
intent.setAction("qwerqwer"); Android_09_10Activity.this.sendStickyBroadcast(intent);
③ 注册广播接收器
⑴动态注册:
// 注册一个广播接收器
IntentFilter intentFilter = new IntentFilter("asdfasdf");
intentFilter.setPriority(0);
Android_09_10Activity.this.registerReceiver(mbr2,
intentFilter);
⑵静态注册:
<receiver android:name=".MyBroadcastReceiver4" >
<intent-filter android:priority="1000" >
<action android:name="android.intent.action.WALLPAPER_CHANGED" />
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
<action android:name="android.intent.action.PHONE_STATE" />
<action android:name="android.intent.action.PACKAGE_REMOVED" />
//这一句比较特殊,是上面那个广播消息特有的
<data android:scheme="package" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
想发送粘性消息的时候必须在配置文件里面获取权限:
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
想用自定义处理器对系统广播进行处理的话也必须在注册文件里面申明获取权限,比如:
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
3. 22 AndroidBroadcast广播机制
广播(Broadcast)机制用于进程/线程间通信,广播分为广播发送和广播接收两个过程,其中广播接收者BroadcastReceiver便是Android四大组件之一。
BroadcastReceiver分为两类:
从广播发送方式可分为三类:
广播在系统中以BroadcastRecord对象来记录, 该对象有几个时间相关的成员变量.
广播注册,对于应用开发来说,往往是在Activity/Service中调用 registerReceiver() 方法,而Activity或Service都间接继承于Context抽象类,真正干活是交给ContextImpl类。另外调用getOuterContext()可获取最外层的调用者Activity或Service。
[ContextImpl.java]
其中broadcastPermission拥有广播的权限控制,scheler用于指定接收到广播时onRecive执行线程,当scheler=null则默认代表在主线程中执行,这也是最常见的用法
[ContextImpl.java]
ActivityManagerNative.getDefault()返回的是ActivityManagerProxy对象,简称AMP.
该方法中参数有mMainThread.getApplicationThread()返回的是ApplicationThread,这是Binder的Bn端,用于system_server进程与该进程的通信。
[-> LoadedApk.java]
不妨令 以BroadcastReceiver(广播接收者)为key,LoadedApk.ReceiverDispatcher(分发者)为value的ArrayMap 记为 A 。此处 mReceivers 是一个以 Context 为key,以 A 为value的ArrayMap。对于ReceiverDispatcher(广播分发者),当不存在时则创建一个。
此处mActivityThread便是前面传递过来的当前主线程的Handler.
ReceiverDispatcher(广播分发者)有一个内部类 InnerReceiver ,该类继承于 IIntentReceiver.Stub 。显然,这是一个Binder服务端,广播分发者通过rd.getIIntentReceiver()可获取该Binder服务端对象 InnerReceiver ,用于Binder IPC通信。
[-> ActivityManagerNative.java]
这里有两个Binder服务端对象 caller 和 receiver ,都代表执行注册广播动作所在的进程. AMP通过Binder驱动将这些信息发送给system_server进程中的AMS对象,接下来进入AMS.registerReceiver。
[-> ActivityManagerService.java]
其中 mRegisteredReceivers 记录着所有已注册的广播,以receiver IBinder为key, ReceiverList为value为HashMap。
在BroadcastQueue中有两个广播队列mParallelBroadcasts,mOrderedBroadcasts,数据类型都为ArrayList<broadcastrecord style="box-sizing: border-box;">:</broadcastrecord>
mLruProcesses数据类型为 ArrayList<ProcessRecord> ,而ProcessRecord对象有一个IApplicationThread字段,根据该字段查找出满足条件的ProcessRecord对象。
该方法用于匹配发起的Intent数据是否匹配成功,匹配项共有4项action, type, data, category,任何一项匹配不成功都会失败。
broadcastQueueForIntent(Intent intent)通过判断intent.getFlags()是否包含FLAG_RECEIVER_FOREGROUND 来决定是前台或后台广播,进而返回相应的广播队列mFgBroadcastQueue或者mBgBroadcastQueue。
注册广播:
另外,当注册的是Sticky广播:
广播注册完, 另一个操作便是在广播发送过程.
发送广播是在Activity或Service中调用 sendBroadcast() 方法,而Activity或Service都间接继承于Context抽象类,真正干活是交给ContextImpl类。
[ContextImpl.java]
[-> ActivityManagerNative.java]
[-> ActivityManagerService.java]
broadcastIntent()方法有两个布尔参数serialized和sticky来共同决定是普通广播,有序广播,还是Sticky广播,参数如下:
broadcastIntentLocked方法比较长,这里划分为8个部分来分别说明。
这个过程最重要的工作是:
BroadcastReceiver还有其他flag,位于Intent.java常量:
主要功能:
这个过主要处于系统相关的10类广播,这里不就展开讲解了.
这个过程主要是将sticky广播增加到list,并放入mStickyBroadcasts里面。
其他说明:
AMS.collectReceiverComponents :
广播队列中有一个成员变量 mParallelBroadcasts ,类型为ArrayList<broadcastrecord style="box-sizing: border-box;">,记录着所有的并行广播。</broadcastrecord>
动态注册的registeredReceivers,全部合并都receivers,再统一按串行方式处理。
广播队列中有一个成员变量 mOrderedBroadcasts ,类型为ArrayList<broadcastrecord style="box-sizing: border-box;">,记录着所有的有序广播。</broadcastrecord>
发送广播过程:
处理方式:
可见不管哪种广播方式,都是通过broadcastQueueForIntent()来根据intent的flag来判断前台队列或者后台队列,然后再调用对应广播队列的scheleBroadcastsLocked方法来处理广播;
在发送广播过程中会执行 scheleBroadcastsLocked 方法来处理相关的广播
[-> BroadcastQueue.java]
在BroadcastQueue对象创建时,mHandler=new BroadcastHandler(handler.getLooper());那么此处交由mHandler的handleMessage来处理:
由此可见BroadcastHandler采用的是”ActivityManager”线程的Looper
[-> BroadcastQueue.java]
此处mService为AMS,整个流程还是比较长的,全程持有AMS锁,所以广播效率低的情况下,直接会严重影响这个手机的性能与流畅度,这里应该考虑细化同步锁的粒度。
4. android怎么发送特定广播的
起一个线程,每发一个广播后就sleep一分钟,如此循环。(或者接受系统的timechanged这个广播,这个广播好像一分钟发一次)。
Android 在发送广播时的方法 sendBroadcast(Intent)。
①:Intent myIntent = new Intent();——【创建Intent对象】
②:myIntent.setAction(String)——【设置一般的要执行的动作。参数:动作一个动作的名称,如ACTION_VIEW。应用程序的具体行动,应与供应商的包名作为前缀。】
③:myIntent.putExtra(String,Object)——【广播中额外发送的数据,String为自定义key,Object表示多种数据类型】
④:sendBroadcast(myIntent);——【发送广播】
接收广播
Android在接收广播的方法是注册一个广播接收器 registerReceiver(MyReceiver,IntentFilter)。
①:首先创建MyReceiver类(类名自定义) 继承 BroadcastReceiver类。——【创建广播接收器】
②:在MyReceiver中重写public void onReceive(Context context, Intent intent)方法。这个方法在接收到广播后触发。——【重写处理方法】
③:在Activity或者Service启动时 onCreate()、onStartCommand()等方法中实例化 MyReceiver类——【启动时实例化广播接收器】
④:IntentFilter filter = new IntentFilter();——【创建IntentFilter对象 意图过滤器】
⑤:filter.addAction(String);——【在过滤器中加入过滤条件,说明接收什么广播】
⑥:registerReceiver(cmdReceiver, filter);——【注册广播,参数为(广播接收器,意图过滤器)】
5. 安卓广播接收器怎么判断是哪个应用发送的想要只接收自身应用广播,怎么实现
安卓广播接收器Intent,它有提供过滤器功能,也就是开发者定义过滤条件,只有是这个条件的广播才接收,这样就可以接收指定广播。这也是安卓广播的基础知识功能,具体自己查阅相关资料,很简单的。
6. Android系统广播(Broadcast)注册,发送,接收流程解析
以下广播简称Broadcast
是Android四大组件之一,在四大组件的另外两个组件 和 拥有发送和接收广播的能力。Android 是在 进程间通信机制的基础上实现的,内部基于消息发布和订阅的事件驱动模型,广播发送者负责发送消息,广播接收者需要先订阅消息,然后才能收到消息。 进程间通信与 的区别在于:
有三种类型
存在一个注册中心,也可以说是一个调度中心,即 。广播接收者将自己注册到 中,并指定要接收的广播类型;广播发送者发送广播时,发送的广播首先会发送到 , 根据广播的类型找到对应的 ,找到后边将广播发送给其处理。
这里以普通广播为例子, 接收者有两种注册方式,一种是 ,一种是 :
(广播的发送分为 两种,这里针对有序的广播) 中的android:priority=""和 中的IntentFilter.setPriority(int)可以用来设置广播接收者的优先级,默认都是0 , 范围是[-1000, 1000],值越大优先级越高,优先级越高越早收到。
在相同优先级接收同个类型广播时, 的广播接收器比 的广播接收者更快的接收到对应的广播,这个之后会进行分析。
注:以下源码基于rk3399_instry 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
7. 【Android】广播的原理及实现步骤
参考文档(图源): https://www.jianshu.com/p/ca3d87a4cdf3
8. android蓝牙BLE(三) —— 广播
在蓝牙开发中,有些情况是不需要连接的,只要外设广播自己的数据即可,例如苹果的 ibeacon 。自 Android 5.0 更新蓝牙API后,手机可以作为外设广播数据。
广播包有两种:
其中 广播包是每个外设都必须广播的,而响应包是可选的 。每个广播包的长度必须是 31个字节 ,如果不到 31个字节 ,则剩下的全用 0 填充 补全,这部分的数据是无效的
广播包中包含若干个广播数据单元,广播数据单元也称为 AD Structure 。
广播数据单元 = 长度值Length + AD type + AD Data。
长度值 Length 只占 一个字节 ,并且位于广播数据单元的 第一个字节 。
概念的东西有些抽象,先看看下面的广播报文:
0x代表这串字符串是十六进制的字符串。 两位十六进制数代表一个字节 。因为两个字符组成的十六进制字符串最大为 FF ,即255,而Java中byte类型的取值范围是-128到127,刚好可以表示一个255的大小。所以两个十六进制的字符串表示一个字节。
继续查看报文内容,开始读取第一个广播数据单元。读取 第一个 字节: 0x07 ,转换为十进制就是7,即表示后面的7个字节是这个广播数据单元的数据内容。超过这7个字节的数据内容后,表示是一个新的广播数据单元。
而第二个广播数据单元,第一个字节的值是 0x16 ,转换为十进制就是22,表示后面22个字节为第二个广播数据单元。
在广播数据单元的 数据部分 中, 第一个字节 代表 数据类型 (AD type),决定数据部分表示的是什么数据。(即广播数据单元第二个字节为AD type)
AD Type 的类型如下:
这bit 1~7分别代表着发送该广播的蓝牙芯片的物理连接状态。当bit的值为1时,表示支持该功能。
例:
蓝牙广播的数据格式大致讲了一下,有助于下面的广播操作的理解。
先看看广播设置( AdvertiseSettings )如何定义:
(1)、通过 AdvertiseSettings.Builder#setAdvertiseMode() 设置广播模式。其中有3种模式:
(2)、通过 AdvertiseSettings.Builder#setAdvertiseMode() 设置广播发射功率。共有4种功率模式:
(3)、通过 AdvertiseSettings.Builder#setTimeout() 设置持续广播的时间,单位为毫秒。最多180000毫秒。当值为0则无时间限制,持续广播,除非调用 BluetoothLeAdvertiser#stopAdvertising() 停止广播。
(4)、通过 AdvertiseSettings.Builder#setConnectable() 设置该广播是否可以连接的。
之前说过,外设必须广播广播包,扫描包是可选。但添加扫描包也意味着广播更多得数据,即可广播62个字节。
可见无论是广播包还是扫描包,其广播的内容都是用 AdvertiseData 类封装的。
(1)、 AdvertiseData.Builder#setIncludeDeviceName() 方法,可以设置广播包中是否包含蓝牙的名称。
(2)、 AdvertiseData.Builder#setIncludeTxPowerLevel() 方法,可以设置广播包中是否包含蓝牙的发射功率。
(3)、 AdvertiseData.Builder#addService UUID (Parcel UUID ) 方法,可以设置特定的 UUID 在广播包中。
(4)、 AdvertiseData.Builder#addServiceData(Parcel UUID ,byte[]) 方法,可以设置特定的 UUID 和其数据在广播包中。
(5)、 AdvertiseData.Builder#addManufacturerData(int,byte[]) 方法,可以设置特定厂商Id和其数据在广播包中。
从 AdvertiseData.Builder 的设置中可以看出,如果一个外设需要在不连接的情况下对外广播数据,其数据可以存储在 UUID 对应的数据中,也可以存储在厂商数据中。但由于厂商ID是需要由Bluetooth SIG进行分配的,厂商间一般都将数据设置在厂商数据。
另外可以通过 BluetoothAdapter#setName() 设置广播的名称
先看一个例子,我们分别在 广播包 和 扫描包 中设置 AdvertiseData.Builder 的 每一种广播报文参数 ,得到一下报文内容:
(1)、Type = 0x01 表示设备LE物理连接。
(2)、Type = 0x09 表示设备的全名
(3)、Type = 0x03 表示完整的16bit UUID 。其值为0xFFF7。
(4)、Type = 0xFF 表示厂商数据。前两个字节表示厂商ID,即厂商ID为0x11。后面的为厂商数据,具体由用户自行定义。
(5)、Type = 0x16 表示16 bit UUID 的数据,所以前两个字节为 UUID ,即 UUID 为0xF117,后续为 UUID 对应的数据,具体由用户自行定义。
最后继承 AdvertiseCallback 自定义广播回调。
初始化完毕上面的对象后,就可以进行广播:
广播主要是通过 BluetoothLeAdvertiser#startAdvertising() 方法实现,但在之前需要先获取 BluetoothLeAdvertiser 对象。
BluetoothLeAdvertiser 对象存在两个情况获取为Null:
所以在调用 BluetoothAdapter#getBluetoothLeAdvertiser() 前,需要先调用判断蓝牙已开启,并判断在 BluetoothAdapter 中获取的 BluetoothLeAdvertiser 是否为空(测试过某些华为手机 mBluetoothAdapter.() 为 false , 但是能发送ble广播)。
与广播成对出现就是 BluetoothLeAdvertiser.stopAdvertising() 停止广播了,传入开启广播时传递的广播回调对象,即可关闭广播:
虽然通过广播告知外边自身拥有这些Service,但手机自身并没有初始化Gattd的Service。导致外部的中心设备连接手机后,并不能找到对应的 GATT Service 和 获取对应的数据。
Service类型有两个级别:
创建 BluetoothGattService 时,传入两个参数: UUID 和Service类型:
我们都知道Gatt中, Service 的下一级是 Characteristic , Characteristic 是最小的通信单元,通过对 Characteristic 进行读写操作来进行通信。
特征属性表示该 BluetoothGattCharacteristic 拥有什么功能,即能对 BluetoothGattCharacteristic 进行什么操作。其中主要有3种:
权限属性用于配置该特征值所具有的功能。主要两种:
Characteristic 下还有 Descriptor ,初始化 BluetoothGattDescriptor 时传入: Descriptor UUID 和 权限属性
为 Service 添加 Characteristic ,为 Characteristic 添加 Descriptor :
通过蓝牙管理器 mBluetoothManager 获取 Gatt Server ,用来添加 Gatt Service 。添加完 Gatt Service 后,外部中心设备连接手机时,将能获取到对应的 GATT Service 和 获取对应的数据
定义 Gatt Server 回调。当中心设备连接该手机外设、修改特征值、读取特征值等情况时,会得到相应情况的回调。
最后开启广播后,用nRF连接后看到的特征值信息如下图所示:(加多了一个只能都的特征值)
android蓝牙BLE(一) —— 扫描
android蓝牙BLE(二) —— 通信
android蓝牙BLE(三) —— 广播
android蓝牙BLE(四) —— 实战
9. android中自定义广播需要哪个权限
接受者的清单文件:
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.permissionbroadcastreceiver">
<permission android:name="com.example.broadcast.permission"
android:protectionLevel="normal" />
<application android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".PermissionRecevicer"
android:permission="com.example.broadcast.permission">
<intent-filter>
<action android:name="com.example.permissionbroadcastreceiver.message" />
</intent-filter>
</receiver>
</application></manifest>
在清单文件中声明一个权限,然后在receiver中要求发送者具有此权限,这样广播接受者进程就算是准备完成了!!
广播发送者的清单文件:
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.permissionbroadcast">
<uses-permission android:name="com.example.broadcast.permission" />
<application android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application></manifest>
在清单文件请求刚才在接收者清单文件声明的权限即可,这里的运行结果就不展示了,只是log而已!!!
10. Android本地广播的使用
为了解决广播的安全性问题,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.本地广播比系统全局广播更加高效