Как в android принято хранить конфигурацию?
В целом задача выглядит так: хочу сделать «витрину», где будет изображение предмета, его название и цена
Детали: предметов фиксированное количество, т.е. их набор статичен и не меняется. Это предметы из компьютерной игры, соответственно я просто надергал изображений, названия и цену из файлов игры и хочу оформить для себя в виде приложения. Это не какой-то интернет магазин с динамическими ценами, запросами на сервер — все гораздо проще.
Как я планирую сделать:
1. изображения загрузить в качестве ресурсов
2. взять идентификаторы, которые андроид студия присвоит фотографиям
3. создать какой-нибудь файл, где записи будут формата «название, идентификатор, цена»
4. программно обойти записи этого файла и добавить в активити
Если в целом план годный, то меня интересуют такие вопросы по файлу:
1. какой принято использовать формат для таких целей в андроид-разработке — json, xml, мб еще что-то?
2. где именно мне нужно хранить этот файл? Я думаю в ресурсах, но это понятие растяжимое — там есть пакеты values, xml, а может быть такие файлы еще куда-то принято класть. UPD. С момента создания вопроса я узнал, что существуют еще ассеты — возможно это мне лучше подойдет? Т.к. предметы делятся на категории («оружие», «артефакты» и т.д.) и хотелось бы их рассортировать по папкам, а не хранить вперемешку
- Вопрос задан более года назад
- 82 просмотра
Сохраняем настройки

