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

Android拍照后ImageView无法显示原图且旋转功能触发权限异常求助

解决相机拍照后图片旋转及权限异常问题

你好!我来帮你一步步解决这个问题,核心要处理两个关键点:存储权限被拒绝和图片方向获取逻辑不准确:


1. 先解决SecurityException权限问题

报错信息明确提示需要READ_EXTERNAL_STORAGE权限,在Android 6.0(API级别23)及以上系统中,这类危险权限不能只在清单文件里声明,必须动态向用户申请。

步骤1:在AndroidManifest.xml添加静态权限声明

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- 如果需要保存图片到外部存储,补充下面的权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" />

步骤2:在Activity中动态申请权限

在打开相机前先检查并申请权限:

image.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        // 检查存储权限是否已授予
        if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {
            // 向用户申请权限
            ActivityCompat.requestPermissions(MainActivity.this,
                    new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                    100); // 自定义权限请求码
        } else {
            // 权限已通过,直接打开相机
            openCamera();
        }
    }
});

// 处理权限申请结果
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == 100) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            openCamera();
        } else {
            Toast.makeText(this, "需要存储权限才能正常处理图片", Toast.LENGTH_SHORT).show();
        }
    }
}

// 封装打开相机的方法
private void openCamera() {
    Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
    startActivityForResult(intent, 101);
}

2. 优化图片方向获取逻辑(关键修复!)

你当前的getImageOrientation()方法是查询整个媒体库中最新的图片,这非常不可靠——如果用户拍照前刚拍过其他照片,拿到的会是旧照片的方向,这也是你需要读取外部存储权限的原因之一。

正确的做法是通过拍摄得到的图片Uri直接查询它的方向,既准确又避免不必要的全局查询:

private int getImageOrientation(Uri imageUri) {
    int orientation = 0;
    Cursor cursor = getContentResolver().query(imageUri,
            new String[]{MediaStore.Images.ImageColumns.ORIENTATION},
            null, null, null);
    
    if (cursor != null && cursor.moveToFirst()) {
        orientation = cursor.getInt(cursor.getColumnIndex(MediaStore.Images.ImageColumns.ORIENTATION));
        cursor.close();
    }
    return orientation;
}

然后在onActivityResult中调用这个方法时,传入拍摄得到的selectedImage:

// 替换原来的getImageOrientation()调用
int orientation = getImageOrientation(selectedImage);
if (orientation != 0) { // 只有方向不为0时才旋转
    bitmapRotate = rotateImage(bitmap, orientation);
    bitmap.recycle(); // 回收原Bitmap避免内存泄漏
} else {
    bitmapRotate = bitmap;
}

3. 额外的优化建议

  • 避免内存泄漏:旋转后要及时回收无用的Bitmap,但注意不要回收正在使用的Bitmap(比如bitmapRotate等于bitmap时就不能回收)。
  • 适配新版本API:startActivityForResult已被废弃,推荐使用registerForActivityResult(如果项目用AndroidX库的话)。
  • 图片压缩处理:相机拍摄的原图分辨率很高,直接加载容易导致OOM,建议压缩后再显示和保存。

这样修改后,权限问题会得到解决,图片方向也能准确修正,ImageView就能正常显示拍摄的图片了。

内容的提问来源于stack exchange,提问作者Arpan Sarkar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:21:20