Где приложение андроид хранит свои настройкики

Студворк — интернет-сервис помощи студентам

продолжаю свое изучение Андройда: время для файловой системы (иначе просто не могу понять – куда создаваемый файл писать).

И хотя я часто использую Убунту, файловая структура Линукса, тем более Андройда – мне почти не знакома.

Установил Х-plore (на КитКэт) и не увидел в нем ничего кроме вопросов:

1) почему директория /storage/emulated/o – содержит то же что и что директория sdcard (это как понимаю примонтированная к корню флэш-карта).

2) где диретория в которой хранятся файлы конкретного пользователя?

3) где хранятся файлы, ярлыки рабочих столов конкретного пользователя?

4) где лучше (удобнее, правильнее или “так принято”) создать диреторию для собственных личных файлов?

5) как вывести “ярлык” своей папки на рабочий стол?

и пользуясь случаем еще вопрос: есть ли у кого-то опыт подключения мыши?

Я подключил клаву через микро-усб, и так не хватает мышки, но больше нет разъемов, кроме того будет ли работать с Андройд какая-то конкретная мышь? (с Убунту все мыши работают, кроме MS мышей). Покажите на Ebay какую мышь можно купить. Если бы она еще через WiFi работала, что было бы идеально, не нужно было бы двойник для усб покупать.

Добавлено через 2 часа 29 минут


PS:

друзья, я не ожидаю, что кто-то даст всеобъемлющий и экспертный ответ.

Каждый кто, что-то знает об этом, есть какой-то опыт, видел, где об этом можно почитать – пожалуйста пишите.

Когда мало информации -любая информация важна.

Все приложения (корневые или нет) имеют каталог данных по умолчанию, который является /data/data/<package_name>
. По умолчанию базы данных приложений, настройки и все остальные данные находятся здесь. Если приложение ожидает, что будут храниться огромные объемы данных, или по другим причинам хочет «быть хорошо со встроенным хранилищем», на SDCard ( Android/data/<package_name>
) имеется соответствующий каталог .

Кроме того, все приложения могут хранить данные в любом месте на SDCard, поскольку нет никаких ограничений – и многие приложения делают это. Они могут свободно использовать имена каталогов (и они снова используют), что часто затрудняет решение, для чего предназначен весь этот «мусор» на карте, и что из него можно удалить.

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

  • databases/
    : здесь идут базы данных приложения
  • lib/
    : библиотеки и помощники для приложения
  • files/
    : другие связанные файлы
  • shared_prefs/
    : настройки и настройки
  • cache/
    : ну кеширует

В этом месте может быть еще несколько каталогов или меньше – все зависит от приложения. В своем собственном «домашнем каталоге» (и это то, чем он в основном является, говоря по Linux), они могут размещать файлы там, где они хотят. Обычно эти файлы и каталоги доступны только для самого приложения (и, конечно, для пользователя root) – кроме тех, которые хранятся на SDCard и доступны всем приложениям.


Я должен настроить более 50 телефонов для своей компании, и мне разрешено рутировать телефоны. Каждый телефон должен иметь одинаковые SSID / пароли WIFI, настройки учетной записи / конфиденциальности, яркость, способы ввода и т. Д. Повторение одной и той же ручной настройки 50 раз кажется утомительным.

Где хранятся настройки телефона? Можно ли просто adb нажать настройки для каждого устройства? Телефоны Samsung Galaxy Pocket.







Оказывается, что нет волшебного файла или каталога, который содержит все настройки. Они хранятся в разных местах и ​​во многом зависят от того, как производитель решит все настроить. Я в основном работаю с телефонами Samsung, поэтому информация в основном будет ориентирована на Samsung. Также обратите внимание, что все перечисленное ниже требует root-доступа. Если кому-то есть что добавить / исправить, не стесняйтесь комментировать.

