Android11存储机制更新

Android10以及以上的版本提供了分区存储机制,为了让用户更好地管理自己的文件并减少混乱,此类应用只能访问外部存储空间上的应用专属目录,以及本应用所创建的特定类型的媒体文件。简单解释就是:Android 10 开启分区存储后,应用在有权限的情况下也无法随便访问其他外部存储空间中的公有文件夹了,应该怎么办呢?

不同版本不同方式

根据应用在哪个 Android 版本上运行来纳入逻辑。

Android 11

使用 MediaStore.createWriteRequest() 或 MediaStore.createTrashRequest() 为应用的写入或删除请求创建待定 intent,然后通过调用该 intent 提示用户授予修改一组文件的权限。 评估用户的响应:

  • 如果授予了权限,请继续修改或删除操作。
  • 如果未授予权限,请向用户说明您的应用中的功能为何需要该权限。

如需访问系统为您的应用提供的目录,请调用 getExternalFilesDirs()

Android 10

如果您的应用以 Android 10(API 级别 29)为目标平台,请停用分区存储,继续使用适用于 Android 9 及更低版本的方法来执行此操作,设置requestLegacyExternalStorage为true即可。

1requestLegacyExternalStorage = true

<= Android 9

按照请求应用权限中所述的最佳做法,请求 WRITE_EXTERNAL_STORAGE 权限。使用 MediaStore API 修改或删除媒体文件。

常用模板代码

下面是申请存储权限时用到的一些模板代码。

AndroidManifest.xml

 1<?xml version="1.0" encoding="utf-8"?>
 2<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 3    package="">
 4
 5    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
 6    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
 7
 8    <!-- 使用requestLegacyExternalStorage为true关闭分区存储 -->
 9    <application
10        android:requestLegacyExternalStorage="true"
11        android:allowBackup="true"
12        android:icon="@mipmap/ic_launcher"
13        android:label="@string/app_name"
14        android:roundIcon="@mipmap/ic_launcher_round"
15        android:supportsRtl="true"
16        android:theme="@style/Theme.Mp3Encode">
17        <activity android:name=".MainActivity">
18            <intent-filter>
19                <action android:name="android.intent.action.MAIN" />
20                <category android:name="android.intent.category.LAUNCHER" />
21            </intent-filter>
22        </activity>
23    </application>
24
25</manifest>

MainActivity.java

 1public class MainActivity extends AppCompatActivity {
 2    private static final String TAG = "MainActivity";
 3  
 4    // 申请权限请求码
 5    private static final int REQUEST_EXTERNAL_STORAGE = 1001;
 6
 7    @Override
 8    protected void onCreate(Bundle savedInstanceState) {
 9        super.onCreate(savedInstanceState);
10        setContentView(R.layout.activity_main);
11        verifyStoragePermissions(this);
12    }
13
14    // 检查权限
15    public static void verifyStoragePermissions(Activity activity) {
16        int writePermission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
17        int readPermission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.READ_EXTERNAL_STORAGE);
18
19        if (writePermission != PackageManager.PERMISSION_GRANTED
20                || readPermission != PackageManager.PERMISSION_GRANTED) {
21            // 如果没有权限需要动态地去申请权限
22            ActivityCompat.requestPermissions(
23                    activity,
24                    // 权限数组
25                    new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE},
26                    // 权限请求码
27                    REQUEST_EXTERNAL_STORAGE
28            );
29        }
30    }
31  
32  
33    // 如果在申请权限的过程中需要做一些对应的处理,则在此方法中处理
34    @Override
35    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
36        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
37        if(REQUEST_EXTERNAL_STORAGE == requestCode){
38            // TODO ...
39        }
40    }
41}

对,就这么简单~