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

