Android解决open failed: EACCES (Permission denied)权限拒绝问题
解决Android分享图片到WhatsApp时的权限拒绝问题
1. 确认并申请对应权限
根据Android版本差异,需申请匹配的存储权限:
- Android 9及以下:申请
READ_EXTERNAL_STORAGE权限 - Android 10-12:仍需
READ_EXTERNAL_STORAGE,同时适配分区存储规则 - Android 13+:申请
READ_MEDIA_IMAGES权限
动态申请权限代码示例
private val REQUEST_STORAGE_PERMISSION = 1001 fun checkAndRequestPermission() { val permissions = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { arrayOf(Manifest.permission.READ_MEDIA_IMAGES) } else { arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE) } if (ContextCompat.checkSelfPermission(this, permissions[0]) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, permissions, REQUEST_STORAGE_PERMISSION) } else { shareWallpaperWithUri() } } // 处理权限申请结果 override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) if (requestCode == REQUEST_STORAGE_PERMISSION && grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { shareWallpaperWithUri() } else { Toast.makeText(this, "需要存储权限才能分享图片", Toast.LENGTH_SHORT).show() } }
2. 适配Android 10+分区存储规则
Android 10及以上启用分区存储后,直接通过文件路径访问公共目录文件会被限制,需通过MediaStore查询获取图片的Uri替代文件路径。
获取图片Uri的代码示例
fun getImageUriFromPath(context: Context, imagePath: String): Uri? { val fileName = imagePath.substringAfterLast("/") val projection = arrayOf(MediaStore.Images.Media._ID) val selection = "${MediaStore.Images.Media.DISPLAY_NAME} = ?" val selectionArgs = arrayOf(fileName) val cursor = context.contentResolver.query( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection, selection, selectionArgs, null ) cursor?.use { if (it.moveToFirst()) { val id = it.getLong(it.getColumnIndexOrThrow(MediaStore.Images.Media._ID)) return ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id) } } return null }
3. 修改分享逻辑,使用Uri替代文件路径
WhatsApp支持通过content://类型的Uri分享图片,需为Intent添加临时读取权限,避免直接访问文件路径引发的权限问题。
修正后的分享方法
fun shareWallpaperWithUri() { val imagePath = "/storage/emulated/0/Pictures/JayTN24/mens_shirt_0.jpg" val imageUri = getImageUriFromPath(this, imagePath) ?: run { Toast.makeText(this, "无法找到目标图片", Toast.LENGTH_SHORT).show() return } val intent = Intent(Intent.ACTION_SEND).apply { type = "image/jpeg" putExtra(Intent.EXTRA_STREAM, imageUri) setPackage("com.whatsapp") addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) } try { startActivity(intent) } catch (e: ActivityNotFoundException) { Toast.makeText(this, "未安装WhatsApp应用", Toast.LENGTH_SHORT).show() } catch (e: Exception) { e.printStackTrace() } }
额外注意事项
- 若图片为你的App生成,建议直接通过
MediaStore写入公共目录,后续可直接获取对应Uri,无需手动解析路径。 - 禁止使用
file://类型Uri分享,高版本Android会限制第三方App访问此类Uri,必须使用content://类型Uri并授予临时权限。
内容的提问来源于stack exchange,提问作者Syed Ghouser
相关产品推荐
相关产品推荐

