Android11及以上文件读写权限如何申请

发布时间:2022-08-08 14:44:50 作者:iii
来源:亿速云 阅读:773

Android 11及以上文件读写权限如何申请

目录

  1. 引言
  2. Android 11文件权限变化
  3. Scoped Storage简介
  4. 文件读写权限申请流程
  5. 常见问题与解决方案
  6. 最佳实践
  7. 总结

引言

随着Android系统的不断更新,Google对文件系统的访问权限管理也变得越来越严格。特别是在Android 11(API级别30)及以上版本中,引入了Scoped Storage(分区存储)机制,极大地改变了应用程序访问外部存储的方式。本文将详细介绍在Android 11及以上版本中,如何申请文件读写权限,并提供相应的代码示例和最佳实践。

Android 11文件权限变化

在Android 11之前,应用程序可以通过READ_EXTERNAL_STORAGEWRITE_EXTERNAL_STORAGE权限访问整个外部存储空间。然而,这种粗粒度的权限管理方式存在安全隐患,容易导致用户隐私数据泄露。

为了增强用户隐私保护,Android 11引入了Scoped Storage机制,将外部存储空间划分为应用专属存储和共享存储两部分。应用专属存储是每个应用程序私有的存储空间,其他应用程序无法访问;共享存储则是所有应用程序都可以访问的公共存储空间,但访问权限受到严格限制。

Scoped Storage简介

Scoped Storage是Android 10引入的一项新特性,旨在限制应用程序对外部存储空间的访问权限。在Android 11中,Scoped Storage得到了进一步强化,成为默认的存储访问方式。

Scoped Storage的核心思想是将外部存储空间划分为以下几个部分:

  1. 应用专属存储:每个应用程序都有一个私有的存储空间,其他应用程序无法访问。应用专属存储包括内部存储和外部存储中的应用专属目录。
  2. 共享存储:所有应用程序都可以访问的公共存储空间,但访问权限受到严格限制。共享存储包括媒体文件(如图片、视频、音频)和下载文件。

文件读写权限申请流程

在Android 11及以上版本中,应用程序需要根据不同的存储类型申请相应的文件读写权限。以下是详细的申请流程。

4.1 请求存储权限

在Android 11中,应用程序仍然需要请求READ_EXTERNAL_STORAGEWRITE_EXTERNAL_STORAGE权限来访问共享存储空间。然而,这些权限的作用范围已经大大缩小,仅限于访问媒体文件和下载文件。

4.1.1 在AndroidManifest.xml中声明权限

首先,在AndroidManifest.xml文件中声明所需的存储权限:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

4.1.2 运行时请求权限

在Android 6.0(API级别23)及以上版本中,应用程序需要在运行时请求危险权限。以下是如何在运行时请求存储权限的示例代码:

if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
        != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions(this,
            new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
            REQUEST_CODE_STORAGE_PERMISSION);
}

4.2 访问应用专属文件

应用专属文件是每个应用程序私有的存储空间,其他应用程序无法访问。在Android 11中,应用程序无需请求任何权限即可访问自己的应用专属文件。

4.2.1 访问内部存储中的应用专属文件

内部存储中的应用专属文件位于/data/data/<package_name>/files目录下。以下是如何访问内部存储中的应用专属文件的示例代码:

File internalFile = new File(getFilesDir(), "example.txt");
try (FileOutputStream fos = new FileOutputStream(internalFile)) {
    fos.write("Hello, World!".getBytes());
} catch (IOException e) {
    e.printStackTrace();
}

4.2.2 访问外部存储中的应用专属文件

外部存储中的应用专属文件位于/storage/emulated/0/Android/data/<package_name>/files目录下。以下是如何访问外部存储中的应用专属文件的示例代码:

File externalFile = new File(getExternalFilesDir(null), "example.txt");
try (FileOutputStream fos = new FileOutputStream(externalFile)) {
    fos.write("Hello, World!".getBytes());
} catch (IOException e) {
    e.printStackTrace();
}

4.3 访问共享存储空间

共享存储空间是所有应用程序都可以访问的公共存储空间,但访问权限受到严格限制。在Android 11中,应用程序需要请求READ_EXTERNAL_STORAGEWRITE_EXTERNAL_STORAGE权限来访问共享存储空间。

4.3.1 访问媒体文件

媒体文件包括图片、视频和音频文件,存储在共享存储空间的PicturesMoviesMusic目录下。以下是如何访问媒体文件的示例代码:

if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
        == PackageManager.PERMISSION_GRANTED) {
    ContentResolver resolver = getContentResolver();
    Uri uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
    Cursor cursor = resolver.query(uri, null, null, null, null);
    if (cursor != null) {
        while (cursor.moveToNext()) {
            String displayName = cursor.getString(
                    cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME));
            Log.d("MediaFile", displayName);
        }
        cursor.close();
    }
}

4.3.2 访问下载文件

