文件与分享
文件与分享 · androidx.documentfile
PhotoPicker:系统图片选择器DocumentFile 1.1.0-rc01
Activity Result API 选图、内嵌 PhotoPicker 与照片选择的最佳实践。
最后更新 2026-08-01
复制即用
用 Activity Result API 调起系统图片选择器(无需存储权限):
import androidx.activity.result.PickVisualMediaRequest
import androidx.activity.result.contract.ActivityResultContracts
val pickMedia = rememberLauncherForActivityResult(
ActivityResultContracts.PickVisualMedia()
) { uri ->
// uri 为选中的图片 Uri,用户取消时为 null
if (uri != null) {
loadImage(uri)
}
}
pickMedia.launch(
PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly)
)限定只选图片(不选视频):
PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly)内嵌 PhotoPicker(API 34+)
@OptIn(ExperimentalPhotoPickerComposeApi::class)
@Composable
fun EmbeddedPicker() {
val state = rememberEmbeddedPhotoPickerState()
EmbeddedPhotoPicker(state = state)
}读取选中内容
// uri 是内容 URI,用 ContentResolver 读取
val input = context.contentResolver.openInputStream(uri)
val bytes = input?.readBytes()
input?.close()媒体类型限定
| 请求 | 说明 |
|---|---|
PickVisualMedia.ImageOnly | 只选图片 |
PickVisualMedia.VideoOnly | 只选视频 |
PickVisualMedia.ImageAndVideo | 图片或视频 |
MediaType("image/gif") | 指定 MIME 类型 |
MediaStore.MediaColumns.DATE_ADDED + 多重选择 | 多选(PickMultipleVisualMedia) |
// 多选
val pickMultiple = rememberLauncherForActivityResult(
ActivityResultContracts.PickMultipleVisualMedia(maxItems = 5)
) { uris -> uris.forEach { loadImage(it) } }常见陷阱
- 低版本无 Photo Picker:旧设备回退到
ACTION_OPEN_DOCUMENT方案或系统旧选择器。 - 读取权限:Photo Picker 返回的是临时授权内容 URI,读完后无需持久化权限,但长时间持有会失效。
- 用户取消:uri 为 null,必须处理。
- 大图 OOM:读取后按需缩放(
BitmapFactoryinSampleSize)。
要点
PickVisualMedia走系统 Photo Picker,不需要READ_MEDIA_IMAGES等存储权限。- 返回值是
Uri(内容 URI),通过contentResolver.openInputStream(uri)读取。 - 用户取消返回
null,需要处理空情况。 - 内嵌
EmbeddedPhotoPicker需要 API 34+(UPSIDE_DOWN_CAKE)且为实验 API,低版本回退到 Activity Result 方案。