Android读取相册图片以及报错java.io.FileNotFoundException: /storage/emulated/0/ (Permission denied)

Android读取相册

读取相册

说明: 方法有许多,我也尝试了许多,但好像就下面这个方法可行,其他的方法也有可能是可以的,毕竟我也是初学者

1. 使用onActivityResult读取图片并保存

虽然已经弃用了,但是应该还能用 (至少我用了貌似没问题) ,别看弃用,但挺管用哈哈 接下来就是看代码吧!
布局就不展示了

	private Uri imageUri;
	private String imagePath;
	btnAlbum.setOnClickListener(v -> {
	            Intent intent = new Intent(Intent.ACTION_PICK,null);
	            intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,"image/*");
	            startActivityForResult(intent,1);
	        });

然后就是重写onActivityResult方法

	@Override
    public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 1 && resultCode == Activity.RESULT_OK && data != null) {
            imageUri = data.getData();
            if (imageUri != null) {
               //把该图片单独保存下,其他地方还要使用
                saveImageToPrivateDirectory(imageUri);
                ivPhoto.setImageURI(Uri.fromFile(new File(imagePath)));
            }
        }
    }

	private void saveImageToPrivateDirectory(Uri imageUri) {
	        try {
	            InputStream inputStream = requireContext().getContentResolver().openInputStream(imageUri);
	            if (inputStream == null) return;
	
	            Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
	            File imageFile = new File(requireContext().getExternalFilesDir(null), "saved_image.jpg");
	
	            FileOutputStream outputStream = new FileOutputStream(imageFile);
	            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
	            outputStream.flush();
	            outputStream.close();
	            inputStream.close();
	
	            imagePath = imageFile.getAbsolutePath();
	            Log.d("TAG", "Image saved to: " + imagePath);
	        } catch (IOException e) {
	            Toast.makeText(requireContext(), "图片保存失败", Toast.LENGTH_SHORT).show();
	        }
	    }
  1. 通过 ContentResolver 使用给定的 imageUri 打开输入流 InputStreamimageUri 是从相册选择的图片的路径。requireContext() 用于获取 Context 对象。

  2. 通过 BitmapFactory.decodeStream() 方法将 InputStream 转换为 Bitmap 对象

  3. File 对象,指定图片的保存路径和文件名。getExternalFilesDir(null) 返回应用的私有外部存储目录路径(该路径在应用卸载时会被系统自动清除)saved_image.jpg 是要保存的图片文件名。

  4. 创建一个 FileOutputStream 对象,关联刚才创建的 imageFile 文件,用于将图片数据写入到该文件中。

  5. Bitmap 对象中的图片数据压缩为 JPEG 格式,并写入到 outputStream 中。100 表示最高质量的压缩,值范围为 0 到 100,其中 100 表示无损压缩。

注: 为什么要使用私有外部存储目录而不使用共有存储目录?

  1. 首先使用共有存储目录需要申请权限才能访问,并且如果是Android 6.0以上需要动态申请,比较麻烦,而且还不一定能行,官方也建议不使用该方法.

官方的解释:

  1. 在API级别29中不赞成使用此方法 (Environment.getExternalStorageDirectory()) 。为了提高用户隐私,不建议直接访问共享/外部存储设备。
  2. 应用程序可以继续访问内容通过迁移到替代品,如存储在私有目录 getExternalFilesDir()
  1. 在 Android 10(API 级别 29)及更高版本中,直接访问外部存储路径 /storage/emulated/0/ 的方式已经被限制。Android 推荐使用应用私有目录来保存文件,这样无需额外的存储权限 (不需要访问权限)

2. 其他地方展示保存后的图片

imageView.setImageBitmap(BitmapFactory.decodeFile(imagePath));

imagePath 是在 saveImageToPrivateDirectory 方法中获得的.

3. 图片展示异常解决办法

1. 路径错误

通过 BitmapFactory.decodeFile(realPath) 来加载图片。如果 realPath 不正确,或者路径对应的文件不存在,图片加载就会失败。

2. 权限问题

AndroidManifest 中添加权限

<uses-feature
        android:name="android.hardware.camera"
        android:required="false" />
<uses-permission android:name="android.permission.CAMERA" />
3. 图片太大

如果图片过大,加载时可能导致内存问题,甚至导致加载失败。
解决办法:

BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2;  // 将图片缩小一半
Bitmap bitmap = BitmapFactory.decodeFile(realPath, options);
ivCommodity.setImageBitmap(bitmap);
4. 报错 java.io.FileNotFoundException: /storage/emulated/0/ (Permission denied)

参考解决办法, 上面的可行代码也使用了该办法

上述问题只是我遇到过的,也可能有其他问题,仅供参考

参考文章

Android 手机存储及路径

FileNotFoundException

  • 21
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值