Доступ к выделенным каталогам

Некоторым приложениям (например, фотоприложениям) обычно требуется доступ только к отдельным каталогам внешнего хранилища, например, к каталогу Pictures. Существующие методы доступа к внешним хранилищам не предназначены для обеспечения приложениям такого типа удобного доступа к выделенным каталогам. Например:

  • Запросы READ_EXTERNAL_STORAGE или WRITE_EXTERNAL_STORAGE в манифесте разрешают доступ ко всем общедоступным каталогам внешнего хранилища, хотя вашему приложению может не требоваться такой уровень доступа.
  • При использовании инфраструктуры Storage Access Framework пользователь обычно выбирает каталоги через системный пользовательский интерфейс, что не требуется, если приложение всегда использует один и тот же внешний каталог.

Android N предоставляет новый упрощенный API для доступа к распространенным каталогам внешнего хранилища.

Доступ к каталогу во внешнем хранилище

Используйте класс StorageManager для получения соответствующего экземпляра StorageVolume. Затем создайте намерение, вызвав метод StorageVolume.createAccessIntent() этого экземпляра. Используйте это намерение для доступа к каталогам внешнего хранилища. Чтобы получить список всех доступных томов, в том числе томов на съемных носителях, используйте StorageManager.getVolumesList().

В следующем фрагменте кода приведен пример того, как открывать каталог Pictures в главном общем хранилище:

StorageManager sm = (StorageManager)getSystemService(Context.STORAGE_SERVICE);
StorageVolume volume = sm.getPrimaryVolume();
Intent intent = volume.createAccessIntent(Environment.DIRECTORY_PICTURES);
startActivityForResult(intent, request_code);

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

Рисунок 1. Приложение запрашивает доступ к каталогу Pictures.

Если пользователь предоставляет доступ, система вызывает переопределенный метод onActivityResult() с кодом результата Activity.RESULT_OK, а также данные намерения, содержащие URI. Используйте предоставленный URI для доступа к данным каталога аналогично использованию URI, возвращаемых Storage Access Framework.

Если пользователь не предоставляет доступ, система вызывает переопределенный метод onActivityResult() с кодом результата Activity.RESULT_CANCELED и отсутствующими данными намерения.

Примечание. При получении доступа к определенному внешнему каталогу приложение также получает доступ к вложенным в него каталогам.

Доступ к каталогу на съемном носителе

Чтобы использовать доступ к выделенным каталогам на съемном носителе, сначала нужно добавить объект BroadcastReceiver, отслеживающий уведомления MEDIA_MOUNTED, например:

<receiver
    android:name=".MediaMountedReceiver"
    android:enabled="true"
    android:exported="true" >
    <intent-filter>
        <action android:name="android.intent.action.MEDIA_MOUNTED" />
        <data android:scheme="file" />
    </intent-filter>
</receiver>

Когда пользователь подключает съемный носитель, например SD-карту, система отправляет уведомление MEDIA_MOUNTED. Это уведомление предоставляет в данных намерения объект StorageVolume, который вы можете использовать для доступа к каталогам на съемном носителе. В следующем примере показано, как осуществляется доступ к каталогу Pictures на съемном носителе:

// BroadcastReceiver has already cached the MEDIA_MOUNTED
// notification Intent in mediaMountedIntent
StorageVolume volume = (StorageVolume)
    mediaMountedIntent.getParcelableExtra(StorageVolume.EXTRA_STORAGE_VOLUME);
volume.createAccessIntent(Environment.DIRECTORY_PICTURES);
startActivityForResult(intent, request_code);

Советы и рекомендации

По возможности оставляйте постоянный URI для доступа к внешнему каталогу, чтобы приложению не приходилось многократно запрашивать у пользователя разрешение на доступ. После предоставления доступа пользователем вызовите метод getContentResolver().takePersistableUriPermssion() для URI доступа к каталогу. Система сохранит постоянный URI и при последующих запросах доступа будет возвращать ответ RESULT_OK. Таким образом, приложение не будет постоянно выводить окно с запросом подтверждения пользователя.

Если пользователь запрещает доступ к внешнему каталогу, не нужно сразу же запрашивать доступ повторно. Пользователю может не понравиться, если приложение будет постоянно настаивать на получении доступа.