search
分发文档
分发文档/应用分发/生态政策/控件适配指南/照片视频选择控件
照片视频选择控件更新时间:2026-01-12 17:33:00

一、背景

在移动应用开发中,访问用户设备上的照片和媒体库是一项常见的需求,尤其是在社交媒体、摄影类应用中。然而,传统上实现这一功能通常需要申请读取存储权限,用户在主动授权后,应用可以使用存储访问API读取设备上的照片和媒体数据。这种方案在实践中也存在诸多痛点,具体体现在以下几个方面:

  • 全面访问权限的风险:应用在获得读取存储权限后,可以访问用户设备上所有的照片和媒体文件。而实际上,应用可能仅需要用户选择的特定照片。这种全面访问的能力可能会引发用户和监管机构对隐私泄露的担忧,从而增加应用在隐私保护方面的合规负担。
  • 用户体验的挑战:出于对隐私的考量,用户可能会拒绝授予存储访问权限,从而导致应用中某些需要访问照片的功能无法使用。这种情况不仅影响用户体验,还可能对应用的功能完整性造成影响。
  • 授权操作的复杂性:当用户多次误拒绝权限请求,但仍希望使用相应功能时,应用需要引导用户手动前往系统设置中授予权限,这一过程繁琐且易使用户流失。

为解决上述问题,PhotoPicker(照片视频选择器)应运而生。通过集成PhotoPicker,应用可以弹出系统级的照片视频选择界面,用户在界面中手动选择并授权应用读取特定的照片视频。这一机制提供了以下显著优势:

  • 无需存储权限:应用不再需要申请全面的存储读取权限,避免了因用户拒绝授权而导致的功能不可用问题。
  • 最小化信息访问:应用仅能读取用户明确选择的照片视频数据,符合最小化数据访问的原则,降低隐私风险和合规压力。
  • 增强用户信任:通过透明化的照片视频选择和授权流程,增强用户对应用的信任感,提高应用的用户体验和使用满意度。

通过引入PhotoPicker,开发者不仅能提升应用的隐私保护标准,还能优化用户交互体验,使应用在日益严格的隐私监管环境中具备更强的竞争力。

二、功能介绍

PhotoPicker 提供系统级照片视频选择功能,允许用户在应用内通过一个统一界面选择并授权共享特定照片视频,应用随后能读取这些用户选中的照片视频数据。

三、 适用范围

当前支持PhotoPicker的操作系统版本如下:

  • ColorOS 16(基于Android 16)及以上
  • HyperOS 3(基于Android 16)及以上
  • OriginOS 6(基于Android 16)及以上
  • MagicOS 10(基于Android 16)及以上

四、使用说明

配置Action即可调用PhotoPicker,其余参数按需配置,在onActivityResult对返回数据进行处理。

4.1 Action

MediaStore.ACTION_PICK_IMAGES

该action仅使用于图片/视频,请求方能读取选中图片/视频的数据,无需申请读权限。

返回picker uri,该uri类型仅支持只读、获取有限列信息MediaStore.PickerMediaColumns,其中DATA字段被修饰,非文件在公共路径下的实际路径,ex/sdcard/.transforms/synthetic/picker/0/com.android.providers.media.photopicker/media/xx

参数说明:

名称必填说明
ActionMediaStore.ACTION_PICK_IMAGES允许用户通过该Action获取到图片/视频数据

代码配置:

Java:

Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
startActivityForResult(intent, CODE_PICK_IMAGES);

Kotlin:

val intent = Intent(MediaStore.ACTION_PICK_IMAGES)
startActivityForResult(intent, CODE_PICK_IMAGES)

4.2 Type

获取数据范围
配置值

