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

使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 17:17:49