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
相关产品推荐
相关产品推荐

