Kotlin跨应用Foreground Service无法向Activity发送Broadcast Intent问题
跨应用Foreground Service向Activity传递数据失败问题
我有两个独立应用:一个是包含Activity的SaleApp,另一个是仅含Foreground Service的RegistryApp。尝试通过BroadcastReceiver从Service向Activity传输数据,但Receiver无法接收Intent。我认为无需在Manifest中注册Receiver。以下是相关代码及Logcat日志,求解决方法。
Activity代码
class SaleActivity : AppCompatActivity() { class MyReceiver : BroadcastReceiver() { override fun onReceive(p0: Context?, p1: Intent?) { if (p1 != null) { val responseCode = p1.getStringExtra("RESPONSE_CODE") } } } override fun onCreate(savedInstanceState: Bundle?) { val filter = IntentFilter("com.myexample.saleapp.TO_SALE_APP") val receiver: MyReceiver = MyReceiver() registerReceiver(receiver, filter) } }
Service代码
class RegistryService : Service() { internal class IncomingHandler( context: Context, private val applicationContext: Context = context.applicationContext, ) : Handler(Looper.getMainLooper()) { override fun handleMessage(msg: Message) { when (msg.what) { MSG_GO_SALE -> { // 发送广播的Intent val i = Intent() i.action = "com.myexample.saleapp.TO_SALE_APP" i.putExtra("RESPONSE_CODE", 99) i.flags = Intent.FLAG_INCLUDE_STOPPED_PACKAGES i.component = ComponentName("com.myexample.saleapp","com.myexample.saleapp.SaleActivity.MyReceiver") applicationContext.sendBroadcast(i) } else -> super.handleMessage(msg) } } } // ... 其他代码 }
Service通知相关代码
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { createNotificationChannel() startForeground(notificationId, notification) val i = packageManager.getLaunchIntentForPackage("com.myexample.paymentapp") if (i != null) { i.flags = Intent.FLAG_ACTIVITY_NEW_TASK i.putExtra("PRODUCT_ID", productId) i.putExtra("PRODUCT_NAME", productName) i.putExtra("PRICE", price) i.putExtra("VAT_RATE", vatRate) startActivity(i) } else { Toast.makeText(this,"启动失败",Toast.LENGTH_SHORT).show() } return START_STICKY } private fun createNotificationChannel() { val notificationChannel = NotificationChannel("progress_channel", "进度", NotificationManager.IMPORTANCE_DEFAULT) val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager notificationManager.createNotificationChannel(notificationChannel) } private val notification by lazy { NotificationCompat.Builder(this, "progress_channel") .setContentTitle("支付处理中...") .setSmallIcon(R.drawable.ic_launcher_foreground) .build() } override fun onCreate() { super.onCreate() createNotificationChannel() startForeground(notificationId, notification) }
错误日志
2022-11-20 03:24:35.323 513-557/? W/BroadcastQueue: Background execution not allowed: receiving Intent { act=android.net.conn.NETWORK_CONDITIONS_MEASURED flg=0x10 (has extras) } to com.google.android.gms/.chimera.GmsIntentOperationService$PersistentTrustedReceiver 2022-11-20 03:24:35.461 513-1473/? W/ActivityManager: Background start not allowed: service Intent { cmp=com.google.android.apps.messaging/.shared.datamodel.action.execution.ActionExecutorImpl$EmptyService } to com.google.android.apps.messaging/.shared.datamodel.action.execution.ActionExecutorImpl$EmptyService from pid=13113 uid=10119 pkg=com.google.android.apps.messaging startFg?=false 2022-11-20 03:24:35.529 513-1477/? W/ActivityManager: Background start not allowed: service Intent { cmp=com.google.android.apps.messaging/.shared.datamodel.action.execution.ActionExecutorImpl$EmptyService } to com.google.android.apps.messaging/.shared.datamodel.action.execution.ActionExecutorImpl$EmptyService from pid=13113 uid=10119 pkg=com.google.android.apps.messaging startFg?=false 2022-11-20 03:24:36.437 513-557/? W/BroadcastQueue: Background execution not allowed: receiving Intent { act=android.net.conn.NETWORK_CONDITIONS_MEASURED flg=0x10 (has extras) } to com.google.android.gms/.chimera.GmsIntentOperationService$PersistentTrustedReceiver 2022-11-20 03:24:43.853 513-551/? D/EventSequenceValidator: Transition from ACTIVITY_FINISHED to INTENT_STARTED 2022-11-20 03:24:43.854 513-1785/? I/ActivityTaskManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000000 pkg=com.google.android.apps.nexuslauncher cmp=com.google.android.apps.nexuslauncher/.NexusLauncherActivity (has extras)} from uid 10137 2022-11-20 03:24:43.877 513-551/? D/EventSequenceValidator: Transition from INTENT_STARTED to ACTIVITY_LAUNCHED 2022-11-20 03:24:44.149 12251-12251/? D/BoundBrokerSvc: onBind: Intent { act=com.google.android.gms.feedback.internal.IFeedbackService dat=chimera-action: cmp=com.google.android.gms/.chimera.GmsBoundBrokerService } 2022-11-20 03:24:44.149 12251-12251/? D/BoundBrokerSvc: Loading bound service for intent: Intent { act=com.google.android.gms.feedback.internal.IFeedbackService dat=chimera-action: cmp=com.google.android.gms/.chimera.GmsBoundBrokerService }
解决方案
问题核心原因
- 动态Receiver的定位错误:你在Service里指定了
ComponentName指向Activity内部的动态Receiver,但动态注册的Receiver不会被系统以组件名的形式记录,这种方式无法找到目标Receiver。 - Activity初始化疏漏:SaleActivity的
onCreate方法缺少super.onCreate(savedInstanceState)调用,会导致Activity初始化异常,间接影响Receiver的注册流程。 - 跨应用广播的适配问题:Android 8.0+对后台广播有严格限制,虽然Service是前台服务,但跨应用广播的配置仍需符合规则。
具体修复步骤
1. 修复Activity初始化
在SaleActivity的onCreate中补上父类方法调用,确保Activity正常初始化:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 必须添加 setContentView(R.layout.activity_sale) // 需绑定对应布局文件 val filter = IntentFilter("com.myexample.saleapp.TO_SALE_APP") val receiver: MyReceiver = MyReceiver() registerReceiver(receiver, filter) }
2. 调整Service的广播发送逻辑
移除ComponentName配置,直接通过Action匹配动态Receiver:
val i = Intent("com.myexample.saleapp.TO_SALE_APP") i.putExtra("RESPONSE_CODE", 99) // 允许广播发送到已停止的应用(如果SaleApp可能未启动) i.flags = Intent.FLAG_INCLUDE_STOPPED_PACKAGES applicationContext.sendBroadcast(i)
3. 可选:添加跨应用广播权限(提升安全性)
为了防止其他应用干扰,建议自定义签名权限:
- 在两个应用的
AndroidManifest.xml中添加:
<!-- 自定义广播权限 --> <permission android:name="com.myexample.permission.SEND_SALE_BROADCAST" android:protectionLevel="signature" /> <!-- 仅同签名应用可发送 --> <uses-permission android:name="com.myexample.permission.SEND_SALE_BROADCAST" />
- 发送广播时指定权限:
applicationContext.sendBroadcast(i, "com.myexample.permission.SEND_SALE_BROADCAST")
4. 调试验证
在Receiver中添加日志,确认是否收到广播:
override fun onReceive(p0: Context?, p1: Intent?) { if (p1 != null) { val responseCode = p1.getStringExtra("RESPONSE_CODE") Log.d("MyReceiver", "收到响应码: $responseCode") } }
也可以用adb命令手动发送广播测试:
adb shell am broadcast -a com.myexample.saleapp.TO_SALE_APP
内容的提问来源于stack exchange,提问作者Sezai
相关产品推荐
相关产品推荐

