Android发广播的坑

示例代码如下:

kotlin 复制代码
class MainActivity : AppCompatActivity() {

    val receiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent?) {
            Log.i("MainActivity", "onReceive")
        }
    }
    val action = "cn.android666.logback.android.demo.action"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        findViewById<Button>(R.id.button).setOnClickListener {
            val intent = Intent(action).setPackage(packageName)
            sendBroadcast(intent)
        }

        ContextCompat.registerReceiver(this, receiver, IntentFilter(action), ContextCompat.RECEIVER_NOT_EXPORTED)
    }

    override fun onDestroy() {
        super.onDestroy()
        unregisterReceiver(receiver)
        Log.i("MainActivity", "onDestroy")
    }

}

在公司的一台 天龙 品牌的Android手机上,型号是N630 ,Android 11系统,运行如上代码,非常简单,就是注册广播,然后发送广播,使用了最新广播代码,RECEIVER_NOT_EXPORTED指示这个广播不会导出,也就是别的应用发广播我们是收不到的,在调用发广播时,我们调用了setPackage(packageName),则表明这个广播只会发给自己的应用,别的应用不会收到。(注:即使使用旧的注册广播和发广播的方式也会有下面说的Bug)

当第一次从Android Studio运行App时,发送广播正常,然后再点Android Studio的运行按钮,此时再发广播就收不到了,奇怪的很,在个复杂的项目,你会以为是项目哪里有问题,现在我把代码简化就只有注册广播和发广播的代码了,所以,这明显是系统有问题。经过测试发现,当我在手机中杀进程后,再从桌面启动App,或者直接从Android Studio点运行,此时都能正常收到广播。

这神奇的很!同样的代码,我在另一个品牌(征服H30)的手机,同样是 Android 11 系统 ,同样的操作,一切正常。

后来问了AI,说是广播没有正常解除注册导致的,于是我试验了,在onDestroy时解除广播,然后再从Android Studio运行,也能正常收到广播了,但是这也算是系统有问题,因为我们开发经常会直接就从Android Studio运行新的代码,而不是先在手机上操作正常退出了才从Android Studio中运行。

另外我还发现,在那台有问题的手机上,无论当前App是可以收到广播还是不能收到广播的状态,我点击Android studio运行旁边的停止按钮,如下:

然后再点运行按钮,也是无法正常收到广播的,这个停止按钮有时候有显示,有时候没显示,我也搞不懂。

或者点击进程列表中的 Force stop process 按钮(需要先选择好进程),如下:

然后再从桌面启动App,或者在Android Studio重新运行App,也是无法收到广播的。

在App可以正常收到广播的状态下,当我点击进程列表中的 Kill process 按钮时,如下:

再从桌面启动App,或者在Android Studio重新运行App,此时是可以正常收到广播的,但是,如果App处于收不到广播的状态下,点这个按钮杀进程,然后再启动App也是收不到广播的。但是,如果是在手机上调出最近任务并在此界面中杀掉应用进程,则再从桌面启动App,或者在Android Studio重新运行App,则可以正常收到广播。

所以总结就是,在手机上手动杀进程,可以确保系统把App的旧广播移除,这样再启动时可以正常收到广播。一但感觉广播接收不正常、收不到,则手动杀进程后再重试。甚至也可以卸载应用重装(但这比较麻烦)。

我还找到另外一个解决方案,当发广播收不到后,调用unregisterReceiver(receiver),然后finish掉这个Activity,然后再启动这个Activity,然后再注册广播,再发送广播就又正常了。(我是基于我的只有一个Activity的简单应用实验的,如果有多个Activity或者更复杂的项目,不知道还有没有用)

当发广播收不到后,不调用unregisterReceiver(receiver),直接finish掉这个Activity,然后再启动这个Activity,然后再注册广播,此时我发现每次发广播会收到两次。

总结还是手动杀进程比较好,不会导致发一次广播而收到两次的问题。

相关推荐
24zhgjx-lxq3 天前
OSPF的网络类型:P2P与Broadcast
网络·智能路由器·p2p·broadcast·ensp
赖small强5 个月前
【Linux 网络基础】网络通信中的组播与广播:基础概念、原理、抓包与应用
linux·网络·broadcast·组播·广播·multicast
至天1 年前
Laravel 新 WebSocket 服务 Reverb 使用指南
websocket·php·laravel·broadcast·composer·队列·reverb
图王大胜1 年前
Android Framework AMS(10)广播组件分析-1
android·framework·应用·组件·broadcast·ams·广播
茜茜西西CeCe2 年前
移动技术开发:音乐播放器
android·java·broadcast·android-studio·receiver·移动技术开发
IH_LZH2 年前
Broadcast:Android中实现组件及进程间通信
android·java·android studio·broadcast
追梦的鱼儿2 年前
Android之广播(Broadcast)
android·broadcast·广播
Rjdeng2 年前
深入分析 Android BroadcastReceiver (八)
android·broadcast·receiver
Rjdeng2 年前
深入分析 Android BroadcastReceiver (九)
android·broadcast·receiver