下载文件存储在共享存储空间的Download目录下。以下是如何访问下载文件的示例代码:

if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
        == PackageManager.PERMISSION_GRANTED) {
    ContentResolver resolver = getContentResolver();
    Uri uri = MediaStore.Downloads.EXTERNAL_CONTENT_URI;
    Cursor cursor = resolver.query(uri, null, null, null, null);
    if (cursor != null) {
        while (cursor.moveToNext()) {
            String displayName = cursor.getString(
                    cursor.getColumnIndex(MediaStore.Downloads.DISPLAY_NAME));
            Log.d("DownloadFile", displayName);
        }
        cursor.close();
    }
}

4.4 访问媒体文件

在Android 11中,应用程序可以通过MediaStore API访问媒体文件。以下是如何使用MediaStore API访问媒体文件的示例代码:

ContentResolver resolver = getContentResolver();
Uri uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
Cursor cursor = resolver.query(uri, null, null, null, null);
if (cursor != null) {
    while (cursor.moveToNext()) {
        String displayName = cursor.getString(
                cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME));
        Log.d("MediaFile", displayName);
    }
    cursor.close();
}

4.5 访问下载文件

在Android 11中,应用程序可以通过MediaStore API访问下载文件。以下是如何使用MediaStore API访问下载文件的示例代码:

ContentResolver resolver = getContentResolver();
Uri uri = MediaStore.Downloads.EXTERNAL_CONTENT_URI;
Cursor cursor = resolver.query(uri, null, null, null, null);
if (cursor != null) {
    while (cursor.moveToNext()) {
        String displayName = cursor.getString(
                cursor.getColumnIndex(MediaStore.Downloads.DISPLAY_NAME));
        Log.d("DownloadFile", displayName);
    }
    cursor.close();
}

常见问题与解决方案

5.1 如何兼容Android 10及以下版本?

在Android 10中,Scoped Storage是可选的,开发者可以通过在AndroidManifest.xml文件中设置requestLegacyExternalStorage属性来禁用Scoped Storage。然而,在Android 11中,Scoped Storage成为默认的存储访问方式,requestLegacyExternalStorage属性不再有效。

为了兼容Android 10及以下版本,开发者可以在AndroidManifest.xml文件中添加以下代码:

<application
    android:requestLegacyExternalStorage="true"
    ... >
    ...
</application>

5.2 如何访问其他应用程序的文件?

在Android 11中,应用程序无法直接访问其他应用程序的文件。如果应用程序需要访问其他应用程序的文件,可以通过ContentProviderFileProvider实现文件共享。

5.3 如何处理权限被拒绝的情况?

如果用户拒绝了存储权限请求,应用程序可以通过ActivityCompat.shouldShowRequestPermissionRationale方法判断是否需要向用户解释权限的重要性。如果需要解释,可以向用户展示一个对话框,说明权限的作用和必要性。

if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_EXTERNAL_STORAGE)) {
    // 向用户解释权限的重要性
    new AlertDialog.Builder(this)
            .setTitle("权限请求")
            .setMessage("我们需要访问存储权限来读取文件")
            .setPositiveButton("确定", (dialog, which) -> {
                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                        REQUEST_CODE_STORAGE_PERMISSION);
            })
            .setNegativeButton("取消", null)
            .show();
} else {
    ActivityCompat.requestPermissions(this,
            new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
            REQUEST_CODE_STORAGE_PERMISSION);
}

最佳实践

6.1 最小化权限请求

为了增强用户隐私保护,应用程序应尽量减少权限请求。只有在必要时才请求存储权限,并确保用户了解权限的作用和必要性。

6.2 使用ContentResolver访问文件

在Android 11中,推荐使用ContentResolverMediaStore API访问共享存储空间中的文件。这种方式更加安全,且符合Scoped Storage的设计理念。

6.3 处理权限被拒绝的情况

如果用户拒绝了存储权限请求,应用程序应优雅地处理这种情况,避免崩溃或功能异常。可以通过提示用户重新授权或提供替代方案来解决问题。

6.4 测试不同Android版本的兼容性

由于Android 11及以上版本的存储权限管理方式发生了较大变化,开发者应确保应用程序在不同Android版本上的兼容性。可以通过在多个Android版本上进行测试,确保应用程序在各种情况下都能正常运行。

总结

Android 11及以上版本的文件读写权限管理方式发生了重大变化,引入了Scoped Storage机制,增强了用户隐私保护。开发者需要了解这些变化,并根据新的权限管理方式调整应用程序的文件访问逻辑。通过合理申请权限、使用ContentResolverMediaStore API访问文件,以及处理权限被拒绝的情况,开发者可以确保应用程序在Android 11及以上版本上正常运行,并提供良好的用户体验。

推荐阅读:
  1. 关于Android的app权限申请问题
  2. linux如何修改文件读写权限?

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

android

上一篇:使用C++实现插件模式时要注意哪些问题

下一篇:JS怎么获取节点并进行兼容性封装

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》