Android 跳转系统相册选取图片/视频/音频/文档(适配全版本权限)
一、权限适配说明
Android 11(API 30)及以上、Android 11 以下权限规则不同,Android 13+ 进一步细分媒体权限,需区分图片、视频、音频单独申请。
1. 权限清单(AndroidManifest.xml)
(1)Android 11+(含 Android 13/14)媒体权限
xml
<!-- 读取图片 -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<!-- 读取视频(选视频时添加) -->
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<!-- 读取音频(选音频时添加) -->
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<!-- 全局文件访问(可选,需手动跳转系统设置授权) -->
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
(2)Android 11 以下 存储权限
xml
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
说明:代码中权限工具类基于 AndroidUtilCode 框架。
二、动态权限申请代码
1. Android 11+ 选取图片(动态申请)
kotlin
PermissionUtils.permission(
Manifest.permission.READ_MEDIA_IMAGES
).callback { isAllGranted, granted, deniedForever, denied ->
if (isAllGranted) {
// 权限通过,跳转相册
goAlbum()
} else {
showError("请授予存储权限")
}
}.request()
2. Android 11 以下 动态申请
kotlin
PermissionUtils.permission(
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
).callback { isAllGranted, granted, deniedForever, denied ->
if (isAllGranted) {
// 权限通过,跳转相册
goAlbum()
} else {
showError("请授予存储权限")
}
}.request()
补充:选取视频/音频 时,将权限替换为
READ_MEDIA_VIDEO/READ_MEDIA_AUDIO即可。
三、跳转系统相册/文件选择器
核心方法 goAlbum()
优先使用 ACTION_OPEN_DOCUMENT(限定系统文件,规避异常文件选中问题),不推荐 ACTION_GET_CONTENT。
kotlin
private fun goAlbum() {
val albumIntent = Intent(Intent.ACTION_OPEN_DOCUMENT)
// ========== 按需设置文件类型(二选一/组合) ==========
// 1. 只选图片
albumIntent.type = "image/*"
// 2. 只选视频
// albumIntent.type = "video/*"
// 3. 只选音频
// albumIntent.type = "audio/*"
// 4. 所有文件不限制
// albumIntent.type = "*/*"
// 5. 选取多种办公文档(自定义 MimeType)
/*
albumIntent.putExtra(
Intent.EXTRA_MIME_TYPES,
arrayOf(
MimeType.DOC,
MimeType.DOCX,
MimeType.PDF,
MimeType.PPT,
MimeType.PPTX,
MimeType.XLS,
MimeType.XLSX,
MimeType.TXT
)
)
*/
// 开启多选
albumIntent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
// 启动选择器
startActivityForResult(albumIntent, 100)
}
四、自定义文件 MimeType 常量类
kotlin
object MimeType {
const val DOC: String = "application/msword"
const val DOCX: String = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
const val XLS: String = "application/vnd.ms-excel application/x-excel"
const val XLSX: String = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
const val PPT: String = "application/vnd.ms-powerpoint"
const val PPTX: String = "application/vnd.openxmlformats-officedocument.presentationml.presentation"
const val PDF: String = "application/pdf"
const val TXT: String = "text/plain"
}
五、选择结果回调(onActivityResult)
接收返回的 Uri,通过 UriUtils(AndroidUtilCode)转换为本地文件路径:
kotlin
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
// 校验请求码与返回结果
if (resultCode != RESULT_OK || requestCode != 100) return
data?.let {
// Uri 转 File 对象
val uriFile = UriUtils.uri2File(data.data)
// 打印文件真实路径
LogUtils.e("文件路径", uriFile.path)
}
}
六、补充注意事项
- Intent 区别
ACTION_OPEN_DOCUMENT:仅选择系统目录文件,安全性高,推荐使用;ACTION_GET_CONTENT:可跳转第三方文件管理器,易选中非法类型文件,不建议使用。
- 版本权限对应
- Android 13+:图片/视频/音频必须分开申请
READ_MEDIA_*系列权限; - Android 11~12:使用媒体权限,也可申请
MANAGE_EXTERNAL_STORAGE全局文件权限(需引导用户手动开启); - Android 10 及以下:传统读写存储权限。
- Android 13+:图片/视频/音频必须分开申请
- 工具依赖:文中
PermissionUtils、UriUtils、LogUtils均来自 AndroidUtilCode 开源工具库。