SharedPreferencesは、シンプルな設定やアプリ設定を保存するために設計されたAndroidのキー値データストレージです。データはデバイスのXMLファイルに保存され、それを作成したアプリ内でのみアクセス可能です。公式ドキュメントによると Android Developers, 2025、SharedPreferencesはプリミティブ型:String、Int、Boolean、Float、Long、Set<String>の保存をサポートしています。これはSQLクエリやファイルシステムを直接操作することなく、少量のユーザー設定を保存するための最もシンプルで最速のソリューションです。
重要なポイント
SharedPreferencesは、デバイスの内部ストレージにあるXMLファイルにキーと値のペアを保存するためのAndroidの組み込みメカニズムです。API Level 1から利用可能で、追加のライブラリは必要ありません。主な目的は、ユーザー設定、インターフェースの状態、初回起動フラグ、および構造化データベースを必要としないその他の単純なデータを保存することです。
各SharedPreferencesファイルは特定の名前とアクセスモードに関連付けられています。デフォルトではContext.MODE_PRIVATEモードが使用され、ファイルへのアクセスは現在のアプリのみに制限されます。以前はAndroidはMODE_WORLD_READABLEとMODE_WORLD_WRITEABLEモードをサポートしていましたが、セキュリティ上の理由からAPI Level 17で非推奨となり、Android 7.0(API 24)で完全に削除されました。
そのシンプルさにもかかわらず、SharedPreferencesは何百万ものAndroidアプリで使用されています。Googleによると、Google Playに公開されているアプリの90%以上が設定の保存にSharedPreferencesを使用しています。ただし、複雑なシナリオ(大量のデータ、型安全性、非同期処理)については、GoogleはAndroid JetpackライブラリのPreferences DataStoreなど、より最新のソリューションを推奨しています。
物理的には、SharedPreferencesはアプリのディレクトリにXMLファイルとして保存されます:/data/data/{package_name}/shared_prefs/{file_name}.xml。ファイルにはルート要素<map>と、保存された値の型に応じて子要素<string>、<int>、<boolean>、<float>、<long>が含まれます。ファイルサイズに制限はありませんが、大量のデータ(100KB以上)では読み取りと書き込みのパフォーマンスが著しく低下し始めます。
SharedPreferencesファイルはデフォルトでは暗号化されていません。データはデバイスのファイルシステムにプレーンテキストで保存されます。機密データ(トークン、パスワード)を保存するには、AndroidX SecurityライブラリのEncryptedSharedPreferencesを使用することをお勧めします。これはAES256-GCMを使用してキーと値を自動的に暗号化します。
SharedPreferencesは、定期的なディスク同期によるメモリ内キャッシュの原則で動作します。最初にファイルにアクセスするとき(getSharedPreferences経由)、AndroidはXMLファイルをRAMにロードし、Mapオブジェクトに解析します。後続のすべての読み取り操作は、ディスクから再読み取りすることなくメモリから実行されます。これにより、データへの高速アクセスが保証されます。
書き込み操作はEditor — 内部変更バッファを使用します。開発者がputStringまたはputBooleanを呼び出すと、変更はメモリ内のEditorオブジェクトに保存されます。実際のディスクへの書き込みは、commit(同期)またはapply(非同期)メソッドが呼び出されたときに発生します。これらのメソッドが呼び出されるまでデータは保存されず、アプリが予期せずクラッシュした場合、変更が失われる可能性があります。
SharedPreferencesインスタンスを取得するには、getPreferencesとgetSharedPreferencesの2つのメソッドが使用されます。前者はActivity内でのみ利用可能で、Activityの名前でファイルを作成します。後者はより柔軟で、ファイル名とアクセスモードを受け入れ、任意のコンテキスト(Application、Activity、Service)からアクセスできます。アプリのモジュールや機能に対応するファイル名でgetSharedPreferencesを使用することをお勧めします。
// SharedPreferencesの取得
val prefs = context.getSharedPreferences(
"user_settings", Context.MODE_PRIVATE
)
// データの書き込み
with(prefs.edit()) {
putString("username", "アンナ")
putInt("age", 28)
putBoolean("isLoggedIn", true)
apply()
}
// データの読み取り
val username = prefs.getString("username", "")
val age = prefs.getInt("age", 0)
val isLoggedIn = prefs.getBoolean("isLoggedIn", false)
MODE_MULTI_PROCESS(非推奨)を使用すると、SharedPreferencesはプロセス間で同期されます。ただし、この同期は原子性を保証せず、GoogleはマルチプロセスシナリオでのSharedPreferencesの使用を避けることを推奨しています。そのような場合は、ContentProvider、プロセス間アクセスを使用したRoom、またはDataStoreを使用することをお勧めします。
SharedPreferencesは、キーによるデータ読み取りのためのメソッドセットと、書き込みのためのEditorインターフェースを提供します。各読み取りメソッドは2つのパラメータを受け取ります:キーと、キーが見つからない場合に返されるデフォルト値です。デフォルト値は戻り値の型も決定します:getStringはStringを返し、getIntはIntを返す、などです。
| 読み取りメソッド | 書き込みメソッド | データ型 |
|---|---|---|
| getString | putString | String |
| getInt | putInt | Int |
| getBoolean | putBoolean | Boolean |
| getFloat | putFloat | Float |
| getLong | putLong | Long |
| getStringSet | putStringSet | Set<String> |
Editorは、バッファに変更を収集するSharedPreferencesの内部オブジェクトです。すべての変更を行った後、開発者はcommit()(同期書き込み)またはapply()(非同期書き込み)を呼び出します。違いは重要です:commitはディスクへの書き込みが完了するまで現在のスレッドをブロックし、boolean(成功/失敗)を返します。一方、applyはバックグラウンドスレッドで書き込みを実行し、すぐに制御を返しますが、結果は返しません。
書き込み結果を知る必要がないすべての場合において、commitの代わりにapplyを使用することをお勧めします。applyはより高速で、UIスレッドをブロックしません。commitは、データが正常に保存されたかどうかを知ることが重要な場合、またはマルチプロセスモードで作業する場合にのみ使用する必要があります。個別のキーを削除するにはremoveメソッド、完全にクリアするにはclearを使用します。すべての削除操作もEditorを介して実行されます。
// 複数の変更 - 1つのapply
prefs.edit {
putString("theme", "dark")
putBoolean("notifications", false)
remove("old_key")
}
// 値変更リスナー
prefs.registerOnSharedPreferenceChangeListener { prefs, key ->
Log.d("TAG", "キーが変更されました: $key")
}
Android 12(API 31)以降、SharedPreferencesはLifecycleを介した自動サブスクリプション解除を備えたregisterOnSharedPreferenceChangeListenerのサポートで強化されました。これにより、忘れられたリスナーに関連するメモリリークを回避できます。古いバージョンでは、開発者はコンポーネントのonDestroyまたはonStopで手動でunregisterOnSharedPreferenceChangeListenerを呼び出す必要があります。
その広範な使用にもかかわらず、SharedPreferencesはAndroid上のすべてのデータストレージシナリオに対する普遍的なソリューションではありません。データ量、型安全性の要件、パフォーマンスに応じて、GoogleはAndroid Jetpackおよび標準Androidライブラリに含まれるさまざまな代替手段を推奨しています。
| ソリューション | 使用するケース | 欠点 |
|---|---|---|
| SharedPreferences | 小規模設定(最大100キー) | 型安全性なし、同期的読み取り |
| DataStore | コルーチンを使用した中程度の複雑さの設定 | API 14未満では後方互換性なし |
| Room | 構造化データとリスト | 3-5設定には過剰 |
| EncryptedSharedPreferences | 機密データとトークン | AndroidX Securityに依存 |
DataStoreは、GoogleがSharedPreferencesの代替として発表したAndroid Jetpackライブラリです。2つのバリエーションを提供します:Preferences DataStore(SharedPreferencesのようなキー値)とProto DataStore(Protocol Buffersを介した型付きストレージ)。DataStoreは非同期操作にコルーチンとFlowを使用し、型安全性を保証し、バージョンマイグレーションを自動的に処理します。Googleはすべての新しいプロジェクトにDataStoreを推奨しています。
DataStoreの主な利点はAPIレベルの非同期性です。すべての読み取り操作はFlowを返し、書き込み操作はサスペンド関数です。これにより、SharedPreferencesの同期的読み取りで発生する可能性のあるUIスレッドのブロッキングが完全に排除されます。さらに、DataStoreはデータの一貫性を保証します:書き込みはトランザクションで実行され、失敗した場合はすべての変更がロールバックされます。
実用的な例を考えてみましょう:Androidアプリでのテーマ設定(ライト/ダーク/システム)。ユーザーがテーマを選択すると、その選択はSharedPreferencesに保存されます。後続のアプリ起動時には、保存された設定からテーマが復元されます。リアクティブなUI更新には、SharedPreferences.OnSharedPreferenceChangeListenerを介した変更の監視が使用されます。
テーマに関するSharedPreferencesとの連携をすべてカプセル化するThemePreferencesクラスを作成しましょう。このクラスはgetTheme(読み取り)、setTheme(書き込み)、observeTheme(監視)メソッドを提供します。設定ファイル名はMODE_PRIVATEモードで「app_preferences」とします。便宜上、キーはコンパニオンオブジェクトに定数として配置されています。
class ThemePreferences(context: Context) {
companion object {
private const val PREF_NAME = "app_preferences"
private const val KEY_THEME = "theme_mode"
const val THEME_LIGHT = "light"
const val THEME_DARK = "dark"
const val THEME_SYSTEM = "system"
}
private val prefs = context
.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
fun getTheme(): String =
prefs.getString(KEY_THEME, THEME_SYSTEM) ?: THEME_SYSTEM
fun setTheme(theme: String) {
prefs.edit { putString(KEY_THEME, theme) }
}
fun observeTheme(callback: (String) -> Unit) {
prefs.registerOnSharedPreferenceChangeListener { _, key ->
if (key == KEY_THEME) {
callback.invoke(getTheme())
}
}
}
}
ActivityまたはFragmentでは、ThemePreferencesインスタンスの取得はアプリコンテキストを介して行われます。初期化時に、現在のテーマを設定するためにgetThemeが呼び出されます。ユーザーが新しいテーマを選択するとsetThemeが呼び出され、observeThemeを介してActivityを再起動せずにインターフェースが更新されます。メモリリークを防ぐために、特に設定変更時にActivityが再作成される場合、onDestroyでリスナーのサブスクリプションを解除することが重要です。
最小ターゲットバージョンがAndroid 12+のアプリでは、LifecycleObserverと組み合わせてregisterOnSharedPreferenceChangeListenerを使用することをお勧めします。これにより、コンポーネントのライフサイクル変更時にサブスクリプションとその解除が自動的に管理されます。古いバージョンでは、サブスクリプションとその解除を手動で管理する必要があり、これはSharedPreferencesを使用するプロダクションアプリでよくあるエラーの原因です。
よくある質問
SharedPreferencesはプリミティブ型とSet<String>のみを直接サポートしています。オブジェクトを保存するには、GsonやMoshiを介してJSON文字列にシリアライズし、putStringで保存し、読み取り時にデシリアライズする必要があります。多くのフィールドを持つ複雑なオブジェクトの場合は、JSONシリアライゼーションを使用したSharedPreferencesの代わりにRoomを使用することをお勧めします。
はい、SharedPreferencesはスレッドセーフです。すべての読み取りおよび書き込み操作は、SharedPreferencesオブジェクトとそのEditorレベルで同期化されます。ただし、マルチプロセスモードを使用する場合、同期は保証されません。単一のアプリ内で複数のスレッドから同時にアクセスする場合、SharedPreferencesは追加のロックなしで安全です。
SharedPreferencesからすべてのデータを完全にクリアするには、Editorでclear()メソッドを呼び出し、applyを介して変更を適用します。XMLファイル自体を削除する必要がある場合は、コンテキストでdeleteSharedPreferences(name)を使用します。設定→アプリ→データを消去からアプリデータをクリアすると、すべてのSharedPreferencesファイルも削除されます。
新しいプロジェクトでは、GoogleはSharedPreferencesの代替としてDataStoreを推奨しています。DataStoreはコルーチンを使用した非同期操作、型安全性(Proto DataStore)、自動マイグレーションを提供します。SharedPreferencesは、API 14未満の最小バージョンのプロジェクト、または追加の依存関係なしで迅速な統合が必要な場合にのみ選択すべきです。
データ暗号化には、AndroidX SecurityライブラリのEncryptedSharedPreferencesを使用してください。これはAES-256 GCMを使用してキーと値を自動的に暗号化します。セットアッププロセスは最小限です:getSharedPreferencesを、Android Keystoreのマスターキーを指定したEncryptedSharedPreferences.createに置き換えます。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。