如何在Adapter中访问URI图片?重启应用遇SecurityException问题
解决重启应用后调用setImageUri触发SecurityException的问题
问题原因分析
- 持久化权限申请时机错误:你在Adapter中调用
takePersistableUriPermission时,应用已重启,从相册获取的临时URI权限已失效,无法再转为持久化权限。持久化权限必须在刚获取到URI的会话中申请。 - URI格式异常:报错中的
android.resource://URI并非相册返回的标准content://URI,说明你保存的URI存在格式错误,或是误存了应用内资源URI而非相册图片URI。
解决方案
1. 在获取URI时立即申请持久化权限
修改AddCocktailFragment中permissionLauncher的回调逻辑,拿到相册返回的URI后,先申请持久化权限再保存URI:
private val permissionLauncher = registerForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri -> uri?.let { // 申请持久化读取权限 requireActivity().contentResolver.takePersistableUriPermission( it, Intent.FLAG_GRANT_READ_URI_PERMISSION ) binding.imageAdd.setImageURI(it) cocktailModel.setImage(it.toString()) // 保存原始content://格式的URI字符串 } }
2. 移除Adapter中无效的权限申请代码
Adapter中无需再调用takePersistableUriPermission,直接使用保存的URI即可:
override fun onBindViewHolder(holder: CocktailHolder, position: Int) { with(holder) { val cocktail = listCocktails[position] binding.apply { // 移除无效的权限申请代码 imageView.setImageURI(Uri.parse(cocktail.image)) // 直接解析保存的URI字符串 titleCocktail.text = cocktail.title imageView.setOnClickListener { cocktailModel.setCocktail(cocktail) NavHostFragment.findNavController(fragment) .navigate(R.id.action_mainFragment_to_cocktailCardFragment) } } } }
3. 验证URI保存格式
确保cocktail.image保存的是相册返回的原始content://格式字符串,不要对URI进行额外格式转换(比如toUri().toString()可能导致格式异常),直接保存uri.toString()即可。
4. 权限配置说明
你的Manifest权限配置已满足需求,注意从Android 13开始,READ_EXTERNAL_STORAGE权限已被废弃,使用PickVisualMedia无需申请该权限,保留现有配置可兼容低版本系统。
内容的提问来源于stack exchange,提问作者Дмитрий Малигон
相关产品推荐
相关产品推荐

