SharedPreferences を使ってアプリの最初の起動時にのみデータをダウンロードさせるためのフラグを保存させたりということが簡単にできます。但し、データが多くなるような場合は データベースを使うことが推奨されています。単純な初期化のための環境変数などの用途ということでしょう。
API 29
SharedPreferences
Androidでのストレージ オプションとしていくつかありますが、このSharedPreferencesは「共有の環境設定」という日本語訳がされています。
- 共有の環境設定
- キーと値のペアでプリミティブ データを保存します。
- 内部ストレージ
- 端末のメモリにプライベート データを保存します。
- 外部ストレージ
- 共有外部ストレージにパブリック データを保存します。
- SQLite データベース
- プライベート データベースに構造化データを保存します。
- ネットワーク接続
- 独自のネットワーク サーバーを使用してウェブにデータを保存します。
Ref: ストレージ オプション | Android Developers
後で出てきますが、SharedPreferencesの実体はxmlファイルです。アプリ内のメモリにxmlファイルでの書き込み、読出しをする訳なので、大量のデータのやり取り、プロセスをまたがったデータ取得は問題が起きる可能性があるようです。
簡単な初期起動が済んだかどうか、true/false 程度のデータを保存するためには手軽です。
SharedPreferences, Editor, MODE の設定
書込ケースでは
- SharedPreferences のインスタンス生成
- edit() を呼び出して SharedPreferences.Editor を取得
- putString() などのメソッドを使用して値を追加
- apply()あるいはcommit() を使用して新しい値を書き込む
String 書込む場合のコード
1 2 3 4 5 6 7 8 9 |
// "DataStore"という名前でインスタンスを生成 val dataStore: SharedPreferences = getSharedPreferences("DataStore", Context.MODE_PRIVATE) // 文字列を"Input"に書き込む val editor = dataStore.edit() editor.putString("Input", "文字列") //editor.commit(); editor.apply() |
書き込み方法にはapply()とcommit()があります。applyは非同期でcommit()は同期した処理ですから直ぐに書き込む必要性がない場合はapply()がいいようです。
apply()によると、非同期でよければこちらを使った方がいいが、問題がある場合はcommit()を使うというケースバイケースのようです。複数の書き込みが別スレッドで起きるような場合は注意しないといけません。
この例は、DataStore という名前で定義して、MODE_PRIVATE のモードで Key が input, value が例えば「abcdefg」を保存するケースです。モードは他にMODE_APPENDがあります。
- MODE_PRIVATE
- このアプリからのみ読み書き可
- MODE_APPEND
- 追加で書き込み
MODE_MULTI_PROCESSServiceで書きこんだデータをActivityで読み出す場合はこれが有効残念ながらAndroid6.0で非推奨になりました
String, Int, Boolean, Long, Float の保存と読み出しの例です。
保存:
1 2 3 4 5 6 7 8 9 10 11 |
val data = getSharedPreferences("Data", Context.MODE_PRIVATE) val editor = data.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 = data.getString("DataString", null) var dataInt = data.getInt("DataInt", 0) var dataBoolean = data.getBoolean("DataBoolean", false) var dataLong = data.getLong("DataLong", 0) var dataFloat = data.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 |
//package your.package.name import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.content.Context import android.content.SharedPreferences // Kotlin Android Extensions import kotlinx.android.synthetic.main.activity_main.* class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // "DataStore"という名前でインスタンスを生成 val dataStore: SharedPreferences = getSharedPreferences("DataStore", Context.MODE_PRIVATE) buttonWrite.setOnClickListener{ // エディットテキストのテキストを取得 val stringText = editText.text.toString() textWrite.text = stringText // 入力文字列を"Input"に書き込む val editor = dataStore.edit() editor.putString("Input", stringText) //editor.commit(); editor.apply() } buttonRead.setOnClickListener{ // "Input"から読み出す val str = dataStore.getString("Input", "NoData") 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 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="40dp" android:orientation="vertical" android:layout_gravity="center_horizontal" tools:context=".MainActivity"> <EditText android:id="@+id/editText" android:hint="@string/hint" android:inputType="text" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="30sp" android:layout_margin="20dp"/> <Button android:id="@+id/buttonWrite" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/write"/> <TextView android:id="@+id/textWrite" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:textSize="50sp" android:layout_marginBottom="40dp"/> <Button android:id="@+id/buttonRead" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/read"/> <TextView android:id="@+id/textRead" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:textColor="#0000ff" android:textSize="50sp" /> </LinearLayout> |
リソースです
strings.xml
1 2 3 4 5 6 |
<resources> <string name="app_name">YourAppName</string> <string name="hint">"文字を入力"</string> <string name="read">Read</string> <string name="write">Write</string> </resources> |
Device File Explorer で確認
Android Studio 3.0で保存したデータを確認します
(注)昔はADMといっていました、その前はDDMSとも呼ばれているものです。
Device File Explorerから /data/data/ 以下にパッケージ名があるのでそれを選択
その下の、Shared_pref フォルダーに設定した名前のxmlがあります。(DataStore.xml)
クリックするとxmlファイルだと言う事がわかります。
テストで設定した「test」が”input”のvalueとなっています。
1 2 3 4 |
<?xml version='1.0' encoding='utf-8' standalone='yes' ?> <map> <string name="input">test</string> </map> |
こんな風になっているのでした。
他にもコマンドの run-as を使って調べることもできます。
関連記事:
- SharedPreferences:データ保存
- アプリ内にファイルを保存、読み出し
References:
ストレージ オプション | Android Developers
SharedPreferences | Android Developers
apply()