Flutter在Android 14中访问设备全量视频与图像的实现求助
Android 14 下获取设备全部视频的实现方案
一、权限申请
Android 14(API 34)对媒体权限做了细分,不再使用统一的READ_EXTERNAL_STORAGE,需单独申请视频读取权限:
- 先在
AndroidManifest.xml中声明权限:
<!-- Android 13+ 专属视频读取权限 --> <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" /> <!-- 兼容低版本(若你的minSdk低于33) --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
- 动态申请权限:
// 检查权限状态 if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_MEDIA_VIDEO) != PackageManager.PERMISSION_GRANTED) { // 发起权限申请 ActivityResultContracts.RequestPermission().launch(Manifest.permission.READ_MEDIA_VIDEO) }
注意:Android 14中用户可选择仅授予「部分权限」(仅允许访问近期视频),若应用需要全量视频,需在权限申请前的说明文案里明确告知用户需求。
二、获取全量视频内容
推荐使用官方的MediaStore API查询设备视频,兼容性与稳定性最优:
1. 构建查询参数
// 定义需要查询的视频字段 val projection = arrayOf( MediaStore.Video.Media._ID, MediaStore.Video.Media.DISPLAY_NAME, MediaStore.Video.Media.DATE_ADDED, MediaStore.Video.Media.SIZE ) // 外部存储视频的查询URI val queryUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI // 可选:按添加时间倒序,优先获取最新视频 val sortOrder = "${MediaStore.Video.Media.DATE_ADDED} DESC"
2. 执行查询并处理结果
contentResolver.query( queryUri, projection, null, null, sortOrder )?.use { cursor -> // 遍历游标提取视频信息 while (cursor.moveToNext()) { val videoId = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID)) val displayName = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DISPLAY_NAME)) val size = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.SIZE)) val dateAdded = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATE_ADDED)) // 生成视频的Content URI,用于后续读取内容 val videoUri = ContentUris.withAppendedId(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, videoId) // 示例:通过ContentResolver打开视频输入流,用于备份操作 contentResolver.openInputStream(videoUri)?.use { inputStream -> // 此处编写备份逻辑,如上传至云端 } } }
3. 处理Android 14的权限限制
如果用户授予了「部分权限」,MediaStore仅会返回最近几天的视频。若要获取全量视频,需引导用户跳转至应用设置页修改权限为「允许所有媒体」:
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply { data = Uri.fromParts("package", packageName, null) } startActivity(intent)
三、可选方案:同时查询图片和视频
若需同时处理图片和视频,可使用MediaStore.Files并过滤媒体类型:
val selection = "${MediaStore.Files.FileColumns.MEDIA_TYPE} = ?" val selectionArgs = arrayOf(MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO.toString()) contentResolver.query( MediaStore.Files.getContentUri("external"), projection, selection, selectionArgs, sortOrder )?.use { cursor -> // 遍历处理视频数据 }
内容的提问来源于stack exchange,提问作者Sharpshooter Gaming
相关产品推荐
相关产品推荐

