Compose从相册和系统相机拍照获取照片

项目中经常需要用户从相册或者调用相机拍照来获取照片,Compose中的实现和之前的View实现基础相同。为了简化照片选择器的集成,从androidx.activity版本1.7.0开始,提供了PickVisualMedia选择单张照片或单个视频,PickMultipleVisualMedia选择多张照片或多个视频。如果照片选择器在设备上不可用,该库会自动调用 ACTION_OPEN_DOCUMENT intent 操作。搭载 Android 4.4(API 级别 19)或更高版本的设备支持此 intent。

创建底部弹窗

模态底部面板可作为内联菜单或简单对话框的替代方案,尤其适用于提供较长的操作列表,或需要更详细描述和图标的操作项。与对话框类似,模态底部面板会出现在应用内容的前方,出现时会禁用应用的所有其他功能,并一直显示在屏幕上,直到用户确认、关闭或执行所需操作为止。

kotlin 复制代码
ModalBottomSheet(
  onDismissRequest = { },
  sheetGesturesEnabled = false,
  dragHandle = null
) {}

onDismissRequest用于处理弹窗隐藏回调;sheetGesturesEnabled设置为false,禁止手势拖动;dragHandle设置为false隐藏拖动条。

调系统相机拍照

注意

当AndroidManifest中注册了相机权限时,则调系统相机前必须先检查是否有相机权限;如果没有注册相机权限,则可直接调用系统相机进行拍照

权限处理

先检查AndroidManifest是否注册了相机权限,再判断是否有权限,否则直接当有权限处理,判断逻辑如下

kotlin 复制代码
private fun checkPermission(): Boolean {
  return application.packageManager.getPackageInfo(application.packageName, PackageManager.GET_PERMISSIONS)
    ?.takeIf { it.requestedPermissions?.contains(Manifest.permission.CAMERA) == true }
    ?.let {
      ContextCompat.checkSelfPermission(application, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED
    } ?: true
}

若没有权限,则动态申请权限,代码如下

kotlin 复制代码
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.RequestPermission()){}
launcher.launch(Manifest.permission.CAMERA)

使用FileProvider提供照片路径

由于使用的是系统相机进行拍照,需要使用FileProvider提供一个Uri,让相机拍完照后,保存到这个Uri对应的文件中。先在xml目录下定义文件file_paths.xml路径规则

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<paths>
  <files-path name="internal_files" path="." />
  <cache-path name="cache" path="." />
  <external-path name="external" path="." />
  <external-files-path name="external_files" path="." />
  <external-cache-path name="external_cache" path="." />
</paths>

在AndroidManifest中注册provider

xml 复制代码
<provider
  android:name="androidx.core.content.FileProvider"
  android:authorities="${applicationId}.provider"
  android:exported="false"
  android:grantUriPermissions="true">
  <meta-data
    android:name="android.support.FILE_PROVIDER_PATHS"
    android:resource="@xml/file_paths" />
</provider>

调系统相机进行拍照

使用FileProvider提供的Uri进行拍照

kotlin 复制代码
if(checkPermission()){
  val launcher = rememberLauncherForActivityResult(ActivityResultContracts.TakePicture()){}
  val dir = File(application.cacheDir, Environment.DIRECTORY_PICTURES)
  val file = File(dir, "${SimpleDateFormat("yyyyMMddHHmmss", Locale.getDefault()).format(System.currentTimeMillis())}.jpg")
  launcher.launch(FileProvider.getUriForFile(application, "${application.packageName}.provider", file))
} else {
  val launcher = rememberLauncherForActivityResult(ActivityResultContracts.RequestPermission()){}
  launcher.launch(Manifest.permission.CAMERA)
}

从相册选择照片

选择单张照片或视频

使用PickVisualMedia activity结果协定选择单张照片或视频

kotlin 复制代码
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.PickVisualMedia()) {}
launcher.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly))

PickVisualMedia.ImageOnly仅选择照片,PickVisualMedia.VideoOnly仅选择视频,PickVisualMedia.ImageAndVideo同时选择照片和视频。

注意:使用 PickVisualMedia 时,照片选择器会以半屏模式打开。

选择多张照片或视频

使用PickMultipleVisualMedia activity结果协定选择单张照片或视频

kotlin 复制代码
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.PickMultipleVisualMedia(9)){}
launcher.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly))

平台会限制在照片选择器中选择的文件数量上限,如上代码最多选择9张照片。

注意:如果照片选择器不可用,且支持库调用 ACTION_OPEN_DOCUMENT intent 操作,则系统会忽略指定的可选媒体文件数量上限。这里的最大数量必须大于1

相关推荐
大锅盖118 分钟前
HarmonyOS 6.1.1 ArkWeb:交付门户下载资料前-为什么必须先登记下载代理与来源字段
android·华为·harmonyos
峥嵘life9 小时前
Android16 311Y3 EAP-TLS 网络连接失败分析与修复总结
android·开发语言·人工智能·php
Kapaseker10 小时前
破坏性更新 - 解读 Jetpack Compose 1.12
android·kotlin
雨白10 小时前
我的 UML 学习笔记:结合 Android 实例看懂 4 种常用图表
android·架构
怣疯knight10 小时前
快速判断apk有没有支持16kb页面标准
android
风流 少年11 小时前
Spring AI 2.0:Advisor
android·人工智能·spring
YM52e13 小时前
分页查询的基石:ArkTS 为鸿蒙商品列表设计 LIMIT/OFFSET 的表
android·学习·华为·harmonyos
安卓与AI研习社14 小时前
Android ANR 到底怎么定位?从触发原理到日志判断的完整方法
android
阿pin16 小时前
Android随笔-MVI
android·mvi
leobertlan17 小时前
【好玩系列】训练一个神经网络指导小孩玩游戏
android·机器学习·程序员