当前位置:   article > 正文

解决各版本安卓读写SD卡的问题-java.io.IOException: Operation not permitted问题(兼容到android13)

java.io.ioexception: operation not permitted

前言:
本文的核心是解决安卓上面读写SD卡目录的问题。

众所周知,安卓上面对于应用来说可以读写的有三块区域:

1.data/data/包名;

2.sdcard/Android/data/包名;

3.sdcard目录。

前两块区域读写一般是没有什么限制的,可以直接读写。但是第三块区域,因为各个APP都可以申请对这块区域进行读写,所以就会很乱,因此安卓也在不断的加强对这块区域管控的力度。

但是我们对SD卡根目录直接读写的需求是一直存在的,所以本文将会记录每个安卓版本对这块权限的变化,以及相对应的解决方案。(持续更新,目前更新到安卓12)

版本适配方案:

1.安卓6.0之前

6.0之前是不需要动态申请权限的,直接在manifest中申请即可以正常使用。

manifest申明:

  1. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. package="com.xt.client">
  4. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  5. ...
  6. </manifest>

代码使用:

  1. private void writeFile() throws IOException {
  2. String absolutePath = Environment.getExternalStorageDirectory().getAbsolutePath();
  3. File file = new File(absolutePath + File.separator + "a.txt");
  4. if (file.exists()) {
  5. file.delete();
  6. ToastUtil.showCenterToast("文件存在,删除成功");
  7. } else {
  8. file.createNewFile();
  9. ToastUtil.showCenterToast("文件不存在,创建成功");
  10. }
  11. }

2.安卓6.0,SDK=23

描述:6.0开始,需要申请读写权限,读和写权限是分开的。

如果申请了写的权限,那么读的权限不需要额外在申请。

解决方案:

1.使用前进行权限检查,如果给予权限则直接使用。

2.如果没有权限,则动态申请权限。

  1. if (ContextCompat.checkSelfPermission(this,Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
  2. requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
  3. }else{
  4. writeFile();
  5. }

在返回的结果里面进行判断,如果给予了权限,则进行写入操作。

  1. @Override
  2. public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
  3. super.onRequestPermissionsResult(requestCode, permissions, grantResults);
  4. if(requestCode==1 && (grantResults[0] == PackageManager.PERMISSION_GRANTED)){
  5. writeFile();
  6. }
  7. }

3.安卓10,SDK=29

安卓10开始,安卓继续加强了限制,如果需要读写SD卡,还需要额外的进行申请requestLegacyExternalStorage申明。

解决方案:

1.targetSdkVersion<29 的应用程序默认带有requestLegacyExternalStorage=true属性。不需要额外处理。

2.targetSdkVersion>=29,需要在manifest的application中进行申请使用,如下:

  1. <application
  2. android:name=".application.DemoApplication"
  3. android:allowBackup="true"
  4. android:icon="@mipmap/ic_launcher"
  5. android:label="@string/app_name"
  6. android:requestLegacyExternalStorage="true"//这一行
  7. android:roundIcon="@mipmap/ic_launcher_round"
  8. android:supportsRtl="true"
  9. tools:ignore="GoogleAppIndexingWarning">
  10. >

安卓10之前的(包含10)都可以使用该方案。

4.安卓11,SDK=30

安卓11的时候继续强化对SD卡读写的管理,引入了MANAGE_EXTERNAL_STORAGE权限,而之前的WRITE_EXTERNAL_STORAGE已经失效了。

并且MANAGE_EXTERNAL_STORAGE权限只能跳转设置页面申请。

解决方案:

1.判断是否有MANAGE_EXTERNAL_STORAGE权限,如果没有跳转设置界面申请。

2.如果有则直接进行读写

  1. if (sdkInt >= 30) {
  2. if (!Environment.isExternalStorageManager()) {
  3. Intent intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
  4. startActivity(intent);
  5. return;
  6. }
  7. writeFile();
  8. return;
  9. }

目前11,12的设备上都验证通过。

流程5.安卓13,SDK=33

android13上,取消了android.permission.WRITE_EXTERNAL_STORAGE权限,所以只需要申请android.permission.MANAGE_EXTERNAL_STORAGE权限就可以了。

所以,代码上和流程4一样,不要申请WRITE_EXTERNAL_STORAGE权限即可。


————————————————
版权声明:本文为CSDN博主「失落夏天」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/rzleilei/article/details/122700219

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/465975
推荐阅读
相关标签
  

闽ICP备14008679号