Android 11/13访问其他应用media文件夹所需权限及代码示例
Android 11/13 访问其他应用
Android/media/包名目录的权限说明及代码示例 权限要求
Android 11(API 30)
- 无需申请
READ_EXTERNAL_STORAGE或WRITE_EXTERNAL_STORAGE权限,但禁止直接通过文件路径访问其他应用的该目录。必须通过**存储访问框架(SAF)**让用户手动选择目标目录,或借助MediaStoreAPI访问目录内的媒体文件。
Android 13(API 33)
- 访问媒体文件时,需申请细分权限:
READ_MEDIA_IMAGES(图片)、READ_MEDIA_VIDEO(视频)、READ_MEDIA_AUDIO(音频),替代了旧版的READ_EXTERNAL_STORAGE。 - 直接路径访问其他应用的
Android/media/包名目录仍受系统限制,需通过SAF或MediaStore操作;访问自身应用的该目录则无需额外权限(属于应用私有媒体目录)。
代码示例
1. 使用SAF选择其他应用的Android/media目录
private const val REQUEST_CODE_OPEN_DIR = 1001 // 启动SAF选择目标目录 fun openOtherAppMediaDir() { val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).apply { // 可选:设置初始打开位置为Android/media目录 val androidMediaUri = DocumentsContract.buildTreeDocumentUri( "com.android.externalstorage.documents", "primary:Android/media" ) putExtra(DocumentsContract.EXTRA_INITIAL_URI, androidMediaUri) } startActivityForResult(intent, REQUEST_CODE_OPEN_DIR) } // 处理SAF返回的目录结果 override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == REQUEST_CODE_OPEN_DIR && resultCode == Activity.RESULT_OK) { data?.data?.let { treeUri -> // 获取持久化访问权限,避免应用重启后权限失效 contentResolver.takePersistableUriPermission( treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION ) // 通过DocumentFile操作目录内文件 val targetDir = DocumentFile.fromTreeUri(this, treeUri) targetDir?.listFiles()?.forEach { file -> Log.d("SAF_TEST", "文件:${file.name}") } } } }
2. 通过MediaStore查询其他应用目录下的图片
private const val REQUEST_CODE_READ_MEDIA = 1002 fun queryOtherAppMediaImages() { // Android 13+先检查权限 if (ContextCompat.checkSelfPermission( this, Manifest.permission.READ_MEDIA_IMAGES ) != PackageManager.PERMISSION_GRANTED ) { ActivityCompat.requestPermissions( this, arrayOf(Manifest.permission.READ_MEDIA_IMAGES), REQUEST_CODE_READ_MEDIA ) return } // 查询路径包含目标应用包名的图片文件 val projection = arrayOf( MediaStore.Images.Media._ID, MediaStore.Images.Media.DISPLAY_NAME, MediaStore.Images.Media.RELATIVE_PATH ) val selection = "${MediaStore.Images.Media.RELATIVE_PATH} LIKE ?" val selectionArgs = arrayOf("%Android/media/com.example.targetapp%") // 替换为目标应用包名 contentResolver.query( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection, selection, selectionArgs, null )?.use { cursor -> while (cursor.moveToNext()) { val fileName = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME)) Log.d("MEDIA_STORE", "找到图片:$fileName") } } } // 处理权限申请结果 override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<out String>, grantResults: IntArray ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) if (requestCode == REQUEST_CODE_READ_MEDIA && grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { queryOtherAppMediaImages() } }
内容的提问来源于stack exchange,提问作者scheininger
相关产品推荐
相关产品推荐

