You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

动态注册BroadcastReceiver时onReceive不触发问题排查

问题描述

我需要获取用户在Google ShareSheet中选择的分享渠道用于分析统计,通过PendingIntent来接收用户的选择值,实现代码如下:

override fun doOpenShareSheet(
        activity: AppCompatActivity
    ) {
        var flag: Int = PendingIntent.FLAG_UPDATE_CURRENT

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            flag = PendingIntent.FLAG_IMMUTABLE
        }

        val pi: PendingIntent = PendingIntent.getBroadcast(
            activity,
            0,
            Intent(activity, ChooserBroadcastReceiver::class.java),
            flag
        )

        // Implement Google ShareSheet
        val share: Intent = Intent.createChooser(
            Intent().apply {
                action = Intent.ACTION_SEND
                putExtra(Intent.EXTRA_TEXT, config.url)

                // Passing content URI to image to be displayed
                flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
                type = "application/url"
            },
            config.mediaTitle,
            pi.intentSender
        )

        activity.startActivity(share)
    }

因为没法在清单文件给BroadcastReceiver的构造函数传参,所以我选择动态注册BroadcastReceiver,代码如下:

class ChooserBroadcastReceiver(private val vm: MyViewModel): BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        val selectedComponent: String = intent?.extras?.get(Intent.EXTRA_CHOSEN_COMPONENT).toString()
        vm.doOnChooserBroadcastReceiver(selectedComponent = selectedComponent)
    }
}
@AndroidEntryPoint
class MyFragment : Fragment() {
...
    override fun onResume() {
        super.onResume()
        registerBroadcast()
    }

    private fun registerBroadcast() {
        chooserBroadcastReceiver = ChooserBroadcastReceiver(vm = vm)
        val intentFilter = IntentFilter()
        intentFilter.addAction(Intent.ACTION_SEND)

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            requireActivity().registerReceiver(chooserBroadcastReceiver, intentFilter, RECEIVER_EXPORTED)
        } else {
            requireActivity().registerReceiver(chooserBroadcastReceiver, intentFilter)
        }
    }
...
}

现在的问题是:能正常打开Google ShareSheet并选择分享渠道,但onReceive方法接收不到事件。测试发现如果移除ViewModel参数,改用清单注册BroadcastReceiver,功能就能正常运行,但这种方式满足不了我传递构造参数的需求。

请问哪里操作有误?为什么清单注册可行但动态注册时onReceive无法触发?


问题原因

核心问题是动态注册的IntentFilter和PendingIntent发送的广播完全不匹配:

  1. 你创建PendingIntent时用的是指向ChooserBroadcastReceiver的显式Intent,但没有指定自定义Action;
  2. 动态注册时,你给IntentFilter加的是Intent.ACTION_SEND的过滤条件,而ShareSheet触发PendingIntent发送的广播根本不是这个Action,所以系统找不到你动态注册的接收器,自然不会回调onReceive。

而清单注册可行的原因是:清单注册的广播接收器如果没有在<receiver>标签里加<intent-filter>,系统会直接通过Intent里指定的组件名找到接收器,不需要匹配Action;但动态注册必须严格匹配IntentFilter的条件才能触发。


解决方案

按以下步骤修改代码即可解决:

1. 定义唯一的自定义广播Action

先定义一个全局唯一的Action常量(比如放在你的Constants类里):

const val ACTION_CHOOSER_SELECTED = "com.your.package.name.ACTION_CHOOSER_SELECTED"

(注意替换成你自己的包名)

2. 修改PendingIntent的Intent

创建PendingIntent时,给Intent设置自定义的Action:

val pi: PendingIntent = PendingIntent.getBroadcast(
    activity,
    0,
    Intent(ACTION_CHOOSER_SELECTED)
        .setClass(activity, ChooserBroadcastReceiver::class.java), // 保持显式指定组件
    flag
)

3. 修正动态注册的IntentFilter

注册广播时,监听我们自定义的Action,而不是Intent.ACTION_SEND:

private fun registerBroadcast() {
    chooserBroadcastReceiver = ChooserBroadcastReceiver(vm = vm)
    val intentFilter = IntentFilter(ACTION_CHOOSER_SELECTED) // 这里改成自定义Action

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
        requireActivity().registerReceiver(chooserBroadcastReceiver, intentFilter, RECEIVER_EXPORTED)
    } else {
        requireActivity().registerReceiver(chooserBroadcastReceiver, intentFilter)
    }
}

4. 别忘了注销广播(关键)

动态注册的广播必须在Fragment销毁/暂停时手动注销,避免内存泄漏:

override fun onPause() {
    super.onPause()
    try {
        requireActivity().unregisterReceiver(chooserBroadcastReceiver)
    } catch (e: IllegalArgumentException) {
        // 防止重复注销抛出异常
    }
}

内容的提问来源于stack exchange,提问作者Sirop4ik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 12:45:17