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

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转真实路径的工具方法即可,性能更好:

  1. 首先在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" />
  1. 新增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
}
  1. 修改选图回调逻辑:
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
    }
}
  1. 记得在触发选图前先动态申请对应的存储权限即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 02:24:08