Android10/11拍照/选图上传服务器 CanHub库onActivityResult返回data为空
问题根因
- 调用系统相机时未预先指定输出Uri,Android 10及以上版本系统相机默认不会在返回的
data中携带图片Uri,直接读取data?.data必然为空 onActivityResult逻辑存在明显错误:裁剪结果对应的requestCode固定为CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE,你在该分支下判断requestCode等于GALLERY_REQUEST_CODE或CAMERA_REQUEST_CODE的条件永远不成立,裁剪后逻辑无法正常执行- 若未动态申请相机、存储读写权限,也会触发返回数据为空的问题
修复步骤
1. 配置FileProvider用于适配文件访问
首先在res/xml目录下创建file_paths.xml,内容如下:
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-files-path name="my_images" path="Pictures" /> </paths>
在AndroidManifest.xml中添加FileProvider配置:
<provider android:name="androidx.core.content.FileProvider" android:authorities="${你的应用包名}.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>
2. 调整相机调用逻辑,预先创建输出Uri
调用相机前先创建待保存的图片文件和对应的Uri,不要依赖系统返回的data获取Uri:
// 全局变量保存相机输出Uri private var cameraOutputUri: Uri? = null private fun openCamera() { // 创建图片存储文件 val photoFile = File( requireContext().getExternalFilesDir(Environment.DIRECTORY_PICTURES), "camera_${System.currentTimeMillis()}.jpg" ) // 生成FileProvider Uri cameraOutputUri = FileProvider.getUriForFile( requireContext(), "${requireContext().packageName}.fileprovider", photoFile ) // 启动相机 val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE) intent.putExtra(MediaStore.EXTRA_OUTPUT, cameraOutputUri) // 授予Uri临时访问权限 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION) startActivityForResult(intent, CAMERA_REQUEST_CODE) }
3. 修复onActivityResult逻辑
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) when (requestCode) { GALLERY_REQUEST_CODE -> { if (resultCode == Activity.RESULT_OK) { data?.data?.let { uri -> launchImageCrop(uri) } } } CAMERA_REQUEST_CODE -> { if (resultCode == Activity.RESULT_OK) { // 直接用预先创建的cameraOutputUri,不要从data里读取 cameraOutputUri?.let { uri -> launchImageCrop(uri) } } } CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE -> { val result = CropImage.getActivityResult(data) if (resultCode == Activity.RESULT_OK) { // 直接拿裁剪后的Uri转文件即可,不需要转Bitmap避免OOM val cropFile = File(result.uri.path) viewModel.getUserCardInfo(cropFile) } else if (resultCode == CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE) { val error = result.error Toast.makeText(requireContext(), error.message, Toast.LENGTH_SHORT).show() } } } }
4. 补充动态权限申请
确保在调用相机/相册前动态申请以下权限:
- 相机权限:
Manifest.permission.CAMERA - 存储权限:Android 12及以下申请
Manifest.permission.READ_EXTERNAL_STORAGE,Android 13及以上替换为READ_MEDIA_IMAGES
内容的提问来源于stack exchange,提问作者parisa
相关产品推荐
相关产品推荐

