You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

打开相机时Intent为null问题求助(附Kotlin代码)

相机拍照后onActivityResult中Intent为null的问题解决

问题说明

已实现打开相机、相册选择图片的功能,选中的图片可显示在ImageView并保存至Room数据库。相册选择流程正常,但调用相机拍照后,onActivityResult中接收的Intent为null,导致data.data为空,无法获取拍照后的图片Uri。

核心原因

当通过MediaStore.EXTRA_OUTPUT指定拍照图片的保存路径时,系统相机应用不会将图片Uri通过onActivityResult的data参数返回——因为你已经提前指定了保存位置,无需再通过data传递。此外,原代码存在两处错误:

  1. 在onActivityResult中错误尝试从当前Activity的intent获取EXTRA_OUTPUT,而非启动相机时的Intent;
  2. 试图从data.data获取Uri,不符合相机的返回逻辑。

修复方案

1. 提前保存拍照Uri

在启动相机前,将生成的图片Uri存储为Activity的成员变量(或通过ViewModel、savedInstanceState持久化),避免依赖onActivityResult的data参数。

2. 修改相机启动逻辑

优化displayCamera方法,确保Uri生成可靠,并授予相机写入权限:

// 在Activity中定义成员变量存储拍照Uri
private var cameraImageUri: Uri? = null

private fun displayCamera(activity: Activity) {
    // 获取应用私有外部存储目录,无需申请外部存储权限
    val destPath = activity.getExternalFilesDir(null)?.absolutePath ?: return
    val imagesFolder = File(destPath, activity.resources.getString(R.string.app_name))
    
    // 创建目录(确保存在)
    if (!imagesFolder.exists()) {
        imagesFolder.mkdirs()
    }
    
    // 生成唯一文件名的图片文件
    val imgFile = File(imagesFolder, "${System.currentTimeMillis()}.jpg")
    cameraImageUri = FileProvider.getUriForFile(
        activity, "${BuildConfig.APPLICATION_ID}.provider", imgFile
    )
    
    // 启动相机Intent,添加写入权限
    val cameraIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE).apply {
        putExtra(MediaStore.EXTRA_OUTPUT, cameraImageUri)
        addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
    }
    activity.startActivityForResult(cameraIntent, 1)
}

3. 修复onActivityResult逻辑

直接使用提前保存的cameraImageUri处理拍照结果,无需依赖data参数:

@Deprecated("Deprecated in Java")
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    if (resultCode == RESULT_OK) {
        when (requestCode) {
            0 -> { // 相册选择逻辑保持不变
                val selectedImageUri = data?.data
                selectedImageUri?.let {
                    databinding.profileImage.setImageURI(it)
                    path = getPath(this, it).toString()
                }
            }
            1 -> { // 拍照结果处理
                cameraImageUri?.let { uri ->
                    // 显示图片
                    databinding.profileImage.setImageURI(uri)
                    // 获取图片路径(根据需求调整)
                    path = uri.path ?: ""
                    
                    // 可选:刷新媒体库,让图片能在系统相册中显示
                    val mediaScanIntent = Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE)
                    mediaScanIntent.data = uri
                    sendBroadcast(mediaScanIntent)
                }
            }
        }
    }
}

4. 处理Activity重建场景(可选)

如果Activity在拍照时因屏幕旋转等原因被销毁,需通过savedInstanceState保存Uri:

override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState)
    cameraImageUri?.let {
        outState.putParcelable("CAMERA_IMAGE_URI", it)
    }
}

override fun onRestoreInstanceState(savedInstanceState: Bundle) {
    super.onRestoreInstanceState(savedInstanceState)
    cameraImageUri = savedInstanceState.getParcelable("CAMERA_IMAGE_URI")
}

注意事项

  • 确保FileProvider配置正确:在AndroidManifest.xml中注册Provider,并在res/xml目录下创建file_paths.xml定义共享路径;
  • Android 10及以上版本无需申请WRITE_EXTERNAL_STORAGE权限,因为使用的是应用私有外部存储目录;
  • 若图片显示异常,可尝试使用文件路径直接加载(如BitmapFactory.decodeFile(imgFile.absolutePath))。

内容的提问来源于stack exchange,提问作者Jayanta Sarkar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 21:30:37