本文最后更新于:1 个月前

系统会在发生各种系统事件时自动发送广播,例如当系统进入和退出飞行模式时。系统广播会被发送给所有同意接收相关事件的应用。广播消息本身会被封装在一个 Intent 对象中,该对象的操作字符串会标识所发生的事件(例如 android.intent.action.AIRPLANE_MODE)。该 Intent 可能还包含绑定到其 extra 字段中的附加信息。例如,飞行模式 intent 包含布尔值 extra 来指示是否已开启飞行模式。

接收广播

应用可以通过两种方式接收广播:清单声明的接收器和上下文注册的接收器。

清单声明的接收器

如果应用以 API 级别 26 或更高级别的平台版本为目标,则不能使用清单为隐式广播声明接收器。大多数情况下,可以使用调度作业来代替。

  1. 在应用清单中指定 <receiver> 元素。

    <receiver android:name=".MyBroadcastReceiver"  android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED"/>
            <action android:name="android.intent.action.INPUT_METHOD_CHANGED" />
        </intent-filter>
    </receiver>

    Intent 过滤器指定接收器所订阅的广播操作。

  2. 创建 BroadcastReceiver 子类并实现 onReceive(Context, Intent)

    private const val TAG = "MyBroadcastReceiver"
    
    class MyBroadcastReceiver : BroadcastReceiver() {
    
        override fun onReceive(context: Context, intent: Intent) {
            StringBuilder().apply {
                append("Action: ${intent.action}\n")
                append("URI: ${intent.toUri(Intent.URI_INTENT_SCHEME)}\n")
                toString().also { log ->
                    Log.d(TAG, log)
                    Toast.makeText(context, log, Toast.LENGTH_LONG).show()
                }
            }
        }
    }

如果应用当前未运行,系统可以启动应用并发送广播。

系统会创建新的 BroadcastReceiver 组件对象来处理它接收到的每个广播。此对象仅在 onReceive(Context, Intent) 期间有效。一旦从此方法返回代码,系统便会认为该组件不再活跃

上下文注册的接收器

  1. 创建 BroadcastReceiver 的实例。
  2. 创建 IntentFilter 并调用 registerReceiver(BroadcastReceiver, IntentFilter) 来注册接收器。
  3. 要停止广播,可以调用 unregisterReceiver(android.content.BroadcastReceiver)

注意注册和注销接收器的位置。如果使用 Activity Context 在 onCreate() 中注册接收器,则需要在 onDestory() 中注销,以防止接收器从 Activity Context 中泄露出去。如果在 onResume() 中注册接收器,应在 onPause() 中注销,以防止多次注册接收器(此举可以减少不必要的系统开销,在暂停时停止接收广播)。

对进程状态的影响

BroadcastReceiver 的状态会影响其所在进程的状态,因此不应从广播接收器启动长时间运行的后太线程。onReceive() 完成后,系统可以随时终止进程来回收内存,在此过程中,也会终止进程中运行的派生线程。要避免这种情况,可以调用 goAsync() 或使用 JobScheduler 从接收器调度 JobService

发送广播

  • sendOrderedBroadcast(Intent, String)
    一次向一个接收器发送广播。当接收器逐个顺序执行时,接收器可以向下传递效果,也可以中止广播。
  • sendBroadcast(Intent)
    常规广播,会按随机的顺序向所有接收器发送广播。
  • LocalBroadcastManager.sendBroadcast
    将广播发送给与发送器位于统一应用中的接收器。

通过权限限制广播

带权限的发送

调用方法发送广播时,可以指定权限参数。接收器若要接受此广播,需要通过清单中的标记请求该权限。

带权限的接收

如果在注册广播接收器时制定了权限参数,广播方需要在清单中请求该权限。

安全注意事项和最佳做法

  • 如果不需要向应用以外的组件发送广播,可以使用 LocalBroadcastManager.
  • 如果有许多应用在清单中注册接收相同的广播,可能会导致系统启动大量应用,为避免此种情况的发生,可以优先使用上下文注册方法。

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!

后台处理指南 上一篇
AIDL 下一篇