使用Kotlin的registerForActivityResult拍照模糊问题求助
解决Fragment中调用相机拍照获取低质量模糊图片问题
你的代码核心问题在于依赖相机返回的缩略图显示,而非获取原图,同时存在逻辑操作错误,导致始终得到模糊图片。以下是具体分析和修复方案:
问题根源
- 获取的是缩略图:通过
intent.extras?.get("data")获取的是相机应用返回的低分辨率缩略图,这是MediaStore.ACTION_IMAGE_CAPTURE的默认行为,并非原图。 - 错误的参数传递:在结果回调中给
intent添加MediaStore.EXTRA_OUTPUT毫无意义,这个参数需要在启动相机时传入,用来指定原图的存储路径。
修复方案
使用官方推荐的ActivityResultContracts.TakePicture()合约,直接让相机将原图保存到指定Uri,避免获取缩略图。步骤如下:
1. 实现临时图片Uri创建方法
用于存储相机拍摄的原图,适配Android 10+的分区存储规则:
private fun createImageUri(): Uri? { val contentValues = ContentValues().apply { put(MediaStore.Images.Media.DISPLAY_NAME, "temp_photo_${System.currentTimeMillis()}.jpg") put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg") } return requireContext().contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues) }
2. 重构相机调用逻辑
替换原有StartActivityForResult为TakePicture合约,直接操作原图Uri:
private var imageUri: Uri? = null // 注册拍照结果回调,专门处理原图存储 val takePictureLauncher = registerForActivityResult(ActivityResultContracts.TakePicture()) { isSuccess -> if (isSuccess && imageUri != null) { // 直接用存储原图的Uri加载图片 binding.ivImagen.setImageURI(imageUri) Toast.makeText(context, "图片Uri: $imageUri", Toast.LENGTH_SHORT).show() } else { Toast.makeText(context, "拍照失败或未获取到图片", Toast.LENGTH_SHORT).show() } } binding.ibTomarFoto.setOnClickListener { // 先创建存储原图的Uri imageUri = createImageUri() imageUri?.let { uri -> // 启动相机并指定原图存储位置 takePictureLauncher.launch(uri) } ?: run { Toast.makeText(context, "无法创建图片存储路径", Toast.LENGTH_SHORT).show() } }
额外注意事项
- 权限适配:Android 13及以上需申请
READ_MEDIA_IMAGES权限;Android 10以下需申请WRITE_EXTERNAL_STORAGE权限,可通过registerForActivityResult(ActivityResultContracts.RequestPermission())处理权限请求。 - 图片加载优化:如果原图过大直接加载可能导致OOM,可使用Glide、Coil等图片加载库进行压缩和缓存处理。
内容的提问来源于stack exchange,提问作者Monrac
相关产品推荐
相关产品推荐

