Android save all settings

Сохраняем настройки

Введение

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

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

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

Первый вариант с файлами хорош, например, для сохранения больших текстовых заметок. Естественно, и для простых данных мы тоже можем использовать файлы. Записали что-то в файл, а потом открыли его и считали данные.

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

Общие настройки поддерживают базовые типы boolean, String, float, long и int, что делает их идеальным средством для быстрого сохранения значений по умолчанию, переменных экземпляра класса, текущего состояния UI и пользовательских настроек. Они чаще всего используются для обеспечения постоянства данных между пользовательскими сессиями и доступа к ним компонентов приложения.

Сохранение значений параметров

Если у вас сохранился старый проект по подсчёту ворон, то можете снова его открыть и добавить новый код. Либо заново создайте проект по памяти, заодно проверите, как усвоили урок и сможете ли вы самостоятельно создать проект с нуля, не заглядывая на сайт за подсказкой.

Создаём переменную, представляющую экземпляр класса SharedPreferences, который отвечает за работу с настройками:

Вы передаёте в указанный метод getSharedPreferences() имя вашего файла (файл будет создан автоматически) и стандартное разрешение по умолчанию MODE_PRIVATE — только приложение имеет доступ к настройкам. Если вам необходимо, вы можете создать несколько подобных файлов настроек.

Немного опередим события и представим, что приложение запущено, и мы считаем ворон весь день. Когда мы закрываем приложение, то нам необходимо сохранить информацию в «Общих настройках». Обычно для этих целей используют методы onPause() или onStop().

Чтобы внести изменения в настройки, нужно использовать класс SharedPreferences.Editor. Получить объект Editor можно через вызов метода edit() объекта SharedPreferences. После того, как вы внесли все необходимые изменения, вызовите метод apply(), чтобы изменения вступили в силу.

Теперь при закрытии программы значение счётчика автоматически запишется в файл. При повторном запуске приложения нам уже не нужно инициализировать счётчик со значением 0. Мы можем прочитать сохранённое значение и использовать его для счётчика, чтобы продолжить подсчёт. Сделаем это в методе onResume().

Мы проверяем сначала наличие ключа APP_PREFERENCES_COUNTER, а затем извлекаем из ключа его значение.

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

Читайте также:  Андроид ком передача файлов

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

Вместо послесловия

Не волнуйтесь, с котёнком всё в порядке. Девочка подобрала его и принесла домой. И добрая девочка по-прежнему пользуется нашей программой «Счётчик ворон». Наверное, биологом станет или ветеринаром.

При написании статьи использовались иллюстрации Рины З..

Источник

Save data in a local database using Room Part of Android Jetpack.

Apps that handle non-trivial amounts of structured data can benefit greatly from persisting that data locally. The most common use case is to cache relevant pieces of data so that when the device cannot access the network, the user can still browse that content while they are offline.

The Room persistence library provides an abstraction layer over SQLite to allow fluent database access while harnessing the full power of SQLite. In particular, Room provides the following benefits:

  • Compile-time verification of SQL queries.
  • Convenience annotations that minimize repetitive and error-prone boilerplate code.
  • Streamlined database migration paths.

Because of these considerations, we highly recommend that you use Room instead of using the SQLite APIs directly.

Setup

To use Room in your app, add the following dependencies to your app’s build.gradle file:

Groovy

Kotlin

Primary components

There are three major components in Room:

  • The database class that holds the database and serves as the main access point for the underlying connection to your app’s persisted data.
  • Data entities that represent tables in your app’s database.
  • Data access objects (DAOs) that provide methods that your app can use to query, update, insert, and delete data in the database.

The database class provides your app with instances of the DAOs associated with that database. In turn, the app can use the DAOs to retrieve data from the database as instances of the associated data entity objects. The app can also use the defined data entities to update rows from the corresponding tables, or to create new rows for insertion. Figure 1 illustrates the relationship between the different components of Room.

Figure 1. Diagram of Room library architecture.

Sample implementation

This section presents an example implementation of a Room database with a single data entity and a single DAO.

Data entity

The following code defines a User data entity. Each instance of User represents a row in a user table in the app’s database.

Kotlin

To learn more about data entities in Room, see Defining data using Room entities.

Data access object (DAO)

The following code defines a DAO called UserDao . UserDao provides the methods that the rest of the app uses to interact with data in the user table.

Kotlin

Database

The following code defines an AppDatabase class to hold the database. AppDatabase defines the database configuration and serves as the app’s main access point to the persisted data. The database class must satisfy the following conditions:

  • The class must be annotated with a @Database annotation that includes an entities array that lists all of the data entities associated with the database.
  • The class must be an abstract class that extends RoomDatabase .
  • For each DAO class that is associated with the database, the database class must define an abstract method that has zero arguments and returns an instance of the DAO class.

Kotlin

Note: If your app runs in a single process, you should follow the singleton design pattern when instantiating an AppDatabase object. Each RoomDatabase instance is fairly expensive, and you rarely need access to multiple instances within a single process.

Читайте также:  Android sdk install extras

If your app runs in multiple processes, include enableMultiInstanceInvalidation() in your database builder invocation. That way, when you have an instance of AppDatabase in each process, you can invalidate the shared database file in one process, and this invalidation automatically propagates to the instances of AppDatabase within other processes.

Usage

After you have defined the data entity, the DAO, and the database object, you can use the following code to create an instance of the database:

Kotlin

