Android Studio调用相机获取Bitmap时出现画质丢失问题
问题原因
你通过result.getData().getExtras().get("data")获取的Bitmap是相机返回的缩略图,不是拍摄的完整分辨率原图,所以不管怎么调整压缩格式或质量,画质都无法提升——因为源数据本身就是低分辨率的。
解决方案
让相机直接将完整分辨率的原图保存到你指定的Uri,而非返回缩略图,之后从该Uri读取原图来生成哈希值。以下是具体实现步骤:
1. 配置文件提供者(适配Android 7+)
在AndroidManifest.xml中注册FileProvider,用于安全地共享文件Uri:
<provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>
在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="camera_images" path="Pictures" /> </paths>
2. 创建临时文件Uri
编写方法生成临时文件的Uri,用于相机保存原图:
private Uri createTempImageUri() { File storageDir = getContext().getExternalFilesDir(Environment.DIRECTORY_PICTURES); try { // 创建临时JPG文件 File tempImage = File.createTempFile( "CAM_" + System.currentTimeMillis(), ".jpg", storageDir ); // 通过FileProvider生成Uri return FileProvider.getUriForFile( getContext(), getContext().getPackageName() + ".fileprovider", tempImage ); } catch (IOException e) { e.printStackTrace(); return null; } }
3. 调整相机调用逻辑
修改Intent和回调,让相机保存原图到指定Uri,并读取原图处理:
// 生成临时Uri Uri imageUri = createTempImageUri(); if (imageUri == null) { Toast.makeText(getContext(), "无法创建临时存储路径", Toast.LENGTH_SHORT).show(); return; } // 构建相机Intent,指定输出Uri Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); // 启动相机 launcherForCamera.launch(cameraIntent); // 注册结果回调 launcherForCamera = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), result -> { if (result.getResultCode() == RESULT_OK) { try { // 方式1:读取完整分辨率Bitmap(如果需要Bitmap处理) Bitmap originalBitmap = MediaStore.Images.Media.getBitmap( getContext().getContentResolver(), imageUri ); // 在这里用originalBitmap生成哈希值 // 方式2:直接读取文件流(更节省内存,推荐用于生成哈希) // InputStream imageStream = getContext().getContentResolver().openInputStream(imageUri); // 用imageStream生成哈希值 // 生成哈希后删除临时文件(可选,因为存在应用私有目录,卸载会自动清除) File tempFile = new File(getContext().getExternalFilesDir(Environment.DIRECTORY_PICTURES), imageUri.getLastPathSegment()); if (tempFile.exists()) { tempFile.delete(); } } catch (IOException e) { e.printStackTrace(); Toast.makeText(getContext(), "读取原图失败", Toast.LENGTH_SHORT).show(); } } } );
4. 权限说明
- Android 6.0+:需要动态申请
CAMERA权限。 - Android 10+:无需申请外部存储权限,因为临时文件存在应用私有目录,系统自动授权访问。
内容的提问来源于stack exchange,提问作者Yan
相关产品推荐
相关产品推荐

