如何通过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
相关产品推荐
相关产品推荐

