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

Kotlin中从本地相册返回时应用被关闭的问题排查与解决

问题:Activity调用相册后按返回键直接终止应用的原因与解决方法

我在Activity页面中调用本地相册,代码如下:

fun selectGallery() {
    val readPermission = ContextCompat.checkSelfPermission(
        this,
        Manifest.permission.READ_EXTERNAL_STORAGE
    )

    // 权限检查
    if (readPermission == PackageManager.PERMISSION_DENIED) {
        // 请求权限
        ActivityCompat.requestPermissions(
            this,
            arrayOf(
                Manifest.permission.READ_EXTERNAL_STORAGE
            ),
            100
        )
    } else {
        var intent = Intent(Intent.ACTION_PICK)
        intent.data = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
        intent.type = "image/*"

        startActivityForResult(intent, 2000)
    }
}

binding.editAvatar.setOnClickListener {
    selectGallery()
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)

    when (requestCode) {
        2000 -> {
            // 获取图片
            selectedAvatarURI = data?.data!!

            Glide.with(this)
                .load(selectedAvatarURI)
                .into(binding.avatarImage)

            editFillClass.avatarFill.value = true
        }
    }
}

代码运行正常,点击按钮可打开本地相册页面,但在相册页面按下返回键时,应用会被终止。奇怪的是,相同代码在另一个Fragment中使用时,按下返回键不会关闭应用,而是回到之前的Fragment页面。请问出现此问题的原因是什么,如何实现仅关闭相册页面的效果?


原因分析

  • Activity任务栈状态异常:如果当前Activity是任务栈中的唯一页面,或者被配置了android:noHistory="true"属性,那么从相册返回时,系统找不到可回到的页面,就会直接终止应用。
  • Fragment的差异:Fragment依附于Activity存在,从相册返回后会回到承载它的Activity,再显示之前的Fragment,因此不会触发应用终止。

解决方法

1. 检查Activity的Manifest配置

打开AndroidManifest.xml,确认当前Activity没有设置android:noHistory="true"——这个属性会让Activity在离开后立即被销毁,导致从相册返回时无页面可回。

<activity
    android:name=".YourTargetActivity"
    <!-- 确保移除或注释掉这行 -->
    <!-- android:noHistory="true" -->
    ... />

2. 排查意外调用finish()的逻辑

检查当前Activity的代码,看是否在启动相册前、权限请求回调等环节不小心调用了finish(),导致Activity提前被销毁。比如在onRequestPermissionsResult中如果错误处理权限拒绝逻辑,可能会触发finish()。

3. 改用Activity Result API替代startActivityForResult(推荐)

startActivityForResult已被官方废弃,使用Activity Result API能避免旧API的生命周期问题,代码示例:

// 初始化图片选择器
private val pickImageLauncher = registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? ->
    uri?.let {
        selectedAvatarURI = it
        Glide.with(this)
            .load(selectedAvatarURI)
            .into(binding.avatarImage)
        editFillClass.avatarFill.value = true
    }
}

private fun selectGallery() {
    val readPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
    if (readPermission == PackageManager.PERMISSION_DENIED) {
        ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), 100)
    } else {
        pickImageLauncher.launch("image/*")
    }
}

// 权限请求回调
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    if (requestCode == 100 && grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        pickImageLauncher.launch("image/*")
    }
}

4. 确保任务栈存在可返回页面

如果当前Activity是应用的入口页面,建议先跳转至主页面后再调用相册,避免让它成为任务栈中的唯一页面。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 22:39:55