# SharedPreferences ###### tags: `android` `data persistance storage` `sharedpreferences` `key-value` Android 提供 `SharedPreferences` 來存取簡單的 Key-Value 資料。儲存的資料型態有:`boolean`, `int`, `float`, `long`, `String`, `Set<String>`。 ## 基本用法 ### 取得 SharedPreference 物件 讀寫資料之前,首先由 `Context` 取得 `SharedPreferences` 物件。 取得 `SharedPreference` 需要三個參數: `Context`,`Mode`,`Key`。 #### Context 指定資料的 Scope #### Mode 指定資料存取的權限 #### Shared Preference Key 指定哪一個 Shared Preference #### 程式碼 ```java Context context = getActivity(); // 也可以 ApplicationContext final String MY_SHARED_PREFERENCE_KEY = context.getString(R.string.preference_file_key); SharedPreferences sharedPref = context.getSharedPreferences( MY_SHARED_PREFERENCE_KEY, Context.MODE_PRIVATE); ``` ### 寫入 寫入 `SharedPreferences` 物件 必須透過 `SharedPreferences.Editor` 物件做寫入動作,寫入完成需要 `editor.commit()` 或 `editor.apply()` 才會生效。 `SharedPreferences.Editor` 支援寫入 `int`、`double`、`String`、`long`、`float`、`boolean` 及 `Set<String>` 資料型態。 #### 程式碼 ```java SharedPreferences.Editor editor = sharedPref.edit(); final String SAVED_HIGHT_SCORE_KEY = getString(R.string.saved_high_score_key); editor.putInt(SAVED_HIGHT_SCORE_KEY, newHighScore); ... // put 其他資料 editor.commit(); // 同步提交寫入(會占用執行緒,一般不建議在主執行緒使用) editor.apply(); // 異步提交寫入 ``` ### 讀取 透過 `SharedPreferences` 物件即可讀取之前儲存的值,並賦予預設值。 也可以透過 `sharedPref.getAll()` 取得所有的Key & Value。 ```java final int defaultValue = getResources().getInteger(R.integer.saved_high_score_default_value); int highScore = sharedPref.getInt(SAVED_HIGHT_SCORE_KEY, defaultValue); Map<String, ?> sharedPrefMap = sharedPref.getAll(); // 取得所有的 Key & Value ``` ### 移除 可以移除資料 ```java sharedPref.edit() .remove(SAVED_HIGHT_SCORE_KEY) .commit(); ``` ### 設定 OnSharedPreferenceChangeListener 由於寫入可以是異步操作,我們可以透過設定 `OnSharedPreferenceChangeListener` 來監聽資料變化。 當 `SharedPreferences` 的 Key-Value 發生變化的時候,會回傳 `SharedPreferences`物件 及 Key 的值。 ```java onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) ``` ## 個人實踐 可以把 `SharedPreferences` 視為 一個 Table,每一筆 Key-Value 就是一筆資料 **ex:** ```java public void storeMacNameTable(Context targetContext, List<MacNamePair> macNamePairs) { SharedPreferences macNameTable = targetContext .getSharedPreferences(MAC_NAME_TABLE_KEY, Context.MODE_PRIVATE); SharedPreferences.Editor editor = macNameTable.edit(); for(MacNamePair mnp: macNamePairs) { editor.put(mnp.mac, mnp.name); } editor.apply(); } ``` ## 安全性 `SharedPreferences` 將資料以 **XML格式** 儲存在 **`/data/data/PACKAGE_NAME/shared_prefs`** 目錄中。當手機被Root後就可以取得這些資料,所以敏感性的資料建議加密。可以使用Java加解密的API或 [Conceal](https://facebook.github.io/conceal/) 在資料的讀寫過程中進行加解密,也可以使用 SharedPreference 的安全封裝 [Secure-preferences](https://github.com/scottyab/secure-preferences),達到資料的加解密。 ## 參考 - [Save key-value data](https://developer.android.com/training/data-storage/shared-preferences) - [SharedPreferences](https://developer.android.com/reference/android/content/SharedPreferences)