使用Glide加载UCrop生成的本地Uri图片失败求助
问题:Glide无法加载应用内部存储的裁剪后图片
生成的Uri为:file:///data/user/0/com.example.tfg_red_social_v0/files/croppedImage.jpg,已通过文件管理器确认文件存在,但Glide无法正常显示该图片。
相关代码及配置如下:
核心加载代码
private val cropImage = registerForActivityResult(uCropContract){uri-> Glide.with(this).load(uri).circleCrop().into(binding.ivPerfil) }
Manifest配置
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <!-- PERMISOS PARA ACCEDER A INTERNET, CAMARA Y SD --> <uses-permission android:name="android.permission.INTERNET" /> <!-- <uses-permission android:name="android.permission.CAMERA" /> --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" tools:ignore="ScopedStorage"/> <uses-feature android:name="android.hardware.camera" android:required="true" />
FileProvider配置
<provider android:authorities="com.example.tfg_red_social_v0.fileprovider" android:name="androidx.core.content.FileProvider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>
file_paths.xml配置
<?xml version="1.0" encoding="utf-8"?> <paths> <external-files-path name="my_debug_images" path="Pictures"/> </paths>
UCrop相关代码
private val uCropContract = object: ActivityResultContract<List<Uri>, Uri>(){ override fun createIntent(context: Context, input: List<Uri>): Intent { val inputUri = input[0] val outPut = input[1] val uCrop = UCrop.of(inputUri,outPut) .withAspectRatio(16f,9f) return uCrop.getIntent(context) } override fun parseResult(resultCode: Int, intent: Intent?): Uri { return UCrop.getOutput(intent!!)!! } } private val cropImage = registerForActivityResult(uCropContract){uri-> imagenUri=uri Glide.with(this).load(uri).into(binding.ivImagen) } private val getContent = registerForActivityResult(ActivityResultContracts.GetContent()){uri-> val inputUri = uri val outputUri = File(requireContext().filesDir, "croppedImage.jpg").toUri() val listUri = listOf<Uri>(inputUri!!,outputUri) cropImage.launch(listUri) }
启动裁剪代码
binding.ivImagen.setOnClickListener{ getContent.launch("image/*") }
解决方案
问题根源
- FileProvider路径不匹配:
file_paths.xml仅配置了外部存储的应用私有目录(external-files-path),但生成的图片存在内部存储的filesDir下,两者路径映射不对应。 - file:// Uri权限限制:Android 7.0+禁止跨进程直接使用
file://Uri访问文件,Glide加载这类Uri会因权限不足失败。
修复步骤
- 修改file_paths.xml,添加内部存储映射:
<?xml version="1.0" encoding="utf-8"?> <paths> <!-- 保留原有外部存储配置(若需) --> <external-files-path name="my_debug_images" path="Pictures"/> <!-- 添加内部存储files目录的全量映射 --> <files-path name="internal_files" path="."/> </paths>
files-path对应应用内部存储的filesDir目录,path="."表示映射整个目录。
- 用FileProvider生成合法的Content Uri:
替换直接生成file://Uri的逻辑,通过FileProvider.getUriForFile()生成符合Android权限规范的Content Uri:
private val getContent = registerForActivityResult(ActivityResultContracts.GetContent()){uri-> val inputUri = uri val outputFile = File(requireContext().filesDir, "croppedImage.jpg") // 生成Content Uri,authorities需与Manifest中配置一致 val outputUri = FileProvider.getUriForFile( requireContext(), "com.example.tfg_red_social_v0.fileprovider", outputFile ) val listUri = listOf<Uri>(inputUri!!,outputUri) cropImage.launch(listUri) }
- 验证文件写入与加载:
- 可通过
outputFile.exists()和outputFile.length()确认UCrop是否成功写入有效文件; - Glide直接使用返回的Content Uri加载即可,无需额外配置:
private val cropImage = registerForActivityResult(uCropContract){uri-> imagenUri=uri Glide.with(this).load(uri).into(binding.ivImagen) }
额外排查点
- 查看Logcat中Glide相关日志,搜索
Glide关键词定位具体错误(如权限异常、文件损坏); - 确认UCrop的输出文件路径与FileProvider映射路径完全匹配。
内容的提问来源于stack exchange,提问作者Monrac
相关产品推荐
相关产品推荐

