SharedPreferences を使ってアプリの最初の起動時にのみデータをダウンロードさせるためのフラグを保存させたりということが簡単にできます。但し、データが多くなるような場合は データベースを使うことが推奨されています。単純な初期化のための環境変数などの用途ということでしょう。
2024.1.1
SharedPreferences
Androidでのストレージ オプションとしていくつかありますが、このSharedPreferencesは「共有の環境設定」という日本語訳がされています。
- 共有の環境設定
- キーと値のペアでプリミティブ データを保存します。
- 内部ストレージ
- 端末のメモリにプライベート データを保存します。
- 外部ストレージ
- 共有外部ストレージにパブリック データを保存します。
- SQLite データベース
- プライベート データベースに構造化データを保存します。
- ネットワーク接続
- 独自のネットワーク サーバーを使用してウェブにデータを保存します。
Ref: ストレージ オプション | Android Developers
SharedPreferencesの実体はxmlファイルです。アプリ内のメモリにxmlファイルでの書き込み、読出しをする訳なので、大量のデータのやり取り、プロセスをまたがったデータ取得は問題が起きる可能性があるようです。
簡単な初期起動が済んだかどうか、true/false 程度のデータを保存するためには手軽です。
SharedPreferences, Editor, MODE の設定
String 書込む場合のコード
1 2 3 4 5 6 7 8 9 |
// "DataStore"という名前でインスタンスを生成 val sharedPref = getSharedPreferences( getString(R.string.preference_file_key), Context.MODE_PRIVATE) // 文字列を"Input"に書き込む val editor = sharedPref.edit() editor.putString("Input", "文字列") editor.apply() |
strings.xml
1 2 3 4 5 |
<resources> ... <string name="preference_file_key">DataStore</string> ... </resources> |
- SharedPreferencesのインスタンスを取得
- R.string.preference_file_key をKeyとして設定
- edit() を呼び出して SharedPreferences.Editor を取得
- putString() などのメソッドを使用して値、Valueを追加
- apply()あるいはcommit() を使用して新しい値を書き込む
以前は書き込みにcommit()を使っていましたが、同期処理ですから直ぐに書き込む必要性がない場合は非同期のapply()がいいようです。
MODE_PRIVATE のモードではこのアプリからのみ読み書き可になります。
String, Int, Boolean, Long, Float の保存と読み出しの例です。
保存:
1 2 3 4 5 6 7 8 9 10 11 12 |
val sharedPref = getSharedPreferences( getString(R.string.preference_file_key), Context.MODE_PRIVATE) val editor = sharedPref .edit() editor.putString("DataString", "sample") editor.putInt("DataInt", 123) editor.putBoolean("DataBoolean", true) editor.putLong("DataLong", 12345678909876L) editor.putFloat("DataFloat", 12.345f) //editor.commit(); editor.apply() |
読出し:
1 2 3 4 5 |
var dataString = sharedPref.getString("DataString", null) var dataInt = sharedPref.getInt("DataInt", 0) var dataBoolean = sharedPref.getBoolean("DataBoolean", false) var dataLong = sharedPref.getLong("DataLong", 0) var dataFloat = sharedPref.getFloat("DataFloat", 0) |
Projectに入れてまとめると
MainActivity.kt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
package com.example.kotlinsharedpreferences import android.content.Context import android.os.Bundle import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat import com.example.kotlinsharedpreferences.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { private lateinit var binding: ActivityMainBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) ViewCompat.setOnApplyWindowInsetsListener(binding.root) { v, insets -> val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) insets } val sharedPref = getSharedPreferences( getString(R.string.preference_file_key), Context.MODE_PRIVATE) binding.buttonWrite.setOnClickListener{ // エディットテキストのテキストを取得 val stringText = binding.editText.text.toString() binding.textWrite.text = stringText // 入力文字列を"Input"に書き込む val editor = sharedPref.edit() editor.putString("Input", stringText) // editor.putInt("DataInt", 123) // editor.putBoolean("DataBoolean", true) // editor.putLong("DataLong", 12345678909876L) // editor.putFloat("DataFloat", 12.345f) editor.apply() } binding.buttonRead.setOnClickListener{ // "Input"から読み出す val str = sharedPref.getString("Input", "NoData") binding.textRead.text = str } } } |
activity_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
<?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" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <EditText android:id="@+id/editText" android:hint="@string/hint" android:autofillHints="@string/hint" android:inputType="text" android:layout_width="270dp" android:layout_height="wrap_content" android:textSize="30sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.15" /> <Button android:id="@+id/buttonWrite" android:text="@string/write" android:layout_width="270dp" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.3" /> <TextView android:id="@+id/textWrite" android:gravity="center" android:textSize="50sp" android:layout_width="270dp" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.4" /> <Button android:id="@+id/buttonRead" android:text="@string/read" android:layout_width="270dp" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.6" /> <TextView android:id="@+id/textRead" android:gravity="center" android:textColor="#0000ff" android:textSize="50sp" android:layout_width="270dp" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.7" /> </androidx.constraintlayout.widget.ConstraintLayout> |
リソースです
strings.xml
1 2 3 4 5 6 7 |
<resources> <string name="app_name">KotlinSharedPreferences</string> <string name="preference_file_key">DataStore</string> <string name="hint">"文字を入力"</string> <string name="read">Read</string> <string name="write">Write</string> </resources> |
ViewBIndingの設定
build.gradle
1 2 3 4 5 6 7 8 |
... android { ... buildFeatures { viewBinding = true } } ... |
実行させてみましょう
Device Explorer で確認
注)あくまでデバッグ段階でのファイル確認です
Android Studio で保存したデータを確認します
Device Explorerから /data/data/ 以下にパッケージ名があるのでそれを選択
その下の、shared_pref フォルダーに設定した名前のxmlがあります。(DataStore.xml)
クリックするとxmlファイルだと言う事がわかります。
テストで設定した「asdfgh」が”input”のvalueとなっています。
1 2 3 4 |
<?xml version='1.0' encoding='utf-8' standalone='yes' ?> <map> <string name="input">asdfgh</string> </map> |
他にもadbコマンドの run-as を使って調べることもできます。
References:
Key-Value データを保存する | Android デベロッパー
ストレージ オプション | Android Developers
SharedPreferences | Android Developers
apply()