Во-первых, я обнаружил, что «копирование настроек» не всегда лучший способ. Вы можете выполнять резервное копирование и восстановление nandroid
, что в значительной степени клонирует один телефон на другой. Если вы достаточно техничны и используете Samsung, то создание собственного образа odin
может быть даже лучшим вариантом, поскольку он не зависит от вас или кого-то еще, кто создал поддержку nandroid / recovery.

Содержание

Настройки

Общие настройки:

настройки в основном хранятся в /data
подкаталоге. Если вы ищете что-то конкретное, начните там.

Встроенные приложения:

встроенные приложения, как правило, сохраняют свои настройки /data/data/com.android.*
и, /data/data/com.google.android.*


например:

контакты: /data/data/com.android.contacts

учетные записи электронной почты: /data/data/com.android.email

MMS: /data/data/com.android.mms

WiFi:

расположение настроек WiFi зависит от производителя, но обычно предсказуемо.

Samsung Galaxy Pocket, S2, S3: /data/misc/wifi/wpa_supplicant.conf

Вкладка Samsung: /data/wifi/bcm_supp.conf

HTC Desire: /data/misc/wifi/wpa_supplicant.conf

Dell Streak: /data/misc/wifi/wpa.conf

Oneplus 2, 3: /data/misc/wifi/networkHistory.txt

Конфигурации клавиатуры:

мне раньше приходилось отключать аппаратные клавиши, перенастраивать раскладки или изменять общее поведение клавиатуры. Точное имя файла имеет тенденцию быть различным на каждом телефоне, но я обнаружил, что файлы конфигурации всегда находятся в /system/usr/keylayout/
. Будьте осторожны, так как их поломка может сделать ваш телефон непригодным для использования.

Разное:

Большинство различных настроек, таких как информация о продукте, звуки загрузки и включение / отключение экранной навигационной панели, хранятся в /system/build.prop
. Взлом этого файла конфигурации может привести к загрузке вашего устройства.

Если я найду больше информации, я добавлю позже.







Другой возможный способ сделать это – использовать команду “ content ”, например:

   adb shell content query --uri content://settings/global 
adb shell content insert --uri content://settings/global --bind name:s:preferred_network_mode1 --bind value:i:0
  
  


Я не эксперт в технологиях Android. Так что я не совсем уверен, верен ли мой ответ или нет. Но, используя Root Explorer, я обнаружил, что некоторые настройки хранятся в следующих файлах:

  • /data/system/users/0/settings_system.xml
  • /data/system/users/0/settings_secure.xml

Например, яркость экрана сохраняется в файле settings_system.xml
. Если вы откроете этот файл с помощью текстового редактора, вы можете встретить следующую строку кода:

   <setting id="2220" name="screen_brightness" value="66" package="com.android.settings" />
  
  

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

  • / Данные / система / пользователей / 0 / обои

Мой мобильный телефон Samsung SM-J7. Может быть, мое открытие может отличаться для других смартфонов.


Большинство настроек Android находятся в /data/data/com.android.providers.settings/databases/settings‌​.db
базе данных SQLite, которой можно легко управлять с помощью браузера SQLite. Сам Android обычно использует защищенный поставщик настроек для управления этими настройками.

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

Последнее обновление: 17.10.2021

Нередко приложению требуется сохранять небольшие кусочки данных для дальнейшего использования, например, данные о пользователе, настройки конфигурации и т.д. Для этого в Android существует концепция Preferences
или настройки. Настройки представляют собой группу пар ключ-значение, которые используются приложением.

В качестве значений могут выступать данные следующих типов: Boolean, Float, Integer, Long, String, набор строк.

Настройки общими для всех activity в приложении, но также могут быть и настройки непосредственно для отдельных activity

Настройки хранятся в xml-файлах в незашифрованном виде в локальном хранилище. Они невидимы, поэтому для простого пользователя недоступны.

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

Общие настройки

  import android.content. SharedPreferences;

//.

SharedPreferences settings = getSharedPreferences("PreferencesName", MODE_PRIVATE);
  

