Android广播最佳实践

时间:2023-01-30 14:59:24

此文翻译自GOOGLE中国官网关于广播的最佳实践。以下为翻译原文:
下面是关于广播发送和接收的安全及其他最佳实践案例:

  • 如果你不需要发送广播给其他app的组件,那么你应该通过LocalBroadcastManager去发送和接收广播。使用LocalBroadcastManager会更加地有效率并且可以不用考虑有其他app接收或发送你的广播的安全问题。本地广播可以作为一个事件总线工具在app内使用而无需任何系统范围的广播开销。

  • 如果很多app都已经在清单文件(AndroidManifest.xml)中注册了相同Action的广播接收者,这将会造成系统去启动这些app,对手机和用户体验造成严重的不良影响。为了避免这种情况出现,我们建议用动态注册广播接收者,不过某些情况下Android系统已经强制开发者使用动态注册广播接收者。比如CONNECTIVITY_ACTION广播已经强制在7.0以上系统使用动态注册,静态注册将不会响应。

  • 不要通过广播的隐式intent发送敏感信息。这些信息可能会被其他注册了这个接收者的app所接收。下面有三种方式去控制哪些广播接收者可以接收你的广播:

    • 在发送广播时定义permission属性
    • 在Android 4.0 及以上,你可以通过setPackage(String)方法定义package信息去发送一个广播。系统会发送该广播给有该package信息的广播接收者。
    • 你可以通过LocalBroadcastManager发送本地广播。
  • 当注册了一个广播接收者时,任意一个app都可能发送潜在的恶意广播给你的app中的广播接收者。这里有三种方式去限制你所注册的广播接收者去接收哪些信息:

    • 你可以给你的广播接收者定义permission属性
    • 静态广播接收者可以通过在清单文件中定义`android:exported属性为false限制其他app发送广播到本app的广播接收者。
    • 通过LocalBroadcastManager注册本地广播。
  • 广播定义的action变量可被全局接收,所以要为自己的广播定义一个特殊的action变量,避免和其他app的action变量产生冲突。

  • 因为广播接收者的onReceive(Context, Intent)方法在主线程中运行,所以该方法应该在段时间内执行并返回,避免造成ANR。如果你需要在该方法中执行长时间的工作,就要小心使用子线程或开启一个service去运行,因为系统可能会在onReceive方法返回之后回收掉该app的进程。更多的信息请查看Effect on process state 。对于耗时较长的工作,我们有如下建议:

    • 在onReceive方法中调用goAsync()方法并发送BroadcastReceiver.PendingResult给子线程。这能让你的广播接收者在onReceive方法中返回时保持其活跃。虽然系统希望你在10s内就结束掉这个广播,但是通过这方法能够让你的耗时工作在子线程中运行在避免造成ANR的同时避免该进程被系统回收。更多详细请看goAsync()方法的API
    • 通过JonScheduler去执行耗时工作。
  • 不要在广播接收者中启动activity,而是考虑使用notification。