Android使用registerForActivityResult拍照无法获取全尺寸照片问题
解决Android通过Activity Result API获取全尺寸相机照片的问题
核心设计说明:
ActivityResultContracts.TakePicture()从API设计层面就不会直接回调返回Bitmap,它的工作逻辑是由调用方提前指定存储全尺寸照片的文件Uri,相机应用接收Uri权限后直接将拍摄的全尺寸照片写入该路径,最终回调仅返回布尔值标识拍摄操作是否完成。
具体实现步骤
- 完成前置配置
- 适配存储权限:Android 10(API 29)及以上版本可直接使用应用专属存储目录,无需申请公共存储权限;Android 9及以下版本需要提前申请
WRITE_EXTERNAL_STORAGE权限,避免文件写入失败。 - 配置
FileProvider:由于Android 7.0(API 24)之后不允许跨应用直接暴露本地文件路径,需要在AndroidManifest.xml中注册FileProvider,并配置可共享的文件路径规则,用于生成可被相机应用访问的内容Uri。
- 适配存储权限:Android 10(API 29)及以上版本可直接使用应用专属存储目录,无需申请公共存储权限;Android 9及以下版本需要提前申请
- 提前创建存储全尺寸照片的Uri
编写工具方法生成对应照片的存储路径,通过FileProvider转换为可跨应用共享的Uri,示例代码:private fun createImageUri(): Uri? { val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(Date()) val targetFile = File( requireContext().getExternalFilesDir(Environment.DIRECTORY_PICTURES), "IMG_${timeStamp}_${UUID.randomUUID()}.jpg" ) return FileProvider.getUriForFile( requireContext(), "${requireContext().packageName}.fileprovider", // 需与Manifest中注册的authorities完全匹配 targetFile ) } - 替换原有Activity Result回调逻辑
用类成员变量临时存储生成的目标照片Uri(避免屏幕旋转等配置变更导致Uri丢失),初始化TakePicture回调后,在拍摄成功时直接从目标Uri中读取全尺寸Bitmap,示例代码:// 类成员变量保存目标Uri private var targetPhotoUri: Uri? = null private val takeFullSizePhoto = registerForActivityResult(ActivityResultContracts.TakePicture()) { isCaptureSuccess -> if (isCaptureSuccess) { targetPhotoUri?.let { uri -> // 从目标Uri解码读取全尺寸Bitmap val fullSizeBitmap = BitmapFactory.decodeStream( requireContext().contentResolver.openInputStream(uri) ) getUserLocation(fullSizeBitmap) } } } - 触发相机拍照时传入对应Uri
调用相机启动方法时,先完成目标Uri的生成与存储,再将Uri作为参数传给contract的launch方法,示例代码:fun startCapture() { targetPhotoUri = createImageUri() targetPhotoUri?.let { uri -> takeFullSizePhoto.launch(uri) } }
常见注意事项
- 不要尝试在
TakePicture的回调中获取Bitmap返回值:该contract的设计初衷就是避免在应用进程内存中加载大尺寸Bitmap引发OOM,因此所有照片数据都直接写入指定的Uri路径,回调仅返回操作结果标记。 - 禁止在回调方法内部临时生成目标Uri:如果出现Activity重建、页面切换等场景,临时创建的Uri会随对象销毁被回收,导致相机应用无法找到写入路径,最终返回的拍摄结果会为false。
- 如果仅需要读取照片的元数据(如拍摄位置、分辨率),可直接通过Uri加载
ExifInterface,无需解码完整Bitmap,进一步降低内存开销。
内容的提问来源于stack exchange,提问作者Eman Essam
相关产品推荐
相关产品推荐

