如何获取高质量图片并显示在ImageView?已尝试方案仍遇异常
解决Android相机拍照后ImageView无显示+FileProvider报错问题
我完全懂你的 frustration——跟着官方教程走却卡壳在FileProvider这一步,还导致ImageView连东西都不显示,确实挺闹心的。咱们一步步拆解问题,先搞定那个FileProvider的报错,再解决ImageView不显示的核心问题:
1. 先核对FileProvider的Manifest配置(90%的坑在这里)
这是FileProvider.getUriForFile()报错的重灾区,一定要逐行匹配:
<application> <!-- 其他原有配置 --> <provider android:name="androidx.core.content.FileProvider" android:authorities="com.your.package.name.fileprovider" <!-- 必须和你代码里传入的authorities完全一致! --> android:exported="false" <!-- FileProvider强制要求为false,不能改 --> android:grantUriPermissions="true"> <!-- 必须开启,才能给相机APP授权访问你的文件 --> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> <!-- 指向res/xml目录下的路径配置文件 --> </provider> </application>
2. 检查res/xml/file_paths.xml的路径配置
这个文件定义了FileProvider允许访问的目录,如果你的拍照保存路径不在这个配置里,必然报错。比如你用getExternalFilesDir(Environment.DIRECTORY_PICTURES)存储照片,配置应该是:
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 对应APP外部私有存储的Pictures目录 --> <external-files-path name="my_captured_images" path="Pictures" /> <!-- 若用其他路径,比如内部存储用<files-path>,外部公共目录用<external-path>,按需添加 --> </paths>
3. 修正拍照Intent的文件创建与传参逻辑
你需要先创建一个空文件来承接相机的输出,再把这个文件的Uri传给相机,而不是依赖Intent返回的data:
// 全局变量保存照片文件,方便onActivityResult里调用 private File photoFile; private static final int REQUEST_IMAGE_CAPTURE = 1; private void takePhoto() { Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); // 先确认有相机APP能处理这个Intent if (takePictureIntent.resolveActivity(getPackageManager()) != null) { try { photoFile = createTempImageFile(); } catch (IOException e) { e.printStackTrace(); // 这里可以给用户提示文件创建失败 return; } // 文件创建成功后生成Uri传给相机 if (photoFile != null) { Uri photoURI = FileProvider.getUriForFile( this, "com.your.package.name.fileprovider", // 再次确认和Manifest里的authorities一致 photoFile ); takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI); startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE); } } } // 创建临时图片文件的辅助方法 private File createTempImageFile() throws IOException { String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date()); String imageFileName = "CAPTURE_" + timeStamp + "_"; File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES); // 确保目录存在 if (!storageDir.exists()) storageDir.mkdirs(); return File.createTempFile(imageFileName, ".jpg", storageDir); }
4. 优化onActivityResult里的图片加载逻辑
官方的setPic()思路没问题,但要确保你是从自己创建的photoFile里读取,而不是从data.getData()取(相机拍照不会把图片Uri放在data里):
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) { // 直接用之前创建的photoFile加载图片,不要碰data.getData() setPic(); } } private void setPic() { ImageView imageView = findViewById(R.id.your_image_view); // 先获取ImageView的尺寸,计算采样率避免OOM int targetW = imageView.getWidth(); int targetH = imageView.getHeight(); BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(photoFile.getAbsolutePath(), options); int photoW = options.outWidth; int photoH = options.outHeight; // 计算缩放比例,取宽高中最小的缩放倍数 int scaleFactor = Math.min(photoW / targetW, photoH / targetH); // 正式解码图片 options.inJustDecodeBounds = false; options.inSampleSize = scaleFactor; options.inPurgeable = true; Bitmap bitmap = BitmapFactory.decodeFile(photoFile.getAbsolutePath(), options); imageView.setImageBitmap(bitmap); // 可以根据需求设置ImageView的scaleType,比如centerCrop或fitCenter imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); }
5. 最后补全权限检查
- Android 13及以上:必须动态申请
CAMERA权限,拍照依赖这个权限; - Android 10以下:如果用的是外部公共目录存储,需要
WRITE_EXTERNAL_STORAGE,但用getExternalFilesDir()的话不需要,因为这是APP私有目录,系统默认授权。
如果还是有报错,把Logcat里的具体错误信息贴出来,但按照上面的步骤排查,大部分FileProvider报错和ImageView不显示的问题都能解决。
内容的提问来源于stack exchange,提问作者Ray
相关产品推荐
相关产品推荐