Очень часто требуется сохранить какие-то настройки. Простой пример — девочка с удовольствием пользовалась нашей программой Счётчик ворон и вертела головой в поисках очередной птицы. Но вот незадача — когда девочка вечером закрывала своё приложение, то на следующий день счётчик обнулялся. А так хотелось узнать, сколько ворон можно насчитать за месяц. Но однажды в дождливый осенний день она встретила рыжее чудо. Впрочем, это уже совсем другая история.
Самый простой способ, который приходит в голову — сбросить данные в файл, а при запуске приложения считывать необходимые данные из файла. Второй вариант — работать с базой данных и хранить настройки там.
Рассмотрим сначала второй вариант. Хранить данные в базе данных не всегда оправдано, если данных не слишком много, они простые и нам не нужно анализировать данные на предмет, сколько мышек поймал котик в прошлом году и сколько часов он спал в январе и феврале.
Первый вариант с файлами хорош, например, для сохранения больших текстовых заметок. Естественно, и для простых данных мы тоже можем использовать файлы. Записали что-то в файл, а потом открыли его и считали данные.
На самом деле нет необходимости изобретать свой велосипед и придумывать свою структуру для хранения данных. В Android существует класс SharedPreferences (Общие настройки), разработанный специально для этих целей. Приложение автоматически создаёт файл в своей папке и хранит простые данные в виде «ключ — значение». Весь процесс создания, открытия, чтения файла оптимизирован и избавляет вас от головной боли.
Общие настройки поддерживают базовые типы boolean, String, float, long и int, что делает их идеальным средством для быстрого сохранения значений по умолчанию, переменных экземпляра класса, текущего состояния UI и пользовательских настроек. Они чаще всего используются для обеспечения постоянства данных между пользовательскими сессиями и доступа к ним компонентов приложения.
Сохранение значений параметров
Если у вас сохранился старый проект по подсчёту ворон, то можете снова его открыть и добавить новый код. Либо заново создайте проект по памяти, заодно проверите, как усвоили урок и сможете ли вы самостоятельно создать проект с нуля, не заглядывая на сайт за подсказкой.
Создаём переменную, представляющую экземпляр класса SharedPreferences, который отвечает за работу с настройками:
private lateinit var prefs: SharedPreferences override fun onCreate(savedInstanceState: Bundle?)
Вы передаёте в указанный метод getSharedPreferences() имя вашего файла (файл будет создан автоматически) и стандартное разрешение по умолчанию MODE_PRIVATE — только приложение имеет доступ к настройкам. Если вам необходимо, вы можете создать несколько подобных файлов настроек.
Немного опередим события и представим, что приложение запущено, и мы считаем ворон весь день. Когда мы закрываем приложение, то нам необходимо сохранить информацию в «Общих настройках». Обычно для этих целей используют методы onPause() или onStop().
Чтобы внести изменения в настройки, нужно использовать класс SharedPreferences.Editor. Получить объект Editor можно через вызов метода edit() объекта SharedPreferences. После того, как вы внесли все необходимые изменения, вызовите метод apply(), чтобы изменения вступили в силу.
override fun onPause() < super.onPause() // Запоминаем данные val editor = prefs.edit() editor.putInt(APP_PREFERENCES_COUNTER, counter).apply() >
Теперь при закрытии программы значение счётчика автоматически запишется в файл. При повторном запуске приложения нам уже не нужно инициализировать счётчик со значением 0. Мы можем прочитать сохранённое значение и использовать его для счётчика, чтобы продолжить подсчёт. Сделаем это в методе onResume().
override fun onResume() < super.onResume() if(prefs.contains(APP_PREFERENCES_COUNTER))< // Получаем число из настроек counter = prefs.getInt(APP_PREFERENCES_COUNTER, 0) // Выводим на экран данные из настроек infoTextView.text = "Я насчитал $counter ворон" >>
Мы проверяем сначала наличие ключа APP_PREFERENCES_COUNTER, а затем извлекаем из ключа его значение.
Вот и всё. Небольшие изменения в коде сделали программу продвинутой. Теперь вы можете спокойно закрывать и открывать программу, ваши данные не будут потеряны. При желании вы можете добавить кнопку для сброса счётчика. Это вам в качестве домашнего задания.
В теории показаны дополнительные примеры и даны подробные сведения об использовании «Общих настроек». Вам следует хорошенько разобраться в этом механизме, так как он часто используется на практике. Более того, некоторые программисты предпочитают использовать «Общие настройки» вместо базы данных, если это позволяет логика программы, так как это работает быстрее и потребляет меньше ресурсов. Выбор за вами.
Вместо послесловия
Не волнуйтесь, с котёнком всё в порядке. Девочка подобрала его и принесла домой. И добрая девочка по-прежнему пользуется нашей программой «Счётчик ворон». Наверное, биологом станет или ветеринаром.
При написании статьи использовались иллюстрации Рины З..
Исходный код (Kotlin)
Код класса активности.
// Если этот код работает, его написал Александр Климов, // а если нет, то не знаю, кто его писал. package ru.alexanderklimov.counter import android.content.Context import android.content.SharedPreferences import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import kotlinx.android.synthetic.main.activity_main.* class MainActivity : AppCompatActivity() < private lateinit var prefs: SharedPreferences private val APP_PREFERENCES_COUNTER = "counter" private var counter: Int = 0 override fun onCreate(savedInstanceState: Bundle?) < super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) prefs = getSharedPreferences("settings", Context.MODE_PRIVATE) crowButton.setOnClickListener < counter = ++counter infoTextView.text = "Я насчитал $counter ворон" >> override fun onPause() < super.onPause() // Запоминаем данные val editor = prefs.edit() editor.putInt(APP_PREFERENCES_COUNTER, counter).apply() >override fun onResume() < super.onResume() if(prefs.contains(APP_PREFERENCES_COUNTER))< // Получаем число из настроек counter = prefs.getInt(APP_PREFERENCES_COUNTER, 0) // Выводим на экран данные из настроек infoTextView.text = "Я насчитал $counter ворон" >> >
Исходный код (Java)
Код класса активности
// Если этот код работает, его написал Александр Климов, // а если нет, то не знаю, кто его писал. package ru.alexanderklimov.counter; import android.content.Context; import android.content.SharedPreferences; import android.support.v7.app.ActionBarActivity; import android.os.Bundle; import android.view.View; import android.widget.TextView; public class MainActivity extends ActionBarActivity < private int mCounter; private TextView mInfoTextView; // имя файла настройки public static final String APP_PREFERENCES = "mysettings"; public static final String APP_PREFERENCES_COUNTER = "counter"; private SharedPreferences mSettings; public void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mSettings = getSharedPreferences(APP_PREFERENCES, Context.MODE_PRIVATE); mInfoTextView = (TextView) findViewById(R.id.textViewInfo); >public void onClick(View v) < // Выводим на экран mInfoTextView.setText("Я насчитал " + ++mCounter + " ворон"); >@Override protected void onResume() < super.onResume(); if (mSettings.contains(APP_PREFERENCES_COUNTER)) < // Получаем число из настроек mCounter = mSettings.getInt(APP_PREFERENCES_COUNTER, 0); // Выводим на экран данные из настроек mInfoTextView.setText("Я насчитал " + mCounter + " ворон"); >> @Override protected void onPause() < super.onPause(); // Запоминаем данные SharedPreferences.Editor editor = mSettings.edit(); editor.putInt(APP_PREFERENCES_COUNTER, mCounter); editor.apply(); >>
Хранение данных и файлов
Устройство на Android содержит в себе набор приложений.

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

