Android 12 及更高版本对SD卡访问权限的限制解决方案

19次阅读
没有评论

问题描述

在尝试为应用程序授予访问SD卡的权限时遇到了问题。当尝试选择SD卡的根目录时,系统会显示“为了保护您的隐私,请选择另一个文件夹”的提示。即使之前能够创建和删除文件夹,但在几个月后再次尝试时,却出现了这个问题。

解决方案

方案1:遵循官方指南

由于Android 11及更高版本对SD卡访问权限进行了严格限制,无法直接请求访问SD卡的根目录。根据官方文档,应用程序只能访问其应用数据目录或用户指定的文件夹。

步骤:

  1. 了解限制:确认Android 12及更高版本不再允许直接访问SD卡的根目录。
  2. 请求特定目录访问权限:在应用程序中,仅请求访问应用数据目录或其他用户选择的文件夹。避免请求访问整个SD卡。
  3. 适配代码:修改应用程序代码,以符合新的权限请求规范。

示例代码:

// 请求存储权限
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
        != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions(this,
            new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
            MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE);
}

方案2:使用文件提供者

对于需要访问特定文件的应用程序,可以考虑使用文件提供者(FileProvider)来共享文件路径,从而绕过根目录访问的限制。

步骤:

  1. 配置FileProvider:在AndroidManifest.xml中配置FileProvider
  2. 请求文件路径:使用FileProvider.getUriForFile()方法获取文件路径。
  3. 传递给应用程序:将获取到的URI传递给需要访问文件的应用程序。

示例配置:

<!-- AndroidManifest.xml -->
<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="${applicationId}.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths"/>
</provider>

示例代码:

// 获取文件路径
File file = new File("/path/to/file");
Uri fileUri = FileProvider.getUriForFile(this, "com.example.fileprovider", file);

// 传递给应用程序
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(fileUri, "image/*");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(intent);

方案3:用户界面引导

在应用程序中添加用户界面引导,提示用户选择一个特定的文件夹,而不是直接访问SD卡的根目录。

步骤:

  1. 设计界面:设计一个界面,让用户选择一个文件夹。
  2. 请求权限:在用户选择文件夹后,请求对该文件夹的访问权限。
  3. 处理结果:根据用户的输入,适当地处理权限请求结果。

示例界面:

<!-- activity_main.xml -->
<Button
    android:id="@+id/select_folder_button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="选择文件夹"/>

<ListView
    android:id="@+id/folder_list"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>

示例代码:

// 处理按钮点击事件
Button button = findViewById(R.id.select_folder_button);
button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
        startActivityForResult(intent, REQUEST_CODE_SELECT_FOLDER);
    }
});

以上方案均基于当前Android系统的权限管理策略,建议按照官方文档进行适配和调整,以确保应用程序能够正常运行并符合最新的安全要求。

正文完