Первый параметр метода указывает на название настроек. В данном случае название – “PreferencesName”. Если настроек с подобным названием нет,
то они создаются при вызове данного метода. Второй параметр указывает на режим доступа. В данном случае режим описан константой MODE_PRIVATE

  • contains(String key)
    : возвращает true, если в настройках сохранено значение с ключом key

  • getAll()
    : возвращает все сохраненные в настройках значения

  • getBoolean (String key, boolean defValue)
    : возвращает из настроек значение типа Boolean, которое имеет ключ key.
    Если элемента с таким ключом не окажется, то возвращается значение defValue, передаваемое вторым параметром

  • getFloat(String key, float defValue)
    : возвращает значение типа float с ключом key.
    Если элемента с таким ключом не окажется, то возвращается значение defValue

  • getInt(String key, int defValue)
    : возвращает значение типа int с ключом key

  • getLong(String key, long defValue)
    : возвращает значение типа long с ключом key

  • getString(String key, String defValue)
    : возвращает строковое значение с ключом key

  • getStringSet(String key, Set<String> defValues)
    : возвращает массив строк с ключом key

  • clear()
    : удаляет все настройки

  • remove(String key)
    : удаляет из настроек значение с ключом key

  • putBoolean(String key, boolean value)
    : добавляет в настройки значение типа boolean с ключом key

  • putFloat(String key, float value)
    : добавляет в настройки значение типа float с ключом key

  • putInt(String key, int value)
    : добавляет в настройки значение int с ключом key

  • putLong(String key, long value)
    : добавляет в настройки значение типа long с ключом key

  • putString(String key, String value)
    : добавляет в настройки строку с ключом key

  • putStringSet(String key, Set<String> values)
    : добавляет в настройки строковый массив

  • commit()
    : подтверждает все изменения в настройках

Рассмотрим пример сохранения и получения настроек в приложении. Определим в файле следующий пользовательский интерфейс:

  <?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>
  

На экране будут две кнопки – для сохранения и для вывода ранее сохраненного значения, а также поле для ввода и текстовое поля ля вывода сохраненной настройки.

Определим методы обработчики кнопок в классе :

  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);
 }
}
  

При отсутствии настроек при попытке их получить, приложение выведет значение по умолчанию:

Получение настроек SharedPreferences preferences в Android и Java

Теперь сохраним и выведем заново сохраненное значение:

Сохранение настроек SharedPreferences preferences в Android и Java

Нередко возникает задача автоматически сохранять вводимые данные при выходе пользователя из 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
используется метод :

  import android.content. SharedPreferences;
//.
SharedPreferences settings = getPreferences(MODE_PRIVATE);
  

В этом уроке:

– хранение данных с помощью Preferences

Хватит об Intent и Activity. Поговорим о хранении данных. В Android есть несколько способов хранения данных:

Preferences
– в качестве аналогии можно привести виндовые INI-файлы

SQLite
 – база данных, таблицы

обычные файлы
– внутренние и внешние (на SD карте)

Мы начнем с самого простого – Preferences
. Значения сохраняются в виде пары: имя
, значение
. Так же, как и например extras в Intent.

Разработаем приложение. В нем будет поле для ввода текста и две кнопки – Save
и Load
. По нажатию на Save
мы будем сохранять
значение из поля, по нажатию на Load
загружать
.

Откроем main.xml
и создадим такой экран:

  <?xml version="1.0" encoding="utf-8"?>
<LinearLayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent"
 android:orientation="vertical">
 <EditText
 android:id="@+id/etText"
 android:layout_width="match_parent"
 android:layout_height="wrap_content">
 <requestFocus>
 </requestFocus>
 </EditText>
 <LinearLayout
 android:id="@+id/linearLayout1"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:orientation="horizontal">
 <Button
 android:id="@+id/btnSave"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="Save">
 </Button>
 <Button
 android:id="@+id/btnLoad"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="Load">
 </Button>
 </LinearLayout>
</LinearLayout>  

Поле ввода и две кнопки.

Теперь пишем код в MainActivity.java
:

  package ru.startandroid.develop.p0331sharedpreferences;

