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

如何通过Intent在onActivityResult()中获取原质量的图片?

我来帮你搞定这个图片模糊的问题!你现在遇到的情况大概率是因为获取到的是系统返回的缩略图,或者Bitmap解码时没做合适的采样处理,咱们一步步来优化:

一、先解决图库选图的模糊问题

你当前用MediaStore.Images.Media.DATA获取路径的方式在高版本Android中已经受限,而且系统返回的data.getData()有时对应的就是缩略图Uri,并非原图。咱们换个思路,直接基于原图Uri做智能解码:

1. 调整图库选择Intent

确保请求的是原图资源:

Intent galleryIntent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
galleryIntent.setType("image/*"); // 限制仅选择图片类型
startActivityForResult(galleryIntent, RESULT_LOAD_IMAGE);

2. 优化Bitmap解码方法

核心是根据ImageView尺寸计算合适的采样率,既避免加载大图导致内存溢出,又保证显示清晰。替换你原来的getBitmapFromUri方法:

private Bitmap getBitmapFromUri(Uri uri, ImageView targetView) throws IOException {
    InputStream input = getContentResolver().openInputStream(uri);
    BitmapFactory.Options options = new BitmapFactory.Options();

    // 第一步:仅解码图片边界,获取真实宽高(不加载完整Bitmap)
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeStream(input, null, options);
    input.close();

    // 计算采样率:让采样后的图片宽高刚好不小于目标View的2倍(保证高清显示)
    int targetWidth = targetView.getWidth();
    int targetHeight = targetView.getHeight();
    int sampleSize = 1;
    int imgWidth = options.outWidth;
    int imgHeight = options.outHeight;

    if (imgWidth > targetWidth || imgHeight > targetHeight) {
        int halfWidth = imgWidth / 2;
        int halfHeight = imgHeight / 2;
        // 找到最大的2的幂数采样率,确保采样后图片仍能覆盖目标View
        while ((halfWidth / sampleSize) >= targetWidth && (halfHeight / sampleSize) >= targetHeight) {
            sampleSize *= 2;
        }
    }

    // 第二步:解码实际Bitmap
    options.inJustDecodeBounds = false;
    options.inSampleSize = sampleSize;
    options.inPreferredConfig = Bitmap.Config.RGB_565; // 优化内存占用
    input = getContentResolver().openInputStream(uri);
    Bitmap bitmap = BitmapFactory.decodeStream(input, null, options);
    input.close();
    return bitmap;
}

3. 修改onActivityResult逻辑

调用优化后的解码方法,直接传入目标ImageView:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == RESULT_LOAD_IMAGE && resultCode == RESULT_OK && null != data) {
        Uri selectedImage = data.getData();
        try {
            // 传入image_view,让方法根据它的尺寸计算采样率
            bmp = getBitmapFromUri(selectedImage, image_view);
        } catch (IOException e) {
            e.printStackTrace();
        }
        image_view.setImageBitmap(bmp);
        // 直接用Bitmap的宽高,比Drawable的更准确
        Toast.makeText(MainActivity.this, 
            bmp.getWidth() + " & " + bmp.getHeight(), 
            Toast.LENGTH_SHORT).show();
    }
}

二、如果是相机拍照的图片模糊

默认相机Intent会返回缩略图,这时候需要指定拍照后保存的文件路径,直接获取原图:

1. 配置相机拍照逻辑

private Uri cameraImageUri;
private static final int REQUEST_IMAGE_CAPTURE = 2;

private void takePhoto() {
    Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    if (cameraIntent.resolveActivity(getPackageManager()) != null) {
        File photoFile = null;
        try {
            photoFile = createTempImageFile();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        if (photoFile != null) {
            // 适配Android 7.0+的FileProvider
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                cameraImageUri = FileProvider.getUriForFile(this, 
                    "你的应用包名.fileprovider", photoFile);
            } else {
                cameraImageUri = Uri.fromFile(photoFile);
            }
            cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, cameraImageUri);
            startActivityForResult(cameraIntent, REQUEST_IMAGE_CAPTURE);
        }
    }
}

private File createTempImageFile() throws IOException {
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    String imgFileName = "JPEG_" + timeStamp + "_";
    File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
    return File.createTempFile(imgFileName, ".jpg", storageDir);
}

2. 配置FileProvider(Android 7.0+)

在AndroidManifest.xml中添加:

<application>
    ...
    <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>
</application>

然后在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>

3. 处理相机返回结果

在onActivityResult中添加相机逻辑:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    // ... 图库处理逻辑 ...
    else if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
        try {
            bmp = getBitmapFromUri(cameraImageUri, image_view);
        } catch (IOException e) {
            e.printStackTrace();
        }
        image_view.setImageBitmap(bmp);
    }
}

额外注意点

  • 不要用image_view.getDrawable().getIntrinsicWidth()获取图片尺寸,直接用bmp.getWidth()/bmp.getHeight()更准确,因为Drawable可能被ImageView缩放。
  • 如果需要上传图片,直接用原图Uri或解码后的Bitmap,不要依赖系统返回的缩略图。

这样修改后,你获取到的图片应该就清晰正常了,还能避免内存溢出问题~

内容的提问来源于stack exchange,提问作者Ashwani kumar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 03:57:17