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
相关产品推荐
相关产品推荐

