Android 跳转系统相册选取图片/视频/音频/文档(适配全版本权限)

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)
    }
}

六、补充注意事项

  1. Intent 区别
    • ACTION_OPEN_DOCUMENT:仅选择系统目录文件,安全性高,推荐使用;
    • ACTION_GET_CONTENT:可跳转第三方文件管理器,易选中非法类型文件,不建议使用。
  2. 版本权限对应
    • Android 13+:图片/视频/音频必须分开申请 READ_MEDIA_* 系列权限;
    • Android 11~12:使用媒体权限,也可申请 MANAGE_EXTERNAL_STORAGE 全局文件权限(需引导用户手动开启);
    • Android 10 及以下:传统读写存储权限。
  3. 工具依赖:文中 PermissionUtilsUriUtilsLogUtils 均来自 AndroidUtilCode 开源工具库。
相关推荐
恋猫de小郭3 小时前
Android 限制侧载新进展,谷歌联合国内厂商推验证计划
android·前端·flutter
恋猫de小郭3 小时前
解读 Android 17 全新内存限制,有没有“豁免”后门?
android·前端·flutter
贾艺驰6 小时前
实战Android Framework: 新增一个系统权限
android
alexhilton11 小时前
使用Android Archive进行打包
android·kotlin·android jetpack
badhope13 小时前
做了几年安卓开发,这些坑我帮你踩过了
android·android studio
逐光老顽童3 天前
Java 与 Kotlin 混合开发避坑指南:30 个真实案例实录
android·kotlin
爱勇宝3 天前
鸿蒙生态的下半场:开发者不只要能开发,还要能赚钱
android·前端·程序员
Yeyu3 天前
刷新一帧的艺术:invalidate / postInvalidate / postInvalidateOnAnimation全解析
android
潘潘潘3 天前
Android OTA 升级原理和流程介绍
android
RTC实战笔记3 天前
Android 实时音视频接入教程:媒体补充增强信息(SEI)
音视频·媒体·rtc