What is external sd card android

Хранение данных и файлов

В целом хранение файлов и данных можно условно разделить на две группы: во внутреннем или внешнем хранилище. Но разница между ними довольна тонка. В целом политика Гугла в отношение данных ужесточается с каждой версии системы.

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 студии.

Читайте также:  Switch emulator android apk

Что делать?

Пользуйтесь методами класса 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» (см. выше).

Источник

Использование карты памяти /sdcard/ приложениями в Android

Друзья, поклонники зеленых роботов, разработчики приложений, просто пользователи:
как Вы используете карту памяти /sdcard/ в Вашем Android-девайсе?

Рассмотрим, для начала данный вопрос на примере большинства рядовых пользователей устройства под управлением ОС Андроид:

Как и многие, я устанавливаю приложения на карту памяти — для экономии места в самом телефоне, но сами приложения, их кеши и т.д. — все это сохраняется прямо в корень карты памяти, в итоге я получаю на карте полную «кашу»:
огромное количество папок и т.д. среди которых достаточно неудобно (как через ФМ так и при подключении к ПК) искать нужные мне файлы, папки и т.д. Понятно, что можно обойтись костылями и, например, добавить мои папки в «избранное» в том же ФМ и т.д., но вопрос в другом.
Почему изначально большинство приложений устанавливаются на карту памяти так:

или, например, так:

или на худой конец — есть же скрытая системная
/sdcard/.android_secure
(понятно, что туда не всегда есть доступ и т.д., но все таки)

В итоге: что же получает юзер?
Среднестатистический юзер устанавливает достаточно много приложений и, зачастую, для экономии места, перемещает их на карту памяти. Все хорошо, но до того момента, когда нам вдруг понадобилось найти свой собственные документы на карте памяти, тут мы подключаем девайс с ПК в режиме карты памяти или же через ФМ самого смартфона заходим сюда: /sdcard/
И что же мы видим?
Да вот что:
habrastorage.org/storage1/e5deae9f/54a3c20b/8ba76329/55414a1a.jpg

Напрашивается, закономерный вопрос: почему так?
Насколько я понимаю, причины две:
1) это сама компания google, точнее ее политика в отношении это аспекта, то есть действия разработчиков программ никак тут не ограничены (тем же условием опубликования программы на market’e и т.д.)
2) разработчики программ, которые пишут софт, зачастую, создающий массу папок в корне /sdcard/

Ну и для любопытства ради воспользуемся любимым поиском:
habrahabr.ru/blogs/android_development/111868
Например тут указан некий Стандарт разработки приложений под Android
из которого четко следует:
Корневой каталог для всех файлов пользователя, кроме временных:
/sdcard/название проекта/, например /sdcard/TalentMania/

Каталог для музыки:
/sdcard/название проекта/sound/, например /sdcard/TalentMania/sound/
Каталог для MIDI:
/sdcard/название проекта/midi/, например /sdcard/TalentMania/midi/
Каталог для графики:
/sdcard/название проекта/img/, например /sdcard/TalentMania/img/

Подкаталоги для файлов различных активити:
/sdcard/название проекта/img/название активити/, например /sdcard/TalentMania/img/guitar/

И т.д.
Никаких претензий я разработчикам или вообще кому либо не предъявляю.
Просто хочу задать два вопроса:
1) Почему так? Почему все «сваливается» в корень карты памяти?
2) Одному мне это чертовски неудобно?

Спасибо за внимание!

PS: а пока юзеры выдают просто шедевральные методы облегчения использвания карты памяти:
открываешь карту памяти и создаешь
_Видео
_Документы
_Музыка
_Прочее
|-Карты
|-и т.д.
_Фото
как результат, то что мне нужно, хотя бы всегда сверху
как в телефоне
так и на ПК

Источник

Получение пути к карте памяти SD Card на Android

Разрабатывая приложение для проведения соревнований, я столкнулся с проблемой хранения базы данных. Проблема состояла в том, как мне определить внешнюю карту памяти. В целом поиск в сети точного ответа не дал. Поэтому, объединив все найденные результаты, я собрал свой класс. Если кому интересно, смотрим под катом.

Итак, начнем с теории.

Терминология

