Android四大组件-BroadcastReceiver

注册方式

静态注册(Manifest-declared receivers)

在Manifest中进行申明,系统会在广播发出后启动您的应用(如果应用尚未运行)。

注意:如果您的应用以 API 级别 26 或更高级别的平台版本为目标,则不能使用清单为隐式广播(没有明确针对您的应用的广播)声明接收器,但一些不受此限制的隐式广播除外。在大多数情况下,您可以使用调度作业来代替。

<!-- If this receiver listens for broadcasts sent from the system or from
     other apps, even other apps that you own, set android:exported to "true". -->
<receiver android:name=".MyBroadcastReceiver" android:exported="false">
    <intent-filter>
        <action android:name="APP_SPECIFIC_BROADCAST" />
    </intent-filter>
</receiver>

动态注册(Context-registered receivers)

val br: BroadcastReceiver = MyBroadcastReceiver()
val filter = IntentFilter(APP_SPECIFIC_BROADCAST)
// 对应android:exported = false
val listenToBroadcastsFromOtherApps = false
val receiverFlags = if (listenToBroadcastsFromOtherApps) {
    ContextCompat.RECEIVER_EXPORTED
} else {
    ContextCompat.RECEIVER_NOT_EXPORTED
}
ContextCompat.registerReceiver(context, br, filter, receiverFlags)

生命周期

广播的生命周期分为根据注册方式分为两种

静态注册的生命周期非常简单且短暂,当系统发出广播后会调用onReceive,当onReceive执行完毕后就会回收实例。

动态注册的生命周期以registerReceiver开始,unregisterReceiver结束,并且会持有当前Context,因此一定注意要成对使用,特殊情况Application除外。

出于这点的理解,监听发送频繁的广播会生成和销毁大量的对象?

为了验证这个问题写了下面这个小Demo:

        <receiver
            android:name=".receiver.StaticReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="android.app.action.NEXT_ALARM_CLOCK_CHANGED" />
            </intent-filter>
        </receiver>
class StaticReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        log("onReceive: $this")
    }
}
I/common StaticReceiver: onReceive: com.whhhr.receiver.StaticReceiver@147451f
I/common StaticReceiver: onReceive: com.whhhr.receiver.StaticReceiver@762106c
I/common StaticReceiver: onReceive: com.whhhr.receiver.StaticReceiver@54a1635
I/common StaticReceiver: onReceive: com.whhhr.receiver.StaticReceiver@54dcaca
I/common StaticReceiver: onReceive: com.whhhr.receiver.StaticReceiver@825143b

可以看到和我们预料的一样,确实是每一次广播都会产生新的对象,因此应该避免使用静态注册的方式监听频繁调用的广播。

版本适配

由于静态广播的大量滥用,尤其是国产流氓APP,Android不得不一步步限制广播的使用。

Note: If your app targets API level 26 or higher, you cannot use the manifest to declare a receiver for implicit broadcasts (broadcasts that do not target your app specifically), except for a few implicit broadcasts that are exempted from that restriction. In most cases, you can use scheduled jobs instead.

Android 9

Beginning with Android 9 (API level 28), The NETWORK_STATE_CHANGED_ACTION broadcast doesn’t receive information about the user’s location or personally identifiable data.

In addition, if your app is installed on a device running Android 9 or higher, system broadcasts from Wi-Fi don’t contain SSIDs, BSSIDs, connection information, or scan results. To get this information, call getConnectionInfo() instead.

Android 8.0

Beginning with Android 8.0 (API level 26), the system imposes additional restrictions on manifest-declared receivers.

If your app targets Android 8.0 or higher, you cannot use the manifest to declare a receiver for most implicit broadcasts (broadcasts that don’t target your app specifically). You can still use a context-registered receiver when the user is actively using your app.

Android 7.0

Android 7.0 (API level 24) and higher don’t send the following system broadcasts:

Also, apps targeting Android 7.0 and higher must register the CONNECTIVITY_ACTION broadcast using registerReceiver(BroadcastReceiver, IntentFilter). Declaring a receiver in the manifest doesn’t work.

在我写这篇文章的时候市面上主流Android版本已经是Android 12了,因此简单理解就是,现在不支持所有静态广播的注册,除了这些例外

多次调用

对于动态注册,多次调用registerReceiver,如果存在系统即时广播(刚绑定就会默认收到一条的情况)会响应多次onReceive,但是不会创建多个Receiver对象,后续也只会响应一次onReceive

一些小记

针对系统广播,我本来以为所有广播常量都是像android.intent.action.BOOT_COMPLETED这样集中记录在Intent类中,但是以ACTION_NEXT_ALARM_CLOCK_CHANGED为例发现在Intent中没有记录,查了官网文档发现在AlarmManager中,不知道为什么要怎么设计,总之一切还是要以官方为准。

public static final String ACTION_NEXT_ALARM_CLOCK_CHANGED =  
 "android.app.action.NEXT_ALARM_CLOCK_CHANGED";

广播清单

每个版本的广播都可以在sdk中如下目录找到:

{sdkDir/platforms/android-xx/data/broadcast_actions.txt}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值