You can then use the abstract methods from the AppDatabase to get an instance of the DAO. In turn, you can use the methods from the DAO instance to interact with the database:

Kotlin

Additional resources

To learn more about Room, see the following additional resources:

Sample

  • Android Sunflower, a gardening app that illustrates Android development best practices with Android Jetpack.
  • Tivi, a TV show tracking app that uses the latest libraries and tools.

Codelabs

Blogs

Content and code samples on this page are subject to the licenses described in the Content License. Java is a registered trademark of Oracle and/or its affiliates.

Источник

Data and file storage overview

Android uses a file system that’s similar to disk-based file systems on other platforms. The system provides several options for you to save your app data:

  • App-specific storage: Store files that are meant for your app’s use only, either in dedicated directories within an internal storage volume or different dedicated directories within external storage. Use the directories within internal storage to save sensitive information that other apps shouldn’t access.
  • Shared storage: Store files that your app intends to share with other apps, including media, documents, and other files.
  • Preferences: Store private, primitive data in key-value pairs.
  • Databases: Store structured data in a private database using the Room persistence library.

The characteristics of these options are summarized in the following table:

Type of content Access method Permissions needed Can other apps access? Files removed on app uninstall?
App-specific files Files meant for your app’s use only From internal storage, getFilesDir() or getCacheDir()

From external storage, getExternalFilesDir() or getExternalCacheDir()

Never needed for internal storage

Not needed for external storage when your app is used on devices that run Android 4.4 (API level 19) or higher

No Yes
Media Shareable media files (images, audio files, videos) MediaStore API READ_EXTERNAL_STORAGE when accessing other apps’ files on Android 11 (API level 30) or higher

READ_EXTERNAL_STORAGE or WRITE_EXTERNAL_STORAGE when accessing other apps’ files on Android 10 (API level 29)

Permissions are required for all files on Android 9 (API level 28) or lower

Yes, though the other app needs the READ_EXTERNAL_STORAGE permission No
Documents and other files Other types of shareable content, including downloaded files Storage Access Framework None Yes, through the system file picker No
App preferences Key-value pairs Jetpack Preferences library None No Yes
Database Structured data Room persistence library None No Yes

The solution you choose depends on your specific needs:

How much space does your data require? Internal storage has limited space for app-specific data. Use other types of storage if you need to save a substantial amount of data. How reliable does data access need to be? If your app’s basic functionality requires certain data, such as when your app is starting up, place the data within internal storage directory or a database. App-specific files that are stored in external storage aren’t always accessible because some devices allow users to remove a physical device that corresponds to external storage. What kind of data do you need to store? If you have data that’s only meaningful for your app, use app-specific storage. For shareable media content, use shared storage so that other apps can access the content. For structured data, use either preferences (for key-value data) or a database (for data that contains more than 2 columns). Should the data be private to your app? When storing sensitive data—data that shouldn’t be accessible from any other app—use internal storage, preferences, or a database. Internal storage has the added benefit of the data being hidden from users.

Categories of storage locations

Android provides two types of physical storage locations: internal storage and external storage. On most devices, internal storage is smaller than external storage. However, internal storage is always available on all devices, making it a more reliable place to put data on which your app depends.

Removable volumes, such as an SD card, appear in the file system as part of external storage. Android represents these devices using a path, such as /sdcard .

Apps themselves are stored within internal storage by default. If your APK size is very large, however, you can indicate a preference within your app’s manifest file to install your app on external storage instead:

Permissions and access to external storage

On earlier versions of Android, apps needed to declare the READ_EXTERNAL_STORAGE permission to access any file outside the app-specific directories on external storage. Also, apps needed to declare the WRITE_EXTERNAL_STORAGE permission to write to any file outside the app-specific directory.

More recent versions of Android rely more on a file’s purpose than its location for determining an app’s ability to access, and write to, a given file. In particular, if your app targets Android 11 (API level 30) or higher, the WRITE_EXTERNAL_STORAGE permission doesn’t have any effect on your app’s access to storage. This purpose-based storage model improves user privacy because apps are given access only to the areas of the device’s file system that they actually use.

Android 11 introduces the MANAGE_EXTERNAL_STORAGE permission, which provides write access to files outside the app-specific directory and MediaStore . To learn more about this permission, and why most apps don’t need to declare it to fulfill their use cases, see the guide on how to manage all files on a storage device.

Scoped storage

To give users more control over their files and to limit file clutter, apps that target Android 10 (API level 29) and higher are given scoped access into external storage, or scoped storage, by default. Such apps have access only to the app-specific directory on external storage, as well as specific types of media that the app has created.

Use scoped storage unless your app needs access to a file that’s stored outside of an app-specific directory and outside of a directory that the MediaStore APIs can access. If you store app-specific files on external storage, you can make it easier to adopt scoped storage by placing these files in an app-specific directory on external storage. That way, your app maintains access to these files when scoped storage is enabled.

To prepare your app for scoped storage, view the storage use cases and best practices guide. If your app has another use case that isn’t covered by scoped storage, file a feature request. You can temporarily opt-out of using scoped storage.

View files on a device

To view the files stored on a device, use Android Studio’s Device File Explorer.

Additional resources

For more information about data storage, consult the following resources.

Videos

Content and code samples on this page are subject to the licenses described in the Content License. Java is a registered trademark of Oracle and/or its affiliates.

Источник

Читайте также:  Тв приставка android tv box x96mini
Оцените статью