Гугл нам говорит, что есть следующие понятия:

  1. Внутренняя (internal) память — это часть встроенной в телефон карты памяти. При ее использовании по умолчанию папка приложения защищена от доступа других приложений (Using the Internal Storage).
  2. Внешняя (external) память — это общее «внешнее хранилище», т.е. это может быть как часть встроенной памяти, так и удаляемое устройство. Обычно это часть встроенной памяти, как удаляемое устройство я видел в последний раз на андройде 2.2, где встроенная память была около 2Гб, и подключаемая память становилась внешней (Using the External Storage).
  3. Удаляемая (removable) память — все хранилища, которые могут быть удалены из устройства без «хирургических» вмешательств.
Читайте также:  Android layout width max width

До версии KitKat 4.4 API не предоставляло функционала для получения путей к внешней памяти. Начиная с этой версии (API 19) появилась функция public abstract File[] getExternalFilesDirs (String type), которая возвращает массив строк с путями к внутренней и внешней памяти. Но как же быть с нашей SD Card, которая вставлена в слот? Путь к ней мы опять не можем получить.

Результаты поиска

Чтобы ответить на поставленный вопрос я обратился к всезнающему гуглу. Но и он мне не дал четкого ответа. Было рассмотрено множество вариантов определения от использования стандартных функций, которые ведут к внешней памяти, но ничего общего с удаляемыми устройствами хранения данных они не имеют, до обработки правил монтирования устройств (Android же на ядре Linux работает). В последних случаях были использованы «зашитые» пути к папке с примонтироваными устройствами (в различных версиях эта директория разная). Не стоит забывать, что от версии к версии правила монтирования меняются.

В конечном итоге я решил объединить все полученные знания и написал свой класс, который может нам вернуть пути к внешним и удаляемым устройствам.

Описание кода

Был создан класс MountDevice, который содержит в себе путь к устройству, тип устройства и некий хэш.
Типов устройств выделено два (внутреннюю память я не стал трогать, так как к ней доступ можно получить через API системы).

И был создан класс StorageHelper, который и осуществляет поиск доступных карт памяти.

В классе StorageHelper реализовано два способа поиска — через системное окружение (Environment) и с использованием утилиты Linux mount, а точнее результата ее выполнения.

Способ первый — Environment

При работе с окружением я использую стандартную функцию getExternalStorageDirectory() для получения информации о внешней памяти. Чтобы получить информацию о удаляемой памяти, я использую переменную окружения «SECONDARY_STORAGE«.

Внешняя память всегда одна и обычно всегда есть, поэтому проверяем ее на читаемость, вычисляем хэш и запоминаем. Удаляемой памяти может быть много, поэтому необходимо полученную строку разбить по разделителю и проверять каждое значение.

Вариант решения взят со stackoverflow. Ответ где-то там внизу.

Способ второй — mount

Так как у меня долго не получалось заставить систему мне сказать путь к удаляемой памяти, я решил искать в сторону примонтированных устройств. В системе есть файлы конфигурации, в которых описаны правила монтирования внешних устройств. Все бы хорошо, но на Android версии 4.* к этому файлу простым смертным доступа нет, поэтому рассматривать этот способ не буду.

Вернемся к утилите mount. При запуске без параметров команда возвращает список смонтированных файловых систем. Удаляемые устройства имеют обычно формат файловой системы FAT, то будем выделять строки, в которых есть характеристика «fat«. Внешняя память будет характеризоваться параметром «fuse«.

Примечание: при использовании такого способа не всегда корректно (скорее всего я что-то не учел) определяются типы смотнтированных устройств. Разницу замечал на разных версиях Android. Поэтому этот способ можно использовать как дополнительный.

Вариант решения взят со stackoverflow. Ответов там несколько примерно одинаковых.

Про дублирование

Многие замечали в директории монтирования устройств такую картину:

И что самое интересно, все это одна и та же внешняя карта памяти. Такое дробление начинается с версии Jelly Bean и сделано это для поддержки многопользовательского режима работы системы. Более подробно тут. И вот, чтобы не получать одну и туже карту памяти как различные устройства, необходим способ определения идентичности. Если бы был доступ к конфигурации монтирования, то и вопросов не было. Но доступа нет. Поэтому я тут подсмотрел решение с расчетом хэша для каждого устройства:

  1. создаем StringBuilder
  2. записываем в него общий размер устройства и размер используемого пространства устройства
  3. обходим содержимое корня устройства
  4. записываем имя каталога
  5. записываем имя файла и размер
  6. вычисляем hash

Пример использования

Заключение

Подробные рассуждения по этому вопросу понимания памяти в Android, некоторые советы можно прочитать тут.

Исходный код всего класса расположен еще нигде не расположен. На днях постараюсь разместить на gitHub.

Источник

Оцените статью