import android.app. Activity;
import android.content. SharedPreferences;
import android.content. SharedPreferences. Editor;
import android.os. Bundle;
import android.view. View;
import android.view. View. OnClickListener;
import android.widget. Button;
import android.widget. EditText;
import android.widget. Toast;

public class MainActivity extends Activity implements OnClickListener {
 
 EditText etText;
 Button btnSave, btnLoad;
 
 SharedPreferences sPref;
 
 final String SAVED_TEXT = "saved_text";
 
 
 /** Called when the activity is first created.  */
 @Override
 public void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.main);
 
 etText = (EditText) findViewById(R.id.etText);
 
 btnSave = (Button) findViewById(R.id.btnSave);
 btnSave.setOnClickListener(this);
 
 btnLoad = (Button) findViewById(R.id.btnLoad);
 btnLoad.setOnClickListener(this);
 }

 @Override
 public void onClick(View v) {
 switch (v.getId()) {
 case R.id.btnSave:
 saveText();
 break;
 case R.id.btnLoad:
 loadText();
 break;
 default:
 break;
 }
 }
 
 void saveText() {
 sPref = getPreferences(MODE_PRIVATE);
 Editor ed = sPref.edit();
 ed.putString(SAVED_TEXT, etText.getText().toString());
 ed.commit();
 Toast.makeText(this, "Text saved", Toast. LENGTH_SHORT).show();
 }
 
 void loadText() {
 sPref = getPreferences(MODE_PRIVATE);
 String savedText = sPref.getString(SAVED_TEXT, "");
 etText.setText(savedText);
 Toast.makeText(this, "Text loaded", Toast. LENGTH_SHORT).show();
 }
}  

Определение элементов экрана, присвоение обработчиков и реализация onClick – тут все понятно и как обычно. Нам интересны методы
, которые мы вызываем в onClick

Все сохраняем, запускаем приложение.

Для начала, давайте убедимся, что сохранение в принципе нужно. Введите какой-нить текст в поле ввода

Где приложение андроид хранит свои настройкики

и не нажимая кнопку Save
закройте приложение кнопкой Назад
.

Теперь найдите приложение в общем списке приложений эмулятора

Где приложение андроид хранит свои настройкики

и запустите снова.

Поле ввода пустое. То, что мы вводили – пропало при закрытии программы. Нажатие на Load
тоже ничего не даст – мы ничего не сохраняли.

Где приложение андроид хранит свои настройкики

Давайте попробуем сохранять. Снова введите значение и нажмите Save
.

Где приложение андроид хранит свои настройкики

Значение сохранилось в системе.

Теперь закроем приложение ( Назад
), снова откроем и нажмем Load
. Значение считалось и отобразилось.

Где приложение андроид хранит свои настройкики

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

  public void onCreate(Bundle savedInstanceState) {
 
 .
 
 btnLoad = (Button) findViewById(R.id.btnLoad);
 btnLoad.setOnClickListener(this);
 
 loadText();
}   

(Добавляете только строку 8)

а метод saveText – в onDestroy

  @Override
 protected void onDestroy() {
 super.onDestroy();
 saveText();
 }  

Все сохраним, запустим. Теперь можно вводить данные, закрывать приложение, снова открывать и данные не потеряются. Кнопки Save
и Load
также работают. В какой момент сохранять данные в ваших приложениях – решать только вам. По нажатию
кнопки, при закрытии
программы или еще по какому-либо событию. Главное – теперь вы это умеете.

Еще немного слов по этой теме.

  <?xml version="1.0" encoding="utf-8"?>
<map>
 <string name="saved_text">abcdefg</string>
</map>  

Все верно, имя – saved_text
и значение – abcdefg
.

Обратите внимание, что в пути к файлу используется наш package.

  sPref = getSharedPreferences("MyPref", MODE_PRIVATE);  

То данные сохранились бы в файле MyPref.xml
, а не в MainActivity.xml
.

Теперь если мы посмотрим исходники метода getPreferences
, то видим следующее:

  public SharedPreferences getPreferences(int mode) {
 return getSharedPreferences(getLocalClassName(), mode);
}  

