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

如何修复Kotlin中Attempting to launch an unregistered ActivityResultLauncher崩溃

Google InAppUpdate 集成崩溃问题排查

问题描述

我在应用中集成了Google的InAppUpdate功能,部分设备出现崩溃但无法复现。Firebase捕获到的崩溃信息如下:

Fatal Exception: java.lang.IllegalStateException: Attempting to launch an unregistered ActivityResultLauncher with contract c.c@5d5894e and input androidx.activity.result.k@c156a6f. You must ensure the ActivityResultLauncher is registered before calling launch()

我的MainActivity代码如下,activityResultLauncher为全局变量,在onCreate方法中检查应用更新,请问有人遇到过该问题吗?

class MainActivity : AppCompatActivity() {

    private lateinit var appUpdateManager: AppUpdateManager

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val toolbar = findViewById<MaterialToolbar>(R.id.toolbar)
        setSupportActionBar(toolbar)

        appUpdateManager = AppUpdateManagerFactory.create(applicationContext)
        appUpdateManager.registerListener(installStateUpdatedListener)
        checkForAppUpdates()
    }

    private val activityResultLauncher =
        registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { result ->
            if (result.resultCode != RESULT_OK) {
                Toast.makeText(this, R.string.something_went_wrong, Toast.LENGTH_SHORT).show()
            }
        }

    private val installStateUpdatedListener = InstallStateUpdatedListener { state ->
        if (state.installStatus() == InstallStatus.DOWNLOADED) {
            popupSnackbarForCompleteUpdate()
        }
    }

    private fun checkForAppUpdates() {
        val appUpdateInfoTask = appUpdateManager.appUpdateInfo
        appUpdateInfoTask.addOnSuccessListener { appUpdateInfo ->
            if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE && appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE)) {
                appUpdateManager.startUpdateFlowForResult(
                    appUpdateInfo, activityResultLauncher,
                    AppUpdateOptions.newBuilder(AppUpdateType.FLEXIBLE).build()
                )
            }
        }
    }

    private fun popupSnackbarForCompleteUpdate() {
        Snackbar.make(findViewById(R.id.cordmain), R.string.update_downloaded, Snackbar.LENGTH_INDEFINITE)
            .setAction(R.string.restart) { appUpdateManager.completeUpdate() }
            .show()
    }
}

问题原因

崩溃核心原因是ActivityResultLauncher未完成注册就被调用launch方法:

  1. Kotlin类属性初始化顺序中,全局的activityResultLauncher虽然声明在onCreate上方,但如果checkForAppUpdates里的appUpdateInfoTask回调因缓存数据快速返回,此时Launcher可能还未完成注册就被传入startUpdateFlowForResult。
  2. 未注销appUpdateManager的监听器,当Activity被系统销毁重建时,旧监听器可能触发回调,而新的Launcher尚未初始化完成。

解决办法

1. 调整初始化顺序,确保Launcher优先注册

将activityResultLauncher的初始化移到onCreate内部,早于checkForAppUpdates调用:

class MainActivity : AppCompatActivity() {

    private lateinit var appUpdateManager: AppUpdateManager
    private lateinit var activityResultLauncher: ActivityResultLauncher<IntentSenderRequest>

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val toolbar = findViewById<MaterialToolbar>(R.id.toolbar)
        setSupportActionBar(toolbar)

        // 先初始化ActivityResultLauncher
        activityResultLauncher = registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { result ->
            if (result.resultCode != RESULT_OK) {
                Toast.makeText(this, R.string.something_went_wrong, Toast.LENGTH_SHORT).show()
            }
        }

        appUpdateManager = AppUpdateManagerFactory.create(applicationContext)
        appUpdateManager.registerListener(installStateUpdatedListener)
        checkForAppUpdates()
    }

    // 其余代码保持不变
}

2. 注销AppUpdateManager监听器

在onDestroy中注销监听器,避免旧回调触发:

override fun onDestroy() {
    super.onDestroy()
    appUpdateManager.unregisterListener(installStateUpdatedListener)
}

3. 增加Launcher初始化状态检查(可选)

在调用更新流程前,确保Launcher已初始化:

private fun checkForAppUpdates() {
    val appUpdateInfoTask = appUpdateManager.appUpdateInfo
    appUpdateInfoTask.addOnSuccessListener { appUpdateInfo ->
        if (::activityResultLauncher.isInitialized && 
            appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE && 
            appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE)) {
            appUpdateManager.startUpdateFlowForResult(
                appUpdateInfo, activityResultLauncher,
                AppUpdateOptions.newBuilder(AppUpdateType.FLEXIBLE).build()
            )
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 02:17:09