You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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:

步骤:

  1. 在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>
  1. 在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>
  1. 修改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

火山引擎 最新活动