Android开发:不使用已废弃的startActivityForResult如何从相册选图获取真实路径
问题排查与修复方案
核心问题点
- Glide请求未绑定目标ImageView,你仅配置了加载监听但没有调用
.into(binding.imgCamera),导致Glide不会触发资源加载流程,onResourceReady回调完全不会执行,这是代码无效果的首要原因。 - 类型强转存在空指针风险,
(resource?.toBitmap() ?: null) as Bitmap的写法错误,若资源加载结果为空,强转Bitmap会直接触发空指针崩溃,必须增加非空拦截逻辑。 - 冗余变量未使用,代码中声明的
private lateinit var activityResultLauncher:ActivityResultLauncher<Intent>全程没有用到,可以直接删除。 - 若你的需求是获取系统相册原图的绝对路径,当前逻辑不符合预期:你现在是将选中的图片重新压缩存储到应用内部私有目录,拿到的是副本路径,不是相册原图的路径。
- 缺少必要的动态权限申请,Android 6.0及以上需要动态申请存储权限才能正常读取相册原图信息,Android13及以上需要申请
READ_MEDIA_IMAGES权限,低于13版本需要申请READ_EXTERNAL_STORAGE权限。
修复方案
方案1:保留原有存副本到内部存储的逻辑
仅需修改Glide加载部分的代码,补充into调用和非空判断即可:
val getImage = registerForActivityResult( ActivityResultContracts.GetContent(), ActivityResultCallback { uri -> uri ?: return@ActivityResultCallback Glide.with(this) .load(uri) .centerCrop() .diskCacheStrategy(DiskCacheStrategy.ALL) .listener(object : RequestListener<Drawable>{ override fun onLoadFailed( e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean ): Boolean { Log.e("TAG", "Error loading image", e) return false } override fun onResourceReady( resource: Drawable?, model: Any?, target: Target<Drawable>?, dataSource: DataSource?, isFirstResource: Boolean ): Boolean { // 非空拦截避免崩溃 resource ?: return false val bitmap: Bitmap = resource.toBitmap() mImagePath = saveImageToInternalStorage(bitmap) binding.txtPath.text = mImagePath return false } }) // 必须添加此行触发Glide加载 .into(binding.imgCamera) } )
方案2:直接获取系统相册原图的绝对路径
不需要通过Glide存副本,新增Uri转真实路径的工具方法即可,性能更好:
- 首先在AndroidManifest.xml中添加权限声明:
<!-- 适配Android13以下版本 --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" /> <!-- 适配Android13及以上版本 --> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
- 新增Uri转路径方法:
private fun getOriginalImagePath(uri: Uri): String? { var path: String? = null val projection = arrayOf(MediaStore.Images.Media.DATA) contentResolver.query(uri, projection, null, null, null)?.use { cursor -> if (cursor.moveToFirst()) { val columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA) path = cursor.getString(columnIndex) } } return path }
- 修改选图回调逻辑:
val getImage = registerForActivityResult(ActivityResultContracts.GetContent()) { uri -> uri ?: return@registerForActivityResult // 加载图片到圆形头像 Glide.with(this) .load(uri) .centerCrop() .into(binding.imgCamera) // 获取原图路径 getOriginalImagePath(uri)?.let { path -> mImagePath = path binding.txtPath.text = path } }
- 记得在触发选图前先动态申请对应的存储权限即可。
内容的提问来源于stack exchange,提问作者Yellow Clock
相关产品推荐
相关产品推荐

