Створення та отримання налаштувань SharedPreferences
Нерідко додатку потрібно зберігати невеликі шматки даних для подальшого використання, наприклад, дані про користувача, налаштування конфігурації тощо. Для цього в Android існує концепція Preferences або налаштувань. Налаштування являють собою групу пар ключ-значення, які використовуються додатком.
Як значення можуть виступати дані наступних типів: Boolean, Float, Integer, Long, String, набір рядків.
Налаштування є загальними для всіх activity в додатку, але також можуть бути і налаштування безпосередньо для окремих activity.
Налаштування зберігаються в xml-файлах у незашифрованому вигляді в локальному сховищі. Вони невидимі, тому для простого користувача недоступні.
При роботі з налаштуваннями слід враховувати наступні моменти. Оскільки вони зберігаються в незашифрованому вигляді, не рекомендується зберігати в них чутливі дані типу паролів чи номерів кредитних карток. Крім того, вони представляють дані, асоційовані з додатком, і через панель управління додатком в Налаштуваннях ОС користувач може видалити ці дані.
Загальні налаштування
Для роботи з розділеними налаштуваннями в класі Activity (точніше в його базовому класі Context) є метод getSharedPreferences():
import android.content.SharedPreferences;
//...........................
SharedPreferences settings = getSharedPreferences("PreferencesName", MODE_PRIVATE);
Перший параметр методу вказує на назву налаштувань. В даному випадку назва - "PreferencesName". Якщо налаштувань з таким ім'ям немає, вони створюються при виклику цього методу. Другий параметр вказує на режим доступу. В даному випадку режим описано константою MODE_PRIVATE.
Клас android.content.SharedPreferences надає низку методів для управління налаштуваннями:
contains(String key): повертаєtrue, якщо в налаштуваннях збережено значення з ключемkeygetAll(): повертає всі збережені в налаштуваннях значенняgetBoolean(String key, boolean defValue): повертає з налаштувань значення типу Boolean, яке має ключkey. Якщо елемент з таким ключем не знайдено, повертається значенняdefValue, передане другим параметромgetFloat(String key, float defValue): повертає значення типу float з ключемkey. Якщо елемент з таким ключем не знайдено, повертається значенняdefValuegetInt(String key, int defValue): повертає значення типу int з ключемkeygetLong(String key, long defValue): повертає значення типу long з ключемkeygetString(String key, String defValue): повертає рядкове значення з ключемkeygetStringSet(String key, Set<String> defValues): повертає масив рядків з ключемkeyedit(): повертає об'єктSharedPreferences.Editor, який використовується для редагування налаштувань
Для управління налаштуваннями використовується об'єкт класу SharedPreferences.Editor, який повертається методом edit(). Він визначає наступні методи:
clear(): видаляє всі налаштуванняremove(String key): видаляє з налаштувань значення з ключемkeyputBoolean(String key, boolean value): додає в налаштування значення типу boolean з ключемkeyputFloat(String key, float value): додає в налаштування значення типу float з ключемkeyputInt(String key, int value): додає в налаштування значення типу int з ключемkeyputLong(String key, long value): додає в налаштування значення типу long з ключемkeyputString(String key, String value): додає в налаштування рядок з ключемkeyputStringSet(String key, Set<String> values): додає в налаштування масив рядківcommit(): підтверджує всі зміни в налаштуванняхapply(): також, як і методcommit(), підтверджує всі зміни в налаштуваннях, однак змінений об'єктSharedPreferencesспочатку зберігається в тимчасовій пам'яті, і лише потім в результаті асинхронної операції записується на мобільний пристрій
Розглянемо приклад збереження й отримання налаштувань у застосунку. Визначимо у файлі activity_main.xml наступний користувацький інтерфейс:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<EditText
android:id="@+id/nameBox"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="Введіть ім'я"
app:layout_constraintBottom_toTopOf="@id/saveButton"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/saveButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Зберегти"
android:onClick="saveName"
app:layout_constraintBottom_toTopOf="@id/nameView"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@id/nameBox"/>
<TextView
android:id="@+id/nameView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
app:layout_constraintBottom_toTopOf="@id/getButton"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@id/saveButton"/>
<Button
android:id="@+id/getButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Отримати ім'я"
android:onClick="getName"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@id/nameView"/>
</androidx.constraintlayout.widget.ConstraintLayout>
На екрані будуть дві кнопки - для збереження і для виведення раніше збереженого значення, а також поле для введення і текстове поля для виведення збереженого налаштування.
Визначимо методи обробники кнопок у класі MainActivity:
package com.example.settingsapp;
import androidx.appcompat.app.AppCompatActivity;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private static final String PREFS_FILE = "Account";
private static final String PREF_NAME = "Name";
SharedPreferences settings;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
settings = getSharedPreferences(PREFS_FILE, MODE_PRIVATE);
}
public void saveName(View view) {
// отримуємо введене ім'я
EditText nameBox = findViewById(R.id.nameBox);
String name = nameBox.getText().toString();
// зберігаємо його в налаштуваннях
SharedPreferences.Editor prefEditor = settings.edit();
prefEditor.putString(PREF_NAME, name);
prefEditor.apply();
}
public void getName(View view) {
// отримуємо збережене ім'я
TextView nameView = findViewById(R.id.nameView);
String name = settings.getString(PREF_NAME, "не визначено");
nameView.setText(name);
}
}
За відсутності налаштувань під час спроби їх отримати, додаток виведе значення за замовчуванням:
Тепер збережемо і виведемо заново збережене значення:
Нерідко виникає завдання автоматично зберігати дані, що вводяться, при виході користувача з activity. Для цього ми можемо перевизначити метод onPause:
package com.example.settingsapp;
import androidx.appcompat.app.AppCompatActivity;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
public class MainActivity extends AppCompatActivity {
private static final String PREFS_FILE = "Account";
private static final String PREF_NAME = "Name";
EditText nameBox;
SharedPreferences settings;
SharedPreferences.Editor prefEditor;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
nameBox = findViewById(R.id.nameBox);
settings = getSharedPreferences(PREFS_FILE, MODE_PRIVATE);
// отримуємо налаштування
String name = settings.getString(PREF_NAME,"");
nameBox.setText(name);
}
@Override
protected void onPause(){
super.onPause();
String name = nameBox.getText().toString();
// зберігаємо в налаштуваннях
prefEditor = settings.edit();
prefEditor.putString(PREF_NAME, name);
prefEditor.apply();
}
public void saveName(View view) {
}
public void getName(View view) {
}
}
Приватні налаштування
Окрім загальних налаштувань, кожна activity може використовувати приватні налаштування, до яких доступ з інших activity буде неможливий. Для отримання налаштувань рівня activity використовується метод getPreferences(MODE_PRIVATE):
import android.content.SharedPreferences;
//........................
SharedPreferences settings = getPreferences(MODE_PRIVATE);
Тобто, на відміну від загальних налаштувань, тут не використовується назва групи налаштувань в якості першого параметра, як в методі getSharedPreferences(). Однак вся решта робота по додаванню, отриманню та зміненню налаштувань буде аналогічна роботі з загальними налаштуваннями.