一、发送自定义广播的两种方式
1. 标准广播(Normal Broadcast)
- 特点:异步发送,所有注册的接收器同时接收,无法拦截。
- 适用场景:通知多个组件事件发生(如数据更新完成)。
示例代码:
kotlin
// 创建 Intent,指定广播的 Action
val intent = Intent("com.example.MY_CUSTOM_ACTION").apply {
// 附加数据(可选)
putExtra("message", "Hello from broadcast!")
putExtra("timestamp", System.currentTimeMillis())
}
// 发送标准广播
sendBroadcast(intent)
2. 有序广播(Ordered Broadcast)
- 特点:同步发送,接收器按优先级顺序处理,可终止传播或修改数据。
- 适用场景:需要链式处理广播(如权限验证链)。
示例代码:
kotlin
val intent = Intent("com.example.ORDERED_ACTION").apply {
putExtra("data", "Initial data")
}
// 发送有序广播
sendOrderedBroadcast(
intent,
null, // 权限(可选)
object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
// 最终接收器处理结果(可选)
val resultData = resultData
Toast.makeText(context, "Final result: $resultData", Toast.LENGTH_SHORT).show()
}
},
null, // Handler(默认主线程)
0, // 初始代码
null, // 初始数据
null // 初始 Bundle
)
二、广播的显式与隐式发送
1. 隐式广播(Implicit Broadcast)
- 定义:通过
Action
字符串匹配接收器,不指定目标组件。 - 限制:Android 8.0 (API 26) 及以上,静态注册的接收器无法接收隐式广播(系统广播除外)。
- 解决方案:
- 使用动态注册的接收器。
- 发送显式广播(指定包名或组件)。
2. 显式广播(Explicit Broadcast)
- 定义:直接指定目标组件(类名或包名)。
- 适用场景:定向发送给特定应用或组件。
示例代码:
kotlin
// 指定目标应用的包名
val intent = Intent("com.example.MY_CUSTOM_ACTION").apply {
setPackage("com.example.targetapp") // 显式指定包名
putExtra("secure_data", "123456")
}
// 发送广播(仅 com.example.targetapp 可接收)
sendBroadcast(intent)
三、携带复杂数据
1. 通过 Intent 附加数据
- 支持类型:基本类型、String、Parcelable、Serializable 等。
- 代码示例:kotlin
data class User(val name: String, val age: Int) : Parcelable { // Parcelable 实现(略) } val user = User("Alice", 30) val intent = Intent("com.example.USER_ACTION").apply { putExtra("user", user) putExtra("is_admin", true) } sendBroadcast(intent)
2. 通过 Bundle 附加数据
kotlin
val bundle = Bundle().apply {
putString("key1", "value1")
putInt("key2", 100)
}
val intent = Intent("com.example.BUNDLE_ACTION").apply {
putExtras(bundle)
}
sendBroadcast(intent)
四、权限控制
1. 发送带权限的广播
- 步骤:
- 在发送方声明权限:xml
<!-- AndroidManifest.xml --> <permission android:name="com.example.BROADCAST_PERMISSION" android:protectionLevel="signature" />
- 发送时附加权限:kotlin
val intent = Intent("com.example.PROTECTED_ACTION") sendBroadcast(intent, "com.example.BROADCAST_PERMISSION")
- 在发送方声明权限:
2. 接收方声明权限
xml
<!-- 接收方的 AndroidManifest.xml -->
<uses-permission android:name="com.example.BROADCAST_PERMISSION" />
五、本地广播(已弃用,替代方案)
1. 旧方式(仅作参考)
kotlin
// 发送本地广播(使用 LocalBroadcastManager)
LocalBroadcastManager.getInstance(context).sendBroadcast(intent)
2. 推荐替代方案
- 使用
LiveData
或Flow
:kotlin// 定义单例事件总线 object EventBus { private val _events = MutableSharedFlow<String>() val events = _events.asSharedFlow() suspend fun sendEvent(event: String) { _events.emit(event) } } // 发送事件 lifecycleScope.launch { EventBus.sendEvent("Custom Event") } // 接收事件 lifecycleScope.launch { EventBus.events.collect { event -> Toast.makeText(context, "收到事件: $event", Toast.LENGTH_SHORT).show() } }
六、完整示例:发送与接收自定义广播
1. 发送方代码
kotlin
// 发送标准广播
fun sendCustomBroadcast() {
val intent = Intent("com.example.MY_ACTION").apply {
putExtra("data", "Hello from sender!")
}
sendBroadcast(intent)
}
// 发送有序广播并传递结果
fun sendOrderedBroadcastWithResult() {
val intent = Intent("com.example.ORDERED_ACTION")
sendOrderedBroadcast(
intent,
null,
object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val result = "Result: ${getResultData()}"
Toast.makeText(context, result, Toast.LENGTH_SHORT).show()
}
},
null,
0,
"Initial Data",
null
)
}
2. 接收方代码
kotlin
// 动态注册接收器
class MainActivity : AppCompatActivity() {
private val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
when (intent?.action) {
"com.example.MY_ACTION" -> {
val data = intent.getStringExtra("data")
Toast.makeText(context, "收到广播: $data", Toast.LENGTH_SHORT).show()
}
"com.example.ORDERED_ACTION" -> {
// 修改有序广播结果
resultData = "Modified Data"
abortBroadcast() // 终止广播(可选)
}
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 注册接收器
val filter = IntentFilter().apply {
addAction("com.example.MY_ACTION")
addAction("com.example.ORDERED_ACTION")
priority = 100 // 设置优先级(有序广播有效)
}
registerReceiver(receiver, filter)
}
override fun onDestroy() {
super.onDestroy()
unregisterReceiver(receiver)
}
}
七、注意事项
Android 8.0+ 限制:
- 静态注册的接收器无法接收隐式广播,需改用动态注册或显式广播。
- 使用
setPackage()
指定目标包名绕过限制:kotlinintent.setPackage("com.example.targetapp")
性能优化:
- 避免在广播中传递大数据(如图片),改用文件路径或标识符。
- 使用
LocalBroadcastManager
的替代方案(如LiveData
)减少跨进程开销。
安全性:
- 敏感数据通过权限或应用签名保护。
- 使用
Intent.setPackage()
或组件类名限制接收范围。
生命周期管理:
- 动态注册的接收器需在组件销毁时取消注册。
- 静态注册的接收器在
onReceive()
中避免耗时操作(主线程限制)。
通过合理设计广播逻辑,可以实现灵活且高效的组件通信,同时确保应用的安全性和兼容性。