使用MediaStore.ACTION_IMAGE_CAPTURE无法获取高质量Bitmap求助
你的代码存在几个关键问题导致无法获取高质量Bitmap,以下是问题点和修正方案:
1. 启动相机时传递的Intent错误
你创建了两个Intent实例:cameraIntent和新的Intent,但仅给新Intent设置了MediaStore.EXTRA_OUTPUT,最终启动的却是未携带该参数的cameraIntent。相机App不会将照片写入你指定的imageUri,导致后续读取失败。
修正后的触发拍照代码:
takepic.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); if (cameraIntent.resolveActivity(getPackageManager()) != null) { File photoFile = null; try { photoFile = createImageFile(); } catch (IOException ex) { ex.printStackTrace(); } if (photoFile != null) { imageUri = FileProvider.getUriForFile(MainActivity.this, "com.oreda.odisha.fileprovider", photoFile); // 给相机App授予Uri读写权限 cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); cameraIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); cameraIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); cameraResultLauncher.launch(cameraIntent); } } } });
2. FileProvider路径配置优化
你当前使用external-path指向应用的外部文件目录,改用external-files-path更贴合getExternalFilesDir()的路径,配置更简洁且不易出错:
修正后的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>
external-files-path直接对应getExternalFilesDir(null)的路径,path="Pictures"指向该目录下的Pictures子文件夹,与createImageFile()中的存储目录完全匹配。
3. 结果处理逻辑错误
当通过MediaStore.EXTRA_OUTPUT指定照片存储路径后,相机返回的data.getData()通常为null,你代码中替换imageUri的逻辑会导致使用错误的Uri读取文件,最终返回null。此外,MediaStore.Images.Media.getBitmap()已被废弃,建议使用ImageDecoder替代。
修正后的结果处理代码:
private void cameraImage() throws IOException { if (imageUri == null) { Toast.makeText(this, "图片Uri为空", Toast.LENGTH_LONG).show(); return; } // 使用ImageDecoder读取高质量Bitmap(替代废弃的getBitmap方法) try { ImageDecoder.Source source = ImageDecoder.createSource(getContentResolver(), imageUri); Bitmap bitmap = ImageDecoder.decodeBitmap(source); if (bitmap != null) { // 处理你的Bitmap } else { Toast.makeText(MainActivity.this, "Bitmap为空", Toast.LENGTH_LONG).show(); } } catch (IOException e) { e.printStackTrace(); // 降级使用BitmapFactory尝试读取 InputStream inputStream = getContentResolver().openInputStream(imageUri); if (inputStream != null) { BitmapFactory.Options options = new BitmapFactory.Options(); options.inPreferredConfig = Bitmap.Config.RGB_565; Bitmap bitmap = BitmapFactory.decodeStream(inputStream); if (bitmap != null) { // 处理Bitmap } inputStream.close(); } } addToJSON(); } ActivityResultLauncher<Intent> cameraResultLauncher = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() { @Override public void onActivityResult(ActivityResult result) { if (result.getResultCode() == Activity.RESULT_OK) { try { cameraImage(); // 无需传递data,直接使用预先保存的imageUri } catch (Exception e) { e.printStackTrace(); } } } });
4. 保存imageUri以应对生命周期变化
如果你的Activity可能因屏幕旋转等情况重建,需要在onSaveInstanceState中保存imageUri,在onCreate中恢复:
@Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); if (imageUri != null) { outState.putParcelable("image_uri", imageUri); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (savedInstanceState != null) { imageUri = savedInstanceState.getParcelable("image_uri"); } // 其他初始化代码 }
内容的提问来源于stack exchange,提问作者Rameswar Tarai

