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

Jetpack Compose的ComponentActivity接收广播Intent回调未触发问题

问题描述

用Kotlin+Jetpack Compose重写原React Native应用时,无法接收扫码硬件关联应用发送的广播Intent。AndroidManifest.xml的Intent过滤配置与旧AppCompatActivity版本完全一致,但当前使用ComponentActivity时,仅能看到日志输出“Setting up intent...”,通过addOnNewIntentListener添加的回调从未触发,怀疑是Activity生命周期配置或调用遗漏导致。

相关代码:

package com.android.composefolderscanner
 import android.annotation.SuppressLint
 import android.content.Intent
 import android.os.Bundle
 import android.util.Log
 import androidx.activity.ComponentActivity
 import androidx.activity.compose.setContent
 import androidx.activity.viewModels
 import androidx.compose.runtime.DisposableEffect
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.core.util.Consumer
 import com.android.composefolderscanner.ui.FolderApp
 import com.android.composefolderscanner.ui.screens.ScanViewModel
 import com.android.composefolderscanner.ui.theme.IgniteFolderScannerTheme
 import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
class MainActivity : ComponentActivity() {

   private val viewModel: ScanViewModel by viewModels()
   
   @SuppressLint("MissingPermission", "UnusedMaterialScaffoldPaddingParameter")
   override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      setContent {
         val resultV = remember { mutableStateOf<Int?>(101) }
         DisposableEffect(key1 = resultV.value) {
            Log.i("MainActivity","Setting up intent...")
            val listener = Consumer<Intent>{
               Log.i("MainActivity","Receiving intent...")
               val decodedData = it?.getStringExtra("com.symbol.datawedge.data_string")
               if (decodedData!= null){
                  viewModel.addBarcode(decodedData)
               }
            }
            addOnNewIntentListener(listener)
            onDispose {
               Log.i("MainActivity","Removing intents...")
               removeOnNewIntentListener(listener) 
            }
         }

         IgniteFolderScannerTheme(useDarkTheme = true, content = {
            FolderApp( )
         })
      }
   }
}
解决方案

1. 确认Activity启动模式

旧AppCompatActivity能正常接收Intent,大概率是配置了合适的启动模式。在AndroidManifest.xml的MainActivity标签中添加与旧应用一致的启动模式(比如singleTop):

<activity
    android:name=".MainActivity"
    android:launchMode="singleTop"
    <!-- 其他已有的配置 -->
    >
    <!-- 你的IntentFilter配置 -->
</activity>

默认standard模式下,每次接收Intent会创建新的Activity实例,不会触发onNewIntent方法,自然也不会触发addOnNewIntentListener的回调。

2. 直接重写onNewIntent方法(更可靠)

相比依赖Compose的DisposableEffect绑定监听,直接重写Activity的onNewIntent方法是更稳定的方式,避免Compose重组带来的监听丢失问题:

@AndroidEntryPoint
class MainActivity : ComponentActivity() {

   private val viewModel: ScanViewModel by viewModels()
   
   @SuppressLint("MissingPermission", "UnusedMaterialScaffoldPaddingParameter")
   override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      // 处理启动时传入的Intent
      intent?.getStringExtra("com.symbol.datawedge.data_string")?.let {
          viewModel.addBarcode(it)
      }
      setContent {
         IgniteFolderScannerTheme(useDarkTheme = true, content = {
            FolderApp( )
         })
      }
   }

   // 重写onNewIntent处理后续传入的Intent
   override fun onNewIntent(intent: Intent?) {
       super.onNewIntent(intent)
       Log.i("MainActivity","Receiving intent via onNewIntent...")
       intent?.getStringExtra("com.symbol.datawedge.data_string")?.let {
           viewModel.addBarcode(it)
       }
   }
}

3. 移除Compose中不必要的监听代码

删除setContent内的DisposableEffect相关逻辑,避免不必要的监听绑定与解绑操作,简化代码结构。

关键原因说明

addOnNewIntentListener的触发依赖系统调用onNewIntent方法,而这要求Activity处于栈顶且启动模式为singleTop/singleTask等。同时,将监听绑定在Compose的DisposableEffect中,若Activity重建或Compose发生重组,可能出现监听未正确绑定的情况,直接重写onNewIntent是符合Android生命周期规范的标准实现,可靠性更高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 00:35:16