- Хранение данных и файлов
- Внешняя карта памяти
- Состояние на текущий момент
- Что делать?
- Android 11
- Storage в смартфоне — что это и зачем нужно?
- Что такое Internal Storage?
- Что такое External Storage?
- Итоги
- Scoped Storage in Android 10 & Android 11
- What was the problem with earlier storage ?
- This is how it is solved now
- What all permissions app need to access the files from scoped storage?
- Access media files from shared storage | Android Developers
- To provide a more enriched user experience, many apps allow users to contribute and access media that’s available on an…
- Access documents and other files from shared storage
- On devices that run Android 4.4 (API level 19) and higher, your app can interact with a documents provider, including…
- What does it mean for you?
- Microsoft Mobile Engineering
Хранение данных и файлов
В целом хранение файлов и данных можно условно разделить на две группы: во внутреннем или внешнем хранилище. Но разница между ними довольна тонка. В целом политика Гугла в отношение данных ужесточается с каждой версии системы.
Android поддерживает различные варианты хранения данных и файлов.
- Специфичные для приложения файлы. Доступ к файлам имеет только приложение, их создавшее. Файлы могут находиться во внутреннем и внешнем хранилище. У других приложений нет доступа (кроме случаев, когда файлы хранятся на внешнем хранилище). Методы getFilesDir(), getCacheDir(), getExternalFilesDir(), getExternalCacheDir(). Разрешений на доступ не требуется. Файлы удаляются, когда приложение удаляется пользователем.
- Разделяемое хранилище. Приложение может создавать файлы, которыми готово поделиться с другими приложениями — медиафайлы (картинки, видео, аудио), документы. Для медифайлов требуется разрешение READ_EXTERNAL_STORAGE или WRITE_EXTERNAL_STORAGE.
- Настройки. Хранение простых данных по принципу ключ-значение. Доступно внутри приложения. Реализовано через Jetpack Preferences. Настройки удаляются, когда приложение удаляется пользователем.
- Базы данных. Хранение данных в SQLite. На данный момент реализовано через библиотеку Room. Доступ только у родного приложения.
В зависимости от ваших потребностей, нужно выбрать нужный вариант хранения данных.
Следует быть осторожным при работе с внутренним и внешним хранилищем. Внутренне хранилище всегда есть в системе, но оно может быть не слишком большим по объёму. Вдобавок к внутреннему хранилищу, устройство может иметь внешнее хранилище. В старых моделях таким хранилищем выступала съёмная SD-карта. Сейчас чаще используют встроенную и недоступную для извлечения флеш-память. Если ваше приложение слишком большое, можно попросить систему устанавливать программу во внешнее хранилище, указав просьбу в манифесте.
В разных версиях Android требования к разрешению для работы с внешним хранилищем постоянно менялись. На данный момент (Android 10, API 29) требования выглядят следующим образом.
Приложение может иметь доступ к собственным файлам, которые находятся во внешнем хранилище. Также может получить доступ к определённым общим файлам на внешнем хранилище.
Доступ к общим файлам достигается через FileProvider API или контент-провайдеры.
Для просмотра файлов через студию используйте инструмент Device File Explorer.
Внешняя карта памяти
Когда появились первые устройства на Android, то практически у всех были внешние карточки памяти, которые вставлялись в телефон. Обычно там хранили фотки, видео и свои файлы. Всё было понятно — были различные методы для доступа к файловой системе. А потом началась чехарда. В телефонах также была и собственная «внешняя» память. Она вроде как и внешняя, но вставлена на заводе и вытащить её пользователь не мог, т.е. практически внутренняя. Затем пошла мода на телефоны, у которых была только такая внутреннее-внешняя карта. Пользователи поворчали, но привыкли. Сейчас встречаются оба варианта. Как правило, у телефонов с спрятанной картой больше памяти и выше степень водонепроницаемости.
Подобные фокусы с картой породили и другую проблему — Гугл озаботился безопасностью файлов и стала думать, как осложнить жизнь разработчику. С выходом каждой новой версии системы компания то давала добро на полный доступ к карточке, то ограничивала, то давала права с ограничениями, то откатывала свои решения назад. Короче, запутались сами и запутали всех.
Попробуем немного разобраться с этим зоопарком. Но помните, что процесс путаницы продолжается.
При подготовке материала я опирался на письма некоторых читателей сайта, которые присылали свои мысли по этому поводу. Спасибо им за структуризацию материала.
Вот что я (кажется) понял, попытавшись загрузить картинку с внешней SD карточки.
External это не External
«EXTERNAL_STORAGE» называется так не потому, что это внешняя память по отношению к устройству, а потому что она выглядит как внешняя память для компьютера, если устройство подключить кабелем к компьютеру. Причём именно выглядит, потому что обмен идёт по протоколу MTP – устройство только показывает компьютеру список папок и файлов, а при необходимости открыть или скопировать файл он специально загружается на компьютер, в отличие от настоящей флешки, файлы которой становятся файлами в файловой системе самого компьютера. Обмен по MTP позволяет устройству продолжать работать, когда оно подключено к компьютеру.
Emulated это не Emulated
Сначала я пытался прочесть файл с карточки на эмуляторе (из этого так ничего и не вышло). Функция getExternalStorageDirectory() давала мне /storage/emulated/0, и я думал, что «emulated» – это потому что на эмуляторе. Но когда я подцепил реальный планшет, слово «emulated» никуда не исчезло. Я стал рыться в интернете и обнаружил, что «Emulated storage is provided by exposing a portion of internal storage through an emulation layer and has been available since Android 3.0.» – то есть это просто кусок внутренней памяти, которая путём какой-то эмуляции делается доступной для пользователя, в отличие от собственно внутренней памяти.
При этом с точки зрения системы доступная для пользователя папка называется /storage/emulated/0, а при подключении к компьютеру по USB это просто одна из двух главных папок устройства – у меня в Windows Explorer она называется Tablet. Вторая папка у меня называется Card, и это и есть настоящая внешняя карточка.
Нет стандартных средств добраться из приложения до файлов на внешней карточке. Все попытки добраться до настоящей внешней карточки делаются с помощью неких трюков. Самое интересное, что я нашел, это статья на http://futurewithdreams.blogspot.com/2014/01/get-external-sdcard-location-in-android.html — парень читает таблицу смонтированных устройств /proc/mounts, таблицу volume daemons /system/etc/vold.fstab, сравнивает их и выбирает те тома, которые оказываются съёмными (с помощью Environment.isExternalStorageRemovable()).
Оказалось, что несистемным приложениям в принципе запрещено напрямую обращаться к съёмной карточке! Похоже, что это было так всегда, но вот начиная с версии Android 6 Marshmallow написано: внешняя карточка может быть определена как Portable либо Adoptable. Adoptable – это как бы «усыновляемая» память которая может быть «adopted», то есть взята в систему (примерно как кот с улицы в дом – это тоже называется to adopt) и использована как внутренняя. Для этого ее надо особым образом отформатировать и не вынимать, иначе не факт, что система продолжит нормально работать.
Portable – это нормальная съёмная карточка, но несистемным приложениям запрещено обращаться из программ к файлам на ней! Вот что написано в https://source.android.com/devices/storage/traditional.html:
Android 6.0 supports portable storage devices which are only connected to the device for a short period of time, like USB flash drives. When a user inserts a new portable device, the platform shows a notification to let them copy or manage the contents of that device. In Android 6.0, any device that is not adopted is considered portable. Because portable storage is connected for only a short time, the platform avoids heavy operations such as media scanning. Third-party apps must go through the Storage Access Framework to interact with files on portable storage; direct access is explicitly blocked for privacy and security reasons.
Если я правильно понял, этот самый Storage Access Framework позволяет работать с документом на карточке через диалог (открыть файл/сохранить файл), а вот прочитать или записать файл на карточке непосредственно из программы невозможно.
Общий вывод – реально из программы можно работать только с файлами на предоставляемой пользователю части встроенной памяти устройства, а на съёмной карточке – нет.
Это напоминает войну Microsoft с пользователями и разработчиками по поводу диска C:, компания уговаривала не устраивать беспорядок в корне этого диска, а ещё лучше — перенести свои файлы на другой диск. Но явных запретов не было.
Состояние на текущий момент
Гугл утверждает, что с версии Android 10 Q стандартный доступ к файлам будет прекращён. Ещё в Android 4.4 появился Storage Access Framework, который и должен стать заменой для работы с файлами.
Методы Environment.getExternalStorageDirectory() и Environment.getExternalStoragePublicDirectory() признаны устаревшими и будут недоступны. Даже если они будут возвращать корректные значения, ими вы не сможете воспользоваться.
В Android 7.0 добавили исключение FileUriExposedException, чтобы разработчики перестали использовать схему file://Uri.
Можно создавать файлы в корневой папке карточки при помощи Environment.getExternalStorageDirectory(), а также папки с вложенными файлами. Если папка уже существует, то у вас не будет доступа на запись (если это не ваша папка).
Если вы что-то записали, то сможете и прочитать. Чужое читать нельзя.
Кстати, разрешения на чтение и запись файлов не требуются, а READ_EXTERNAL_STORAGE и WRITE_EXTERNAL_STORAGE объявлены устаревшими.
Другие приложения не могут получить доступ к файлам вашего приложения. Файлы, которые вы создали через getExternalFilesDir(), доступны через Storage Access Framework, кроме файлов, созданных в корне карточки (что-то я совсем запутался). Ещё можно дать доступ через FileProvider.
При подключении USB-кабеля через getExternalFilesDir(), вы можете увидеть свои файлы и папки, а также файлы и папки пользователя. При этом файлы и папки пользователя на корневой папке вы не увидите. Вам не поможет даже adb или Device File Explorer студии.
Что делать?
Пользуйтесь методами класса Context, типа getExternalFilesDir(), getExternalCacheDir(), getExternalMediaDirs(), getObbDir() и им подобными, чтобы найти место для записи.
Используйте Storage Access Framework.
Используйте MediaStore для мультимедийных файлов.
Используйте FileProvider, чтобы файлы были видимы другим приложениям через ACTION_VIEW/ACTION_SEND.
Android 10: Появился новый флаг android:allowExternalStorageSandbox=»false» и метод Environment.isExternalStorageSandboxed() для работы с песочницей. Флаг android:requestLegacyExternalStorage=»true» для приложений, которые ещё используют старую модель доступа к файлам.
Как временное решение можно добавить в блок манифеста application атрибут android:requestLegacyExternalStorage=»true», чтобы доступ к файлам был как раньше в Android 4.4-9.0.
Android 11
Если вы создаёте файловый менеджер, то ему нужны возможности для просмотра файлов. Для этого следует установить разрешение MANAGE_EXTERNAL_STORAGE или использовать атрибут android:requestLegacyExternalStorage=»true» (см. выше).
Источник
Storage в смартфоне — что это и зачем нужно?
Какие типы памяти есть в телефонах, и чем отличается Internal Storage от External Storage?
Многие пользователи приложений интересуются — где хранятся создаваемые файлы? Как их посмотреть? Очищается ли информация после удаления программы? Чтобы разобраться в таких вопросах, обратимся к терминам «Internal Storage» и «External Storage».
Для начала приведем переводы терминов. Storage — место хранения, Internal — внутреннее, External — внешнее. Простыми словами, Storage в широком смысле слова — это память смартфона, в которой хранятся данные.
Что такое Internal Storage?
Internal Storage представляет собой внутреннее хранилище информации, которое есть на каждом телефоне независимо от поддержки карт памяти. Эта область памяти располагается в системном разделе /data и является защищенной. Основное предназначение внутреннего хранилища — обеспечение безопасности пользовательской информации. Таким образом, владелец телефона не может случайно удалить важные файлы, тем самым нарушив функциональность устройства.
После удаления приложения информация автоматически очищается системой. Такая возможность предусмотрена разработчиками операционной системы Android в целях предотвращения засорения памяти. Файлы, хранящиеся в каталоге Internal Storage, просто становятся ненужными, поэтому удаляются вместе с программами и играми.
Что такое External Storage?
Раньше операционная система Android присваивала картам памяти название External Storage (внешнее хранилище). Сейчас его предназначение — хранение доступной пользователю информации. Здесь могут располагаться фотографии, видеозаписи, музыка и другие разновидности информации.
Управлять содержимым хранилища External Storage можно встроенными средствами телефона или любым менеджером файлов. Владелец смартфона может перемешать, переименовывать, копировать, передавать и удалять файлы. Следует заметить, что удаление некоторой информации способно повлиять на работоспособность приложений, поэтому перед каждым действием нужно проверять предназначение файла.
Итоги
Internal Storage — внутреннее хранилище информации для временных файлов приложений. External Storage выполняет аналогичную задачу, позволяя хранить постоянные и временные файлы. Разница между разделами заключается в защищенности.
Источник
Scoped Storage in Android 10 & Android 11
A secure and advanced app storage system for Android.
A controversial storage access change, slated for Android 10, becomes mandatory for Android 11. This blog talks about scoped storage, How we can access it and what does it mean for our app?
Before Android 10, storage was divided into private storage and shared storage. Private storage’s(android/data/
) access and contribution was limited to owner app alone. Apart from private storage, rest of the storage was called shared storage which is where all the media and non-media files were being stored. Any app with storage permission would be able to access this part of storage.
What was the problem with earlier storage ?
Limited access: Most of the apps do not need the access of whole storage since their use case are limited to certain types of files or files they own. One such use case can be a grocery app or an e-commerce app which needs storage access only to ask user to upload their profile picture.
Security: With storage access, an app can access a document as vulnerable as your bank statement or personal files. How would you like that?
Data organisation: Data/Files related to an app was scattered at multiple places in Shared Storage. If you have to uninstall the app and you want to clear all the corresponding data, that would not come easy.
This is how it is solved now
With Android 10, Google started to restructure the storage and change the way app accesses the storage so that all the mentioned problems can be eliminated. This storage division is called scoped storage.
Idea behind scoped storage was to divide whole storage into multiple blocks. An app would be provided access to the storage blocks which has relevant data for the app. In addition, system will bind storage to owner apps so that it becomes easier for the system to locate relevant files, corresponding to an app. This would also help to remove app specific data once app is uninstalled unless user does not want to.
This is how storage is divided now:
This storage remains same as before. Its app’s own private directory (/app/data/
) where app has unlimited access to read and write.
This is further divided into Media and Download collection. Media collection stores Image, Audio and Video files. Download collection would take care of non-media files.
What all permissions app need to access the files from scoped storage?
Earlier there was one permission to read all the files and another to write. Now with scoped storage, access is allotted based upon storage type and the ownership of the content.
1. App will have unlimited access to their internal and external storage for both read & write operation.
2. App will have unrestricted access to contribute files ( Media & Non-Media) as long as the file is stored in organised collection.
3. Media collection contributed by other apps can be accessed using ‘READ_STORAGE_PERMISSION’ permission. ‘WRITE_STORAGE_PERMISSION’ permission will be deprecated from next version and if used, will work same as ‘READ_STORAGE_PERMISSION’.
4. Non Media files contributed by other apps can be accessed using Storage access framework API. No explicit permission is needed. This does not mean that App can get access to all the directories ( Root, android/Data , Download directory etc.). Once user grants access to it, it will be complete access. (Read, Modify, Delete).
This is how we can access non-media Files. Here i am trying to access PDF file.
If App wants to select a custom folder, intent ACTION_OPEN_DOCUMENT can be replaced with ACTION_OPEN_DOCUMENT_TREE. ACTION_OPEN_DOCUMENT_TREE is introduced in android 11. This access will be valid till user reboots device. If app wants to persist the access, while accessing URI using content resolver , content resolver has to call takePersistableUriPermission method.
If App wants to create a file such as an email app saving attachment, intent can be replaced with ACTION_CREATE_DOCUMENT.
Access media files from shared storage | Android Developers
To provide a more enriched user experience, many apps allow users to contribute and access media that’s available on an…
Access documents and other files from shared storage
On devices that run Android 4.4 (API level 19) and higher, your app can interact with a documents provider, including…
Note: Media location is considered sensitive data now and would not be available unless app has ACCESS_MEDIA_LOCATION permission. It’s not a run time permission and has to be included in manifest. However it would be good idea to check this if app highly depends upon metadata or is an enterprise application where admin can remove the permission. If you want exact bytes of stored media, ‘MediaStore.setRequireOriginal(photoUri)’ has to be called.
So now apps can get access to specific block of memory. But what if I am a back up app which needs to access everything?
In Android 10, users tried to access the directories using storage access framework. Storage access framework was not intended for this purpose. Also, User complained about confusing UX. For such apps, a special permission is introduced in android 11. To ask the permission, Apps have to submit a declaration form to Google play. Once user grants the permission to have a broad access then user will get an unfiltered view of MediaStore that include non-media file. However, your app will not have access to external app directories.
Unfiltered view of Mediastore…What if my app uses custom file picker which displays exact data directories?
There is nothing you can do about it. You might want to use system picker from now on.
Alright so till this point we understand the reason behind scoped storage and the permission/methods to access it. Now let’s talk about scoped storage API changes over android 10 & 11.
Scoped storage was introduced in Android 10 but there were some controversial decision which enforced google to make API changes in Android 11.
1. In Android 10 and 11, Scoped storage is default behaviour. However app can request legacy external storage in Android 10 which is not the case in 11. Additionally In Android 10, Apps which wanted broader access, tried to use Storage access framework to select the directories which was not the intended purpose of storage framework. In Android 11, special access permission is introduced. Once Google play white list the app, special permission can be asked to the user.
2. In Android 10, UI for scoped storage permission looked same as earlier android version. So it would be hard for user to know if they are giving access to scoped storage or whole storage. With Android 11, permission UI will be updated so that user can clearly differentiate between different permissions he is providing.
3. In Android 11, Media store has been updated. User can do bulk delete/edit of media files which was not the case in Android 10. Additionally, Copying and Editing of files is possible in 11 but recommended only for one-off edits and small sized files since copying files will clutter user’s disk storage.
4. Android 10 has lack of support for native libraries and file path. This is use-case for apps written in c, c++. This support has been added in Android 11, in-fact this is the only use case where developer is expected to write new code. Under the hood file path api is a proxy to media storage api. so if possible, call media store api directly.
What does it mean for you?
if your app has files stored in Shared storage or outside app directory, you need to move them to app directory if you plan to target android 10 and above. Starting with Android 10 you will lose access to it.
Scoped storage is here to solve long time privacy issue. Although there were lots of controversial decisions and negative feedback in Android 10, It is here to stay. Starting September 2020, apps must target android 10 or later so unless you are an app which does not use storage, it’s recommended to start using scoped storage.
Lastly, thank you for reading the article! Any questions and suggestions are most welcome. See you soon.
Microsoft Mobile Engineering
#Mobile development articles and news brought to you by #MobileDevs working at @Microsoft
Источник