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

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 }

解决方案

问题核心原因

  1. 动态Receiver的定位错误:你在Service里指定了ComponentName指向Activity内部的动态Receiver,但动态注册的Receiver不会被系统以组件名的形式记录,这种方式无法找到目标Receiver。
  2. Activity初始化疏漏:SaleActivity的onCreate方法缺少super.onCreate(savedInstanceState)调用,会导致Activity初始化异常,间接影响Receiver的注册流程。
  3. 跨应用广播的适配问题: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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 09:35:24