You need to enable JavaScript to run this app. Android使用registerForActivityResult拍照无法获取全尺寸照片问题
优惠活动
大模型
产品
解决方案
定价
更多

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。
  • 提前创建存储全尺寸照片的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.26 10:54:03