– используете getPreferences
, если работаете с данными для текущего Activity и не хотите выдумывать имя файла.

Кстати, в File Explorer вы можете видеть юниксовые rwx-права доступа
к файлу. Попробуйте при сохранении данных использовать не MODE_PRIVATE
, а  MODE_WORLD_READABLE
или  MODE_WORLD_WRITEABLE
и посмотрите, как будут меняться права. 

Полный код MainActivity.java
:

  package ru.startandroid.develop.p0331sharedpreferences;

import android.app. Activity;
import android.content. SharedPreferences;
import android.content. SharedPreferences. Editor;
import android.os. Bundle;
import android.view. View;
import android.view. View. OnClickListener;
import android.widget. Button;
import android.widget. EditText;
import android.widget. Toast;

public class MainActivity extends Activity implements OnClickListener {
 
 EditText etText;
 Button btnSave, btnLoad;
 
 SharedPreferences sPref;
 
 final String SAVED_TEXT = "saved_text";
 
 
 /** Called when the activity is first created.  */
 @Override
 public void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.main);
 
 etText = (EditText) findViewById(R.id.etText);
 
 btnSave = (Button) findViewById(R.id.btnSave);
 btnSave.setOnClickListener(this);
 
 btnLoad = (Button) findViewById(R.id.btnLoad);
 btnLoad.setOnClickListener(this);
 
 loadText();
 }

 @Override
 public void onClick(View v) {
 switch (v.getId()) {
 case R.id.btnSave:
 saveText();
 break;
 case R.id.btnLoad:
 loadText();
 break;
 default:
 break;
 }
 }
 
 void saveText() {
 sPref = getPreferences(MODE_PRIVATE);
 Editor ed = sPref.edit();
 ed.putString(SAVED_TEXT, etText.getText().toString());
 ed.commit();
 Toast.makeText(this, "Text saved", Toast. LENGTH_SHORT).show();
 }
 
 void loadText() {
 sPref = getPreferences(MODE_PRIVATE);
 String savedText = sPref.getString(SAVED_TEXT, "");
 etText.setText(savedText);
 Toast.makeText(this, "Text loaded", Toast. LENGTH_SHORT).show();
 }
 
 @Override
 protected void onDestroy() {
 super.onDestroy();
 saveText();
 }

}  

На следующем уроке:

– хранение данных с помощью SQLite


Присоединяйтесь к нам в Telegram
:

– в канале StartAndroid
 публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

– в чатах решаем возникающие вопросы и проблемы по различным темам: Android
, Compose
, Kotlin
, RxJava
, Dagger
, Тестирование
, Performance
 

– ну и если просто хочется поговорить с коллегами по разработке, то есть чат  Флудильня


Сохранение состояния приложения

Последнее обновление: 17.10.2021

В одной из предыдущих тем был рассмотрен жизненный цикл Activity в приложении на Android, где после создания Activity вызывался метод ,
который восстанавливал ее состояние, а перед завершением работы вызывался метод , который сохранял состояние Actiity.
Оба этих метода в качестве параметра принимают объект , который как раз и хранит состояние activity:

  protected void onRestoreInstanceState(Bundle saveInstanceState);
protected void onSaveInstanceState(Bundle saveInstanceState);
  

В какой ситуации могут быть уместно использование подобных методов? Банальная ситуация – переворот экрана и переход от портретной ориентации к альбомной и наоборот.
Если, к примеру, графический интерфейс содержит текстовое поле для вывода TextView, и мы программно изменяем его текст, то после изменения ориентации экрана его текст может исчезнуть. Или если у нас глобальные переменные, то
при изменении ориентации экрана их значения могут быть сброшены до значений по умолчанию.

Чтобы точнее понять проблему, с которой мы можем столкнуться, рассмотрим пример. Изменим файл следующим образом:

  <?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>
  

Здесь определено поле EditText, в которое вводим имя. И также определена кнопка для его сохранения.

