【问题标题】:Android Q (10) ask permission to get access all storage. Scoped storageAndroid Q (10) 请求访问所有存储的权限。范围存储
【发布时间】:2019-12-18 07:52:22
【问题描述】:

在 Android 10 中,需要访问存储的应用需要请求访问具体路径的权限。但是文件资源管理器等应用程序可以请求访问根存储的权限,并获得对所有存储的读/写权限。这就是我想要做的。

根据 Android,我们必须为此使用 ACTION_OPEN_DOCUMENT_TREE。我遇到的问题是一切似乎都是正确的,但没有授予应用程序权限。

  private void askAndroid10Perm()
    {
        Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
        intent.addFlags(
                Intent.FLAG_GRANT_READ_URI_PERMISSION
                        | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
                        | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
                        | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
        startActivityForResult(intent, REQUEST_CODE_OPEN_DOCUMENT_TREE);
    }

在这里,用户可以看到 Android 文件树,并在选择主存储的情况下,单击以授予权限。 “它将允许 - 应用程序名称 - 完全访问当前存储在此位置下的所有文件,以及存储在此处的任何未来内容”-> 允许

然后:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch (requestCode) {
        case REQUEST_CODE_OPEN_DOCUMENT_TREE:
            if (resultCode == Activity.RESULT_OK) {
                Uri treeUri = data.getData();
                int takeFlags = data.getFlags();
                takeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION |
                        Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {

                    Log.i("TAG", "takePersistableUriPermission: " + treeUri);
                    this.getContentResolver().takePersistableUriPermission(treeUri, takeFlags);

                }

            }
    }
}

日志:

采取PersistableUriPermission: content://com.android.externalstorage.documents/tree/primary%3A

那么应用程序仍然没有访问root的权限。

打开失败:EACCES(权限被拒绝)

我当然有:

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

由用户授予。

【问题讨论】:

  • 我不认为你可以在 Android Q 中拥有 root 访问权限
  • 我测试过的一些应用程序通过范围存储具有此访问权限。例如“Solid explorer”应用。
  • 是的,我知道。我曾问过类似的问题,CommonWare 对我说这是因为那些公司拥有的工程师。我知道,他的回答没那么有用。
  • root 访问是什么意思?
  • 访问设备存储文件。显示默认文件资源管理器预装应用程序的相同文件。我不是在谈论系统根文件。已安装设备、外部 sd 卡和内部存储的根目录。

标签: android android-10.0 scoped-storage


【解决方案1】:

在清单中添加一行

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:requestLegacyExternalStorage="true" //Add this Line
    android:label="@string/app_name">

---------<Activity, Sevices or Recivers>----------

</application>

【讨论】:

【解决方案2】:

您必须在 AndroidManifest.xml 中添加这一行

android:requestLegacyExternalStorage="true"

【讨论】:

    【解决方案3】:

    问题是我使用 File 对象来访问文件,但只有当我们使用 DocumentFile 对象来操作文件时,权限才有效。

    使用 DocumentFile 而不是 File 解决。

    使用 DocumentFile 有多个缺点,例如性能,以及您无权访问 apache 公共库,但没有其他选择。

    【讨论】:

    • File(path)、file.delete()、mkdirs() 不能在 android Q 上运行吗?范围存储有什么变化?
    • 有一些用于 java 的库,例如,您可以在“文件”对象中复制、剪切或压缩目录。 DocumentFile 不存在此库。
    • 文件 API 在 android 10 中不适用于共享存储中不属于您的应用的文件。 developer.android.com/training/data-storage/shared/…
    【解决方案4】:

    使用Simple Storage 可能会更简单。您可以向用户请求存储完全访问权限:

    class MainActivity : AppCompatActivity() {
    
        private val storageHelper = SimpleStorageHelper(this)
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            btnRequestStorageAccess.setOnClickListener {
                storageHelper.requestStorageAccess()
            }
    
            storageHelper.onStorageAccessGranted = { requestCode, root ->
                // do stuff
            }
        }
    }
    

    它适用于 Android 10 及更高版本。无需在清单文件中添加android:requestLegacyExternalStorage="true"

    【讨论】:

      【解决方案5】:

      (不适用于 ANDROID 11)将此添加到应用程序的清单文件中,以便您的应用程序如下所示:

      <application
          android:requestLegacyExternalStorage="true"
      

      对于 android 11 我确实喜欢这个

              ContextWrapper cw = new ContextWrapper(mContext);
      String fullPath =cw.getExternalFilesDir(Environment.DIRECTORY_MUSIC).toString();
      File directory = cw.getExternalFilesDir(Environment.DIRECTORY_MUSIC);
      

      在这里查看https://www.programmersought.com/article/50766505696/

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-04-28
        • 2017-07-26
        • 2015-11-14
        • 1970-01-01
        • 2020-08-27
        • 1970-01-01
        • 2021-01-02
        相关资源
        最近更新 更多