示例代码如下:
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,然后再注册广播,此时我发现每次发广播会收到两次。
总结还是手动杀进程比较好,不会导致发一次广播而收到两次的问题。