Далее для вывода сохраненного имени предназначено поле TextView, а для получения сохраненного имени – вторая кнопка.

Теперь изменим класс :

  package com.example.settingsapp;

import androidx.appcompat.app. AppCompatActivity;

import android.os. Bundle;
import android.view. View;
import android.widget. EditText;
import android.widget. TextView;

public class MainActivity extends AppCompatActivity {

 String name ="undefined";

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 }

 public void saveName(View view) {

 // получаем введенное имя
 EditText nameBox = findViewById(R.id.nameBox);
 name = nameBox.getText().toString();
 }
 public void getName(View view) {

 // получаем сохраненное имя
 TextView nameView = findViewById(R.id.nameView);
 nameView.setText(name);
 }
}
  

Для хранения имени в программе определена переменная name. При нажатии на первую кнопку сохраняем текст из EditText в переменную name, а при нажатии на вторую кнопку –
обратно получаем текст из переменной name в поле TextView.

Запустим приложение введем какое-нибудь имя, сохраним и получим его в TextView:

Состояние activity в Android и Java

Но если мы перейдем к альбомному режиму, то TextView окажется пустым, несмотря на то, что в него вроде бы уже получили нужное значение:

Состояние Bundle activity в Android и Java

И даже если мы попробуем заново получить значение из переменной name, то мы увидим, что она обнулилась:

Сохранение состояния activity в Android и Java

Чтобы избежать подобных ситуаций как раз и следует сохранять и восстанавливать состояние activity. Для этого изменим код MainActivity:

  package com.example.settingsapp;

import androidx.appcompat.app. AppCompatActivity;

import android.os. Bundle;
import android.view. View;
import android.widget. EditText;
import android.widget. TextView;

public class MainActivity extends AppCompatActivity {

 String name ="undefined";
 final static String nameVariableKey = "NAME_VARIABLE";
 TextView nameView;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);

 nameView = findViewById(R.id.nameView);
 }

 // сохранение состояния
 @Override
 protected void onSaveInstanceState(Bundle outState) {

 outState.putString(nameVariableKey, name);
 super.onSaveInstanceState(outState);
 }
 // получение ранее сохраненного состояния
 @Override
 protected void onRestoreInstanceState(Bundle savedInstanceState) {
 super.onRestoreInstanceState(savedInstanceState);

 name = savedInstanceState.getString(nameVariableKey);
 nameView.setText(name);
 }
 public void saveName(View view) {

 // получаем введенное имя
 EditText nameBox = findViewById(R.id.nameBox);
 // сохраняем его в переменную name
 name = nameBox.getText().toString();
 }
 public void getName(View view) {

 // выводим сохраненное имя
 nameView.setText(name);
 }
}
  

В методе onSaveInstanceState()
сохраняем состояние. Для этого вызываем у параметра Bundle метод ,
первый параметр которого – ключ, а второй – значение сохраняемых данных. В данном случае мы сохраняем строку, поэтому вызываем метод putString()
. Для
сохранения объектов других типов данных мы можем вызвать соответствующий метод:

  • : универсальный метод, который добавляет значение типа Object. Соответственно поле получения данное значение необходимо
    преобразовать к нужному типу

  • : добавляет объект типа String

  • : добавляет значение типа int

  • : добавляет значение типа byte

  • : добавляет значение типа char

  • : добавляет значение типа short

  • : добавляет значение типа long

  • : добавляет значение типа float

  • : добавляет значение типа double

  • : добавляет значение типа boolean

  • : добавляет массив объектов char

  • : добавляет массив объектов int

  • : добавляет массив объектов float

  • : добавляет объект интерфейса Serializable

  • : добавляет объект Parcelable

Каждый такой метод также в качестве первого параметра принимает ключа, а в качестве второго – значение.

