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

Потом:

@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"/>

Предоставлено пользователем.


person user2983041    schedule 11.08.2019    source источник
comment
Я не думаю, что у вас может быть root-доступ в Android Q   -  person Gaurav Mall    schedule 11.08.2019
comment
Некоторые приложения, которые я тестировал, имеют такой доступ с ограниченным хранилищем. Например, приложение Solid explorer.   -  person user2983041    schedule 11.08.2019
comment
Да, я знаю. Я задал аналогичный вопрос, и CommonWare сказала мне, что это из-за инженеров этих компаний. Я знаю, его ответ не был таким уж полезным.   -  person Gaurav Mall    schedule 11.08.2019
comment
что вы имеете в виду под root-доступом?   -  person greywolf82    schedule 11.08.2019
comment
Доступ к файлам хранилища устройства. Те же файлы, которые показывают предустановленное приложение проводника файлов по умолчанию. Я не говорю о системных корневых файлах. Корневой каталог подключенных устройств, внешней SD-карты и внутреннего хранилища.   -  person user2983041    schedule 11.08.2019
comment
Вы можете это сделать, но вы не указали в вопросе, как вы пытаетесь открыть рут. Вы можете использовать класс DocumentFile, а затем использовать файлы списков.   -  person greywolf82    schedule 14.08.2019


Ответы (5)


Добавить строку в манифесте

<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>
person D_K    schedule 20.02.2020
comment
Работал как шарм! - person Mohd Zaid; 11.05.2020
comment
Это временно, см. developer.android. ru / training / data-storage / - person dominikkv; 09.06.2020
comment
Что ж, это стоило мне 3 часов моей жизни ... Спасибо, D_K - person Simon Corcos; 31.08.2020
comment
В android 11 больше работать не будет. Итак, как мы можем получить доступ к полному доступу к хранилищу и на Android 11? любая идея? - person Chirag Prajapati; 22.01.2021
comment
Вы должны использовать MediaStore для Android 11 или более поздней версии. Обратите внимание на следующее: developer.android. ru / training / data-storage / варианты использования - person D_K; 22.01.2021

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

android:requestLegacyExternalStorage="true"
person tohid hajimorad    schedule 30.07.2020

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

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

У него есть несколько отрицательных моментов в использовании DocumentFile, таких как производительность и то, что у вас нет доступа, например, к общедоступным библиотекам apache, но другого варианта нет.

person user2983041    schedule 14.08.2019
comment
File (path), file.delete (), mkdirs () не работает на android Q? Что изменится при ограниченном хранилище? - person Aswin P Ashok; 14.08.2019
comment
Существуют библиотеки для java, которые вы можете копировать, вырезать или заархивировать, например, в объектах File. Эти библиотеки не существуют для DocumentFile. - person user2983041; 15.08.2019
comment
File API недоступен в Android 10 для файлов в общем хранилище, которые не принадлежат вашему приложению. developer.android.com/training/data-storage/ общий / - person M. Reza Nasirloo; 16.06.2021

(НЕ РАБОТАЕТ НА 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/

person Mehran Sahandi Far    schedule 26.02.2021

Это могло быть проще с Простым хранилищем. Вы можете запросить у пользователя полный доступ к хранилищу:

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" в файл манифеста.

person Anggrayudi H    schedule 17.07.2021