Приложение может также иметь собственные документы, картинки, музыку. Они занимают больше места, поэтому для приложения выделяется место во внешнем хранилище. Но доступ к файлам остаётся прежним — только самому приложению.

При деинсталляции приложения все файлы из хранилищ будут удалены.
Но изолированные файлы не всегда удобны для пользователя. Ведь мы хотим взаимодействовать с ними. Например, поделиться фотографией своего кота через месседжер. Поэтому на устройстве есть особое хранилище — Shared storage (разделяемое хранилище).

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» (см. выше).
Хранение данных, файлов в Android
Разработчики Android имеют различные возможности хранения данных приложения локально. Сюда следует отнести, прежде всего, настройки приложения. Кроме этого, можно использовать внутренние и внешние хранилища (файлы). Также данные можно хранить в БД (базе данных) типа SQLite, либо в сторонних базах данных, которые предлагают поддержку NoSQL.
Настройки приложения
К настройкам приложения в первую очередь следует отнести простые данные в формате ключ-значение. Объем таких данных незначителен и включает обозримое количество строк. Для доступа к этим данным можно использовать меню настроек приложения. Это достаточно хорошая идея хранить «под рукой» логические флаги, короткие строки, целые и вещественные числа для настройки интерфейса и бизнес-логики приложения.
Для программного доступа к настройкам используются методы :
- getPreferences() — метод активности для доступа к настройкам активности;
- getSharedPreferences() — метод активности для доступа к настройкам на уровне приложения;
- getDefaultSharedPreferences() — метод класса PreferencesManager для доступа к настройкам, предоставляемым Android.
Все эти методы возвращают объект типа SharedPreferences, который может быть использован как для чтения, так и для записи в файл настроек. Чтобы сохранить одну или несколько записей в файл настроек, необходимо получить SharedPreferences.Editor вызовом метода edit объекта SharedPreferences. Пример :
SharedPreferences prefer; SharedPreferences.Editor editor; prefer = getSharedPreferences(); editor = prefer.edit();
Сохранение настроек
Объект SharedPreferences.Editor имеет несколько интуитивно-понятных методов записи, которые позволяют сохранять данные настроек приложения. Например, методом putInt(key, int) можно поместить пару ключ-значение со значением типа Integer в файл настроек. Аналогично с использованием метода putFloat(key, float) сохраняется пара ключ-значение типа float. Функцию, выполняющую методом putString(key, String), можно не комментировать. После добавления одного или нескольких значений необходимо вызвать метод commit. В следующем примере в настройках сохраняются пары ключ-значение :
editor.putString ("Background", "Yellow"); editor.putInt ("Timeout" , 30 ); editor.putBoolean("Photo" , false ); editor.putBoolean("Video" , true ); editor.commit();
Чтение настроек
Для чтения пары ключ-значение необходимо использовать метод getXXX(param, default) объекта SharedPreferences, где XXX определяет тип данных. В следующем коде извлекаются все значение, добавленные на предыдущем шаге :
String background = prefer.getString ("Background", "white"); int timeout = prefer.getInt ("Timeout" , 15 ); boolean photo = prefer.gutBoolean("Photo" , false );
Вторым параметром всех методов getXXX(param, default) определяется значение по-умолчанию, если ключ не найден в файле настроек.
Таким образом, в файле настроек можно сохранить примитивные данные в формате ключ-значения. Если необходимо сохранить более сложные типы данных или двоичные данные, можно выбрать другой вариант хранения, либо использовать тип String с предварительной (при сохранении) и/или последующей (при чтении) обработкой текстовой строки.
Для удаления настроек используйте метод deleteSharedPreferences.
boolean deleteSharedPreferences (String name);
Пример использования SharedPreference представлен на странице Хранение данных, файлов в Android
Внутренние и внешние хранилища файлов
Ниже представлено описание методов использования внутреннего и внешнего хранилища файлов. Пример использования хранилищ файлов в Android приложениях представлен здесь.
Внутреннее хранилище
Каждое приложение Android имеет свой собственный внутренний каталог хранения, в котором можно хранить текстовые и двоичные файлы. Файлы внутри этого каталога недоступны для пользователя или других приложений, установленных на устройстве. При удалении приложения связанные с ним файлы также автоматически удаляются.
При работе с внутренним хранилищем для доступа к файлам можно использовать методы оболочки от Activity :
- openFileInput — открыть файл на чтение;
- openFileOutput — открыть файл на запись.
Ниже представлено описание данных классов, возвращающих объекты FileInputStream, FileOutputStream соответственно.
public FileInputStream openFileInput (String name); public FileOutputStream openFileOutput (String name, int mode);
Первым параметром данных методов определяется только наименование файла (не путь к файлу). Вторым параметром (mode) метода FileOutputStream может быть значение 0 или комбинация из MODE_PRIVATE, MODE_WORLD_READABLE, MODE_WORLD_WRITEABLE и MODE_APPEND.
Ниже в свернутом виде представлен пример использования данных методов.
Пример записи/чтения файлов во внутреннее хранилище
void writeFile(final String fileName, final String text) < try < FileOutputStream fos; OutputStreamWriter osw; BufferedWriter bw ; fos = openFileOutput(fileName, MODE_PRIVATE); osw = new OutputStreamWriter(fos); bw = new BufferedWriter(osw); bw.write(text); bw.close(); Log.d(LOG_TAG, "Файл записан"); >catch (FileNotFoundException e) < e.printStackTrace(); >catch (IOException e) < e.printStackTrace(); >> void readFile(final String fileName) < try < FileInputStream fis; InputStreamReader isr; BufferedReader br ; fis = openFileInput(fileName); isr = new InputStreamReader(fis); br = new BufferedReader(isr); String str = ""; while ((str = br.readLine()) != null) < Log.d(LOG_TAG, str); >> catch (FileNotFoundException e) < e.printStackTrace(); >catch (IOException e) < e.printStackTrace(); >>
При работе с внутренним хранилищем имеются еще два метода, связанные с активностью (Activity) приложения : метод удаления файла deleteFile и метод чтения списка файлов fileList.
public boolean deleteFile (String name); public String[] fileList ();
Внешнее хранилище файлов
Внешнее хранилище относится не только к хранилищу SD-card, но и для телефонов более высокого класса это может быть внутреннее монтируемое хранилище (например, в Galaxy Nexus). Во внешнее хранилище записывают большие видеофайлы, изображения с высоким разрешением и т.д., которые совместно используются как разными приложениями, так и на разных устройствах, если Вы меняете SD-карты. Доступ к данным можно получить через путь к файлу.
Прежде чем приступить к использованию внешнего хранилища необходимо проверить его состояние с использованием метода getExternalStorageState, который возвращает текстовое значение. Ниже (в свернутом виде) представлено описание getExternalStorageState и возможные ответы (MEDIA_MOUNTED, MEDIA_UNMOUNTED . ).
Описание getExternalStorageState
/* * Returns the current state of the primary shared/external * storage media */ public static String getExternalStorageState (); /* * Returns the current state of the shared/external storage * media at the given path. */ public static String getExternalStorageState (File path); /* * Возможные возвращаемые значения : * MEDIA_UNKNOWN, * MEDIA_REMOVED, * MEDIA_UNMOUNTED, * MEDIA_CHECKING, * MEDIA_NOFS, * MEDIA_MOUNTED, * MEDIA_SHARED, * MEDIA_MOUNTED_READ_ONLY, * MEDIA_BAD_REMOVAL, * MEDIA_UNMOUNTABLE. */
Проверка методом getExternalStorageState доступного хранилища должна вернуть значение типа MEDIA_MOUNTED. Вызов данной функции в примере Android Studio вернул значение «mounted».
Ниже представлены методы получения доступа к директориям хранилища Android. К каждому методу приводится краткое описание из документации на англ. языке. В нижней части описания типы хранилищ, которые можно использовать, если методу необходимо передать какое-либо значение.
Подробное описание методов обращения к хранилищам Android представлено здесь.
Методы получения доступа к хранилищу
/* * Return root of the "system" partition holding the core * Android OS. Always present and mounted read-only. */ public static File getRootDirectory(); //----------------------------------------------------------- /* * Return the user data directory. */ public static File getDataDirectory(); //----------------------------------------------------------- /* * Return the download/cache content directory. */ public static File getDownloadCacheDirectory(); //----------------------------------------------------------- /* * Return the primary shared/external storage directory. * This directory may not currently be accessible if it has * been mounted by the user on their computer, has been * removed from the device, or some other problem has * happened. You can determine its current state with * getExternalStorageState(). */ public static File getExternalStorageDirectory(); //----------------------------------------------------------- /* * Get a top-level shared/external storage directory for * placing files of a particular type. This is where the * user will typically place and manage their own files, so * you should be careful about what you put here to ensure * you don't erase their files or get in the way of their * own organization. */ public File getExternalStoragePublicDirectory(String type); //----------------------------------------------------------- /* * Returns absolute paths to application-specific directories * on all shared/external storage devices where the * application can place persistent files it owns. These * files are internal to the application, and not typically * visible to the user as media. */ public File[] getExternalFilesDirs (String type); /* * type : * Environment.DIRECTORY_MUSIC, * Environment.DIRECTORY_PODCASTS, * Environment.DIRECTORY_RINGTONES, * Environment.DIRECTORY_ALARMS, * Environment.DIRECTORY_NOTIFICATIONS, * Environment.DIRECTORY_PICTURES, * Environment.DIRECTORY_MOVIES */
Примеры записи и чтения; внешнее хранилище
final String MY_DIR = "myDir" ; final String FILENAME = "myFile"; void writeExternalFile() < if (!Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) < Log.d(LOG_TAG, "Доступ к внешнему хранилищу закрыт : " + Environment.getExternalStorageState()); return; >File path = Environment.getExternalStorageDirectory(); path = new File(path.getAbsolutePath() +"/"+ MY_DIR); // Создаем каталог path.mkdirs(); // Создаем File File file = new File(path, FILENAME); try < // открываем поток для записи BufferedWriter bw; bw = new BufferedWriter(new FileWriter(file)); // пишем данные bw.write("Содержимое файла во внешнем хранилище"); // закрываем поток bw.close(); Log.d(LOG_TAG, "Файл записан : " + file.getAbsolutePath()); >catch (IOException e) < e.printStackTrace(); >> void readExternalFile() < if (!Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) < Log.d(LOG_TAG, "Доступ к внешнему хранилищу закрыт : " + Environment.getExternalStorageState()); return; >File path = Environment.getExternalStorageDirectory(); path = new File(path.getAbsolutePath() +"/"+ MY_DIR); File file = new File(path, FILENAME); try < // открываем поток для чтения BufferedReader br; br = new BufferedReader(new FileReader(file)); String str = ""; // читаем содержимое while ((str = br.readLine()) != null) < Log.d(LOG_TAG, str); >> catch (FileNotFoundException e) < e.printStackTrace(); >catch (IOException e) < e.printStackTrace(); >>
База данных SQLite
Описание методов взаимодействия с SQLite в виду значительного объема вынесено на отдельную страницу БД SQLite в Android. Кроме этого, Вы можете также перейти на страницу с Примером SQLite в Android.