Android相机拍照后无法在ImageView显示问题求助
拍照后图片无法在ImageView显示的问题排查与修复
嘿,看了你的代码和问题描述,我帮你梳理下几个可能导致图片不显示的关键点,以及对应的修复方案:
1. 动态权限缺失(Android 6.0+必备)
你只在Manifest里声明了读写权限,但Android 6.0(API 23)及以上需要动态申请权限,否则实际运行时会没有读写外部存储的权限,导致图片无法保存或读取。
修复步骤:
在MainActivity的onCreate或者点击拍照按钮前,先检查并申请权限:
private static final int REQUEST_PERMISSIONS = 100; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); imgpic = findViewById(R.id.imgpic); btncam = findViewById(R.id.btncamera); // 检查权限 if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_PERMISSIONS); } btncam.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // 先确保权限已获取再启动相机 if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { launchCamera(); } else { Toast.makeText(MainActivity.this, "请先授予存储权限", Toast.LENGTH_SHORT).show(); } } }); } // 处理权限申请结果 @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == REQUEST_PERMISSIONS) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 权限获取成功,可以启动相机 launchCamera(); } else { Toast.makeText(this, "需要存储权限才能保存照片", Toast.LENGTH_SHORT).show(); } } } // 把启动相机的逻辑抽成单独方法 private void launchCamera() { Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); name = System.currentTimeMillis(); File imageFile = new File(G.appadress + "/" + name + ".jpg"); intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(imageFile)); startActivityForResult(intent, take); }
2. 路径兼容性问题(Android Q+)
你用的Environment.getExternalStorageDirectory()在Android Q(API 29)及以上已经被废弃,而且直接存到根目录可能会因为存储策略变更导致无法访问。建议改用应用专属的外部存储路径:
修改G类的路径:
public class G extends Application { public static Context context; // 改用应用专属外部存储目录,无需额外权限(Android Q+) public static String appadress; @Override public void onCreate() { super.onCreate(); context = getApplicationContext(); // 获取应用专属的外部存储图片目录 appadress = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES).getAbsolutePath(); File file = new File(appadress); if (!file.exists()) { file.mkdirs(); } } }
这个路径属于应用私有,Android Q+不需要读写权限,也不会因为系统存储变更导致访问失败。
3. onActivityResult的逻辑漏洞
你没有判断resultCode == RESULT_OK,如果用户取消拍照,name对应的文件可能不存在,解码Bitmap会返回null,导致ImageView无显示。另外要处理Bitmap解码失败的情况:
修复onActivityResult:
@Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { case take: // 先判断拍照是否成功 if (resultCode == RESULT_OK) { String imagePath = G.appadress + "/" + name + ".jpg"; File imageFile = new File(imagePath); if (imageFile.exists()) { // 用Options优化Bitmap加载,避免OOM BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 2; // 缩小一半加载,根据需求调整 Bitmap bitmap = BitmapFactory.decodeFile(imagePath, options); if (bitmap != null) { imgpic.setImageBitmap(bitmap); } else { Toast.makeText(this, "图片解码失败", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(this, "照片未保存成功", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(this, "已取消拍照", Toast.LENGTH_SHORT).show(); } break; } }
4. Android 7.0+的FileUriExposedException
如果你的targetSdkVersion >=24,直接用Uri.fromFile()会抛出这个异常,需要用FileProvider来生成Uri:
步骤:
- 在Manifest里注册FileProvider:
<application ...> <provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.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="my_images" path="Pictures" /> </paths>
- 修改launchCamera里的Uri生成:
private void launchCamera() { Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); name = System.currentTimeMillis(); File imageFile = new File(G.appadress + "/" + name + ".jpg"); // 用FileProvider生成Uri Uri imageUri = FileProvider.getUriForFile(this, getPackageName() + ".fileprovider", imageFile); intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); // 授予临时权限 intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); startActivityForResult(intent, take); }
把这些点都修复后,应该就能正常显示拍照后的图片了。
内容的提问来源于stack exchange,提问作者reza motahari




