Android Q (10) запрашивает разрешение на доступ ко всему хранилищу. Объем хранения

В приложениях 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 и с выделенным основным хранилищем нажимает в разрешении garant. "Это позволит - имя приложения - получить полный доступ ко всем файлам, которые в данный момент хранятся в этом месте, и к любому будущему содержимому, хранящемуся здесь"

Затем:

@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);

                }

            }
    }
}

Журнал:

takePersistableUriPermission: 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"/>

Приобретено пользователем.

5 ответов

В Android Q. Если вы даете разрешение, и оно предоставлено или не работает, перейдите в Manifest и добавьте

<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>

Вы должны добавить эту строку в свой AndroidManifest.xml

android:requestLegacyExternalStorage="true"

Проблема заключалась в том, что я использую объект File для доступа к файлам, но разрешение работает, только если мы используем объект DocumentFile для манипулирования файлами.

Решено с использованием DocumentFile вместо File.

Он имеет несколько отрицательных моментов для использования DocumentFile, таких как производительность, и то, что у вас нет доступа к библиотекам Apache Commons, например, но другого варианта нет.

добавьте это в свой файл манифеста в приложении, чтобы ваше приложение выглядело следующим образом:

      <application
    android:requestLegacyExternalStorage="true"

Это может быть проще с 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"в файл манифеста.

Другие вопросы по тегам