Android - попросить записать в диалог разрешения SD-карты - PullRequest
0 голосов
/ 01 марта 2019

У меня проблемы с получением доступа на запись в корневой каталог SD-карты устройства.Я могу без проблем записать на внутреннюю память устройства и в папку пакета приложения на SD-картеЯ обнаружил, что получить доступ к SD-карте можно с помощью Storage Access Framework, поэтому я посмотрел на другие приложения, чтобы узнать, как они получают доступ к SD-карте, и нашел Total Commander с его аккуратным диалоговым окном разрешения.

write to SD card permission dialog

Как показать такой диалог, потому что я не могу найти примеры?Моя цель - хранить на SD-карте большие файлы, которые остаются после удаления приложения.

Подобные вопросы:

Android (запись на внешнюю SD-карту): java.io.IOException: Разрешение отклонено

Android M для записи на SD-карту - Разрешение отклонено

Разрешение записи SD-карты Android с использованием SAF (Storage Access Framework)

Ответы [ 2 ]

0 голосов
/ 17 мая 2019

К сожалению, использование createAccessIntent устарело в Android Q, и в документации говорится, что если вы используете его в Android Q, оно немедленно вернет RESULT_CANCELED.

Они рекомендуют использоватьнамерение с ACTION_OPEN_DOCUMENT_TREE . Вы можете указать каталог, который он открывает изначально (который поддерживается только в Android O и выше), упрощая его для пользователя, но это все же не очень удобный для пользователя подход.

Мне интересно, есть ли другие удобные решения, о которых кто-нибудь знает?Я не понимаю, почему Android удалил createAccessIntent, так как он кажется наиболее удобным для пользователя способом.

0 голосов
/ 06 марта 2019

Я нашел файловый менеджер с открытым исходным кодом.Посмотрел код и наконец нашел решение.

Работает только на Android N (7.0.0) (api 24) и выше.

Сначала получите корневой путь SD-карты и покажите разрешение пользователядиалоговое окно.

public void takeCardUriPermission(String sdCardRootPath) {
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
            File sdCard = new File(sdCardRootPath);
            StorageManager storageManager = (StorageManager) getSystemService(Context.STORAGE_SERVICE);
            StorageVolume storageVolume = storageManager.getStorageVolume(sdCard);
            Intent intent = storageVolume.createAccessIntent(null);
            try {
                startActivityForResult(intent, 4010);
            } catch (ActivityNotFoundException e) {
            }
        }
    }

Когда пользователь принимает запрос, запускается onActivityResult (), и мы можем сохранить URI из данных намерений

protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == 4010) {

            Uri uri = data.getData();

            grantUriPermission(getPackageName(), uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION |
                    Intent.FLAG_GRANT_READ_URI_PERMISSION);

            final int takeFlags = data.getFlags() & (Intent.FLAG_GRANT_WRITE_URI_PERMISSION |
                    Intent.FLAG_GRANT_READ_URI_PERMISSION);

            getContentResolver().takePersistableUriPermission(uri, takeFlags);
        }
    }

Теперь мы можем извлечь Uri из корня SD-карты и использоватьэто с помощью Storage Access Framework

public Uri getUri() {
        List<UriPermission> persistedUriPermissions = getContentResolver().getPersistedUriPermissions();
        if (persistedUriPermissions.size() > 0) {
            UriPermission uriPermission = persistedUriPermissions.get(0);
            return uriPermission.getUri();
        }
        return null;
    }
...