名称数据类型说明
mimeTypeStringimage/*只获取图片
video/*只获取视频
/不配置图片和视频都获取

是否必填:

代码配置:

Java:

intent.setType("image/*")//仅图片
intent.setType("video/*")//仅视频

Kotlin:

intent.type = "image/*" // 仅图片
intent.type = "video/*" // 仅视频

若不设置type,图片和视频都显示

4.3 Extra

4.3.1 多选模式最大选择数

配置参数: MediaStore.EXTRA_PICK_IMAGES_MAX

系统值: android.provider.extra.PICK_IMAGES_MAX

是否必填:

参数说明:

参数参数类型参数说明
MediaStore.EXTRA_
PICK_IMAGES_MAX
int设置多选模式,值大于1且小于等于100。不传该参数为单选模式

代码配置:
Java:

intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, 50);

Kotlin:

intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, 50)

4.3.2 预选设置

配置参数: MediaStore.EXTRA_PICKER_PRE_SELECTION_URIS

系统值: android.provider.extra.PICKER_PRE_SELECTION_URIS

参数数据类型参数说明
MediaStore.EXTRA_PICKER_PRE_SELECTION_URISArrayList<Uri>多选拉起PhotoPicker时,设置预选图片/视频。受MediaStore.EXTRA_PICK_IMAGES_MAX影响,集合长度不可以超过设置的最大选择数

是否必填:

代码配置:

intent.putExtra(MediaStore.EXTRA_PICKER_PRE_SELECTION_URIS, preSelectResultUris); 

五、使用示例

Java:

Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES); // 必配  
intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, 50); // 选配  
intent.setType("image/*"); // 选配  
intent.putExtra(MediaStore. EXTRA_PICK_IMAGES_IN_ORDER, false); // 选配  
intent.putExtra(MediaStore.EXTRA_PICKER_PRE_SELECTION_URIS, preSelectResultUris); // 选配  
startActivityForResult(intent, CODE_PICK_IMAGES);

Kotlin:

val intent = Intent(MediaStore.ACTION_PICK_IMAGES).apply {
putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, 50)// 选配
    type = "image/*" // 选配
putExtra(MediaStore.EXTRA_PICK_IMAGES_IN_ORDER, false) // 选配
putExtra(MediaStore.EXTRA_PICKER_PRE_SELECTION_URIS, preSelectResultUris) // 选配
}
startActivityForResult(intent, CODE_PICK_IMAGES)

输出结果获取在onActivityResult中获取选中图片的uri集合,区分单选和多选

单选:从intent中直接获取:data.getData()

多选:从intent中取ClipData,uri信息封装在ClipData中

Java:

@Override 
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {  
super.onActivityResult(requestCode, resultCode, data);  
if (requestCode == CODE_PICK_IMAGE && resultCode == Activity.RESULT_OK) {  
if (data != null) {  
mSelectResultUris.clear();  
if (mIsMultiSelect) { // 多选,设置多选参数时配置  
ClipData clipData = data.getClipData();  
if (clipData != null && clipData.getItemCount() > 0) {  
for (int i = 0; i < clipData.getItemCount(); i++) {  
ClipData.Item item = clipData.getItemAt(i);  
mSelectResultUris.add(item.getUri());  
                    }  
                }  
            } else { // 单选  
mSelectResultUris.add(data.getData());  
            }  
Log.d(TAG, "onActsivityResult: mSelectResultUri = " + mSelectResultUris.size());  
        }  
    }  
}

Kotlin:

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    if (requestCode == CODE_PICK_IMAGES && resultCode == Activity.RESULT_OK) {
        data?.let {
            mSelectResultUris.clear()
            // 多选情况
            val clipData = it.clipData
            if (clipData != null && clipData.itemCount > 0) {
                for (i in 0 until clipData.itemCount) {
                    val item = clipData.getItemAt(i)
                    mSelectResultUris.add(item.uri)
                }
            } else {
                // 单选情况
                it.data?.let { uri ->
                    mSelectResultUris.add(uri)
                }
            }
            Log.d(TAG, "onActivityResult: 选择的图片数量 = ${mSelectResultUris.size}")
            mSelectResultUris.forEachIndexed { index, uri ->
                Log.d(TAG, "图片 $index: $uri")
            }
        }
    }
}

该适配指南与金标联盟官网适配指南一致,您也可查阅金标联盟官网中公示适配指南。

金标联盟官方文档地址:https://www.itgsa.com/doc/6631953378231296

上一篇:文件选择控件
下一篇:日历写入控件
文档内容是否有帮助?
有帮助
无帮助