В методе происходит обратный процесс – с помощью метода по ключу получаем из сохраненного состояния строку по ключу.
Соответственно для получения данных других типов мы можем использовать аналогичные методы:

  • : универсальный метод, который возвращает значение типа Object. Соответственно поле получения данное значение необходимо
    преобразовать к нужному типу

  • : возвращает объект типа String

  • : возвращает значение типа int

  • : возвращает значение типа byte

  • : возвращает значение типа char

  • : возвращает значение типа short

  • : возвращает значение типа long

  • : возвращает значение типа float

  • : возвращает значение типа double

  • : возвращает значение типа boolean

  • : возвращает массив объектов char

  • : возвращает массив объектов int

  • : возвращает массив объектов float

  • : возвращает объект интерфейса Serializable

  • : возвращает объект Parcelable

  package com.example.settingsapp;

import java.io. Serializable;

public class User implements Serializable {

 private String name;
 private int age;

 public User(String name, int age){
 this.name = name;
 this.age = age;
 }

 public String getName() {
 return name;
 }

 public void setName(String name) {
 this.name = name;
 }

 public int getAge() {
 return age;
 }

 public void setAge(int age) {
 this.age = age;
 }
}
  

Пусть у нас будет следующий интерфейс в :

  <?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/yearBox"
 app:layout_constraintLeft_toLeftOf="parent"
 app:layout_constraintRight_toRightOf="parent"
 app:layout_constraintTop_toTopOf="parent" />
 <EditText
 android:id="@+id/yearBox"
 android:layout_width="0dp"
 android:layout_height="wrap_content"
 android:hint="Введите возраст"
 android:inputType="numberDecimal"
 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="saveData"
 app:layout_constraintBottom_toTopOf="@id/dataView"
 app:layout_constraintLeft_toLeftOf="parent"
 app:layout_constraintTop_toBottomOf="@id/yearBox"/>

 <TextView
 android:id="@+id/dataView"
 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="getData"
 app:layout_constraintLeft_toLeftOf="parent"
 app:layout_constraintTop_toBottomOf="@id/dataView"/>

</androidx.constraintlayout.widget. ConstraintLayout>
  

Здесь определены два поля ввода для имени и возраста соответственно.

В классе пропишем логику сохранения и получения данных:

  package com.example.settingsapp;

import androidx.appcompat.app. AppCompatActivity;

import android.os. Bundle;
import android.view. View;
import android.widget. EditText;
import android.widget. TextView;

public class MainActivity extends AppCompatActivity {

 User user = new User("undefined", 0);
 final static String userVariableKey = "USER_VARIABLE";

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 }

 // сохранение состояния
 @Override
 protected void onSaveInstanceState(Bundle outState) {

 outState.putSerializable(userVariableKey, user);
 super.onSaveInstanceState(outState);
 }
 // получение ранее сохраненного состояния
 @Override
 protected void onRestoreInstanceState(Bundle savedInstanceState) {
 super.onRestoreInstanceState(savedInstanceState);
 // получаем объект User в переменную
 user = (User)savedInstanceState.getSerializable(userVariableKey);
 TextView dataView = findViewById(R.id.dataView);
 dataView.setText("Name: " + user.getName() + " Age: " + user.getAge());
 }
 public void saveData(View view) {

 // получаем введенные данные
 EditText nameBox = findViewById(R.id.nameBox);
 EditText yearBox = findViewById(R.id.yearBox);
 String name = nameBox.getText().toString();
 int age = 0; // значение по умолчанию, если пользователь ввел некорректные данные
 try{
 age = Integer.parseInt(yearBox.getText().toString());
 }
 catch (NumberFormatException ex){}
 user = new User(name, age);
 }
 public void getData(View view) {

 // получаем сохраненные данные
 TextView dataView = findViewById(R.id.dataView);
 dataView.setText("Name: " + user.getName() + " Age: " + user.getAge());
 }
}
  

onRestoreInstanceState и onSaveInstanceState 	 в Android и Java

1 Звездаслабоватона троечкухорошо!просто отлично! (1 оценок, среднее: 5,00 из 5)
Загрузка...

Расскажите нам ваше мнение:

Ваш адрес email не будет опубликован. Обязательные поля помечены *