David Friedman | 8f1f66f | 2016-04-13 18:11:00 -0700 | [diff] [blame] | 1 | page.title=Доступ к выделенным каталогам |
| 2 | page.keywords=preview,sdk,scoped directory access |
| 3 | page.tags=androidn |
| 4 | |
| 5 | @jd:body |
| 6 | |
| 7 | <div id="qv-wrapper"> |
| 8 | <div id="qv"> |
| 9 | <h2>Содержание документа</h2> |
| 10 | <ol> |
| 11 | <li><a href="#accessing">Доступ к каталогу во внешнем хранилище</a></li> |
| 12 | <li><a href="#removable">Доступ к каталогу на съемном носителе</a></li> |
| 13 | <li><a href="#best">Советы и рекомендации</a></li> |
| 14 | </ol> |
| 15 | </div> |
| 16 | </div> |
| 17 | |
| 18 | <p>Некоторым приложениям (например, фотоприложениям) обычно требуется доступ только к отдельным каталогам |
| 19 | внешнего хранилища, например, к каталогу <code>Pictures</code>. Существующие |
| 20 | методы доступа к внешним хранилищам не предназначены для обеспечения приложениям такого типа удобного |
| 21 | доступа к выделенным каталогам. Например:</p> |
| 22 | |
| 23 | <ul> |
| 24 | <li>Запросы {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} |
| 25 | или {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} в манифесте |
| 26 | разрешают доступ ко всем общедоступным каталогам внешнего хранилища, хотя |
| 27 | вашему приложению может не требоваться такой уровень доступа.</li> |
| 28 | <li>При использовании инфраструктуры |
| 29 | <a href="{@docRoot}guide/topics/providers/document-provider.html">Storage |
| 30 | Access Framework</a> пользователь обычно выбирает каталоги через |
| 31 | системный пользовательский интерфейс, что не требуется, если приложение всегда использует один |
| 32 | и тот же внешний каталог.</li> |
| 33 | </ul> |
| 34 | |
| 35 | <p>Android N предоставляет новый упрощенный API для доступа |
| 36 | к распространенным каталогам внешнего хранилища. </p> |
| 37 | |
| 38 | <h2 id="accessing">Доступ к каталогу во внешнем хранилище</h2> |
| 39 | |
| 40 | <p>Используйте класс <code>StorageManager</code> для получения соответствующего экземпляра |
| 41 | <code>StorageVolume</code>. Затем создайте намерение, вызвав метод |
| 42 | <code>StorageVolume.createAccessIntent()</code> этого экземпляра. |
| 43 | Используйте это намерение для доступа к каталогам внешнего хранилища. Чтобы получить список |
| 44 | всех доступных томов, в том числе томов на съемных носителях, используйте |
| 45 | <code>StorageManager.getVolumesList()</code>.</p> |
| 46 | |
| 47 | <p>В следующем фрагменте кода приведен пример того, как открывать каталог |
| 48 | <code>Pictures</code> в главном общем хранилище:</p> |
| 49 | |
| 50 | <pre> |
| 51 | StorageManager sm = (StorageManager)getSystemService(Context.STORAGE_SERVICE); |
| 52 | StorageVolume volume = sm.getPrimaryVolume(); |
| 53 | Intent intent = volume.createAccessIntent(Environment.DIRECTORY_PICTURES); |
| 54 | startActivityForResult(intent, request_code); |
| 55 | </pre> |
| 56 | |
| 57 | <p>Система пытается предоставить доступ к внешнему каталогу и, при необходимости, |
| 58 | запрашивает подтверждение доступа у пользователя с помощью упрощенного пользовательского интерфейса:</p> |
| 59 | |
| 60 | <img src="{@docRoot}preview/images/scoped-folder-access-framed.png" srcset="{@docRoot}preview/images/scoped-folder-access-framed.png 1x, |
| 61 | {@docRoot}preview/images/scoped-folder-access-framed_2x.png 2x" /> |
| 62 | <p class="img-caption"><strong>Рисунок 1.</strong> Приложение запрашивает |
| 63 | доступ к каталогу Pictures.</p> |
| 64 | |
| 65 | <p>Если пользователь предоставляет доступ, система вызывает переопределенный метод |
| 66 | <code>onActivityResult()</code> с кодом результата |
| 67 | <code>Activity.RESULT_OK</code>, а также данные намерения, содержащие URI. Используйте |
| 68 | предоставленный URI для доступа к данным каталога аналогично использованию URI, |
| 69 | возвращаемых |
| 70 | <a href="{@docRoot}guide/topics/providers/document-provider.html">Storage |
| 71 | Access Framework</a>.</p> |
| 72 | |
| 73 | <p>Если пользователь не предоставляет доступ, система вызывает переопределенный метод |
| 74 | <code>onActivityResult()</code> с кодом результата |
| 75 | <code>Activity.RESULT_CANCELED</code> и отсутствующими данными намерения.</p> |
| 76 | |
| 77 | <p class="note"><b>Примечание.</b> При получении доступа к определенному внешнему каталогу |
| 78 | приложение также получает доступ к вложенным в него каталогам.</p> |
| 79 | |
| 80 | <h2 id="removable">Доступ к каталогу на съемном носителе</h2> |
| 81 | |
| 82 | <p>Чтобы использовать доступ к выделенным каталогам на съемном носителе, |
| 83 | сначала нужно добавить объект {@link android.content.BroadcastReceiver}, отслеживающий уведомления |
| 84 | {@link android.os.Environment#MEDIA_MOUNTED}, например:</p> |
| 85 | |
| 86 | <pre> |
| 87 | <receiver |
| 88 | android:name=".MediaMountedReceiver" |
| 89 | android:enabled="true" |
| 90 | android:exported="true" > |
| 91 | <intent-filter> |
| 92 | <action android:name="android.intent.action.MEDIA_MOUNTED" /> |
| 93 | <data android:scheme="file" /> |
| 94 | </intent-filter> |
| 95 | </receiver> |
| 96 | </pre> |
| 97 | |
| 98 | <p>Когда пользователь подключает съемный носитель, например SD-карту, система отправляет уведомление |
| 99 | {@link android.os.Environment#MEDIA_MOUNTED}. Это уведомление |
| 100 | предоставляет в данных намерения объект <code>StorageVolume</code>, который вы можете использовать |
| 101 | для доступа к каталогам на съемном носителе. В следующем примере показано, |
| 102 | как осуществляется доступ к каталогу <code>Pictures</code> на съемном носителе:</p> |
| 103 | |
| 104 | <pre> |
| 105 | // BroadcastReceiver has already cached the MEDIA_MOUNTED |
| 106 | // notification Intent in mediaMountedIntent |
| 107 | StorageVolume volume = (StorageVolume) |
| 108 | mediaMountedIntent.getParcelableExtra(StorageVolume.EXTRA_STORAGE_VOLUME); |
| 109 | volume.createAccessIntent(Environment.DIRECTORY_PICTURES); |
| 110 | startActivityForResult(intent, request_code); |
| 111 | </pre> |
| 112 | |
| 113 | <h2 id="best">Советы и рекомендации</h2> |
| 114 | |
| 115 | <p>По возможности оставляйте постоянный URI для доступа к внешнему каталогу, чтобы приложению не |
Mark Lu | c4a0139 | 2016-07-18 10:42:11 -0700 | [diff] [blame] | 116 | приходилось многократно запрашивать у пользователя разрешение на доступ. После предоставления доступа пользователем вызовите метод |
David Friedman | 8f1f66f | 2016-04-13 18:11:00 -0700 | [diff] [blame] | 117 | <code>getContentResolver().takePersistableUriPermssion()</code> для |
| 118 | URI доступа к каталогу. Система сохранит постоянный URI и при последующих запросах |
| 119 | доступа будет возвращать ответ <code>RESULT_OK</code>. Таким образом, приложение не будет постоянно выводить |
| 120 | окно с запросом подтверждения пользователя.</p> |
| 121 | |
| 122 | <p>Если пользователь запрещает доступ к внешнему каталогу, не нужно сразу |
| 123 | же запрашивать доступ повторно. Пользователю может не понравиться, если приложение будет постоянно настаивать на |
| 124 | получении доступа.</p> |