SharedPreferences

Androidキャッシュデータ保存キー値ストア設定保存

キャッシュライブラリ

SharedPreferences

概要

SharedPreferencesは、Androidアプリケーションで小さなキー値ペアのコレクションを保存するためのインターフェースで、自動的にキャッシュされ効率的なデータアクセスを提供します。

詳細

SharedPreferencesは、比較的小さなキー値のコレクションを保存するために使用されるAndroidの標準的なデータ保存機能です。SharedPreferencesオブジェクトは、キー値ペアを含むファイルを指し、それらを読み書きするためのシンプルなメソッドを提供します。各SharedPreferencesファイルはフレームワークによって管理され、プライベートまたは共有可能です。重要な特徴として、SharedPreferencesは自動的にキャッシュされます。特定のSharedPreferencesへの最初のアクセス時にXMLファイルがロードされ、その後の読み取りはキャッシュから動作するため、非常に効率的です。アプリケーション設定、ユーザー設定、簡単な状態情報の保存に適しています。

メリット・デメリット

メリット

  • 自動キャッシュ: フレームワークが自動的にキャッシュを管理
  • 高速アクセス: 初回ロード後はメモリキャッシュから高速読み取り
  • シンプルAPI: 直感的で使いやすいメソッド群
  • 型安全: 型別のgetterメソッドでタイプセーフな操作
  • 永続化: アプリ再起動後もデータが保持される
  • アトミック操作: commitとapplyによる安全な書き込み

デメリット

  • 小データ向け: 大容量データには不向き
  • XML形式: 複雑なデータ構造は保存できない
  • メインスレッド: 同期操作はメインスレッドをブロック
  • 型制限: プリミティブ型とStringのみサポート
  • 非推奨: DataStoreが推奨される新しい代替手段

主要リンク

書き方の例

基本的な使用方法

// SharedPreferencesインスタンスの取得
SharedPreferences sharedPref = getSharedPreferences("MyAppPrefs", Context.MODE_PRIVATE);

// データの保存
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString("username", "john_doe");
editor.putInt("user_age", 25);
editor.putBoolean("is_logged_in", true);
editor.apply(); // 非同期で保存

// データの読み取り
String username = sharedPref.getString("username", "");
int age = sharedPref.getInt("user_age", 0);
boolean isLoggedIn = sharedPref.getBoolean("is_logged_in", false);

Activity でのデフォルト SharedPreferences

public class MainActivity extends AppCompatActivity {
    private SharedPreferences prefs;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        // デフォルトのSharedPreferencesを使用
        prefs = PreferenceManager.getDefaultSharedPreferences(this);
        
        // 初回起動チェック
        if (isFirstLaunch()) {
            showWelcomeScreen();
            setFirstLaunchCompleted();
        }
    }
    
    private boolean isFirstLaunch() {
        return prefs.getBoolean("first_launch", true);
    }
    
    private void setFirstLaunchCompleted() {
        prefs.edit()
             .putBoolean("first_launch", false)
             .apply();
    }
}

ユーザー設定の保存と読み込み

public class SettingsManager {
    private static final String PREFS_NAME = "AppSettings";
    private static final String KEY_THEME = "theme";
    private static final String KEY_NOTIFICATIONS = "notifications_enabled";
    private static final String KEY_LANGUAGE = "language";
    
    private Context context;
    private SharedPreferences prefs;
    
    public SettingsManager(Context context) {
        this.context = context;
        this.prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
    }
    
    // テーマ設定
    public void setTheme(String theme) {
        prefs.edit()
             .putString(KEY_THEME, theme)
             .apply();
    }
    
    public String getTheme() {
        return prefs.getString(KEY_THEME, "light");
    }
    
    // 通知設定
    public void setNotificationsEnabled(boolean enabled) {
        prefs.edit()
             .putBoolean(KEY_NOTIFICATIONS, enabled)
             .apply();
    }
    
    public boolean isNotificationsEnabled() {
        return prefs.getBoolean(KEY_NOTIFICATIONS, true);
    }
    
    // 言語設定
    public void setLanguage(String language) {
        prefs.edit()
             .putString(KEY_LANGUAGE, language)
             .apply();
    }
    
    public String getLanguage() {
        return prefs.getString(KEY_LANGUAGE, "en");
    }
}

セッション管理

public class SessionManager {
    private static final String PREF_NAME = "UserSession";
    private static final String KEY_IS_LOGGED_IN = "isLoggedIn";
    private static final String KEY_USER_TOKEN = "userToken";
    private static final String KEY_USER_ID = "userId";
    private static final String KEY_LOGIN_TIME = "loginTime";
    
    private SharedPreferences pref;
    private SharedPreferences.Editor editor;
    private Context context;
    
    public SessionManager(Context context) {
        this.context = context;
        pref = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
        editor = pref.edit();
    }
    
    public void createLoginSession(String token, String userId) {
        editor.putBoolean(KEY_IS_LOGGED_IN, true);
        editor.putString(KEY_USER_TOKEN, token);
        editor.putString(KEY_USER_ID, userId);
        editor.putLong(KEY_LOGIN_TIME, System.currentTimeMillis());
        editor.commit(); // 即座に保存
    }
    
    public boolean isLoggedIn() {
        return pref.getBoolean(KEY_IS_LOGGED_IN, false);
    }
    
    public String getUserToken() {
        return pref.getString(KEY_USER_TOKEN, null);
    }
    
    public String getUserId() {
        return pref.getString(KEY_USER_ID, null);
    }
    
    public void logoutUser() {
        editor.clear();
        editor.apply();
        
        // ログイン画面にリダイレクト
        Intent intent = new Intent(context, LoginActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent);
    }
    
    public boolean isSessionExpired() {
        long loginTime = pref.getLong(KEY_LOGIN_TIME, 0);
        long currentTime = System.currentTimeMillis();
        long sessionDuration = 24 * 60 * 60 * 1000; // 24時間
        
        return (currentTime - loginTime) > sessionDuration;
    }
}

Kotlinでの使用例

class PreferenceHelper(context: Context) {
    companion object {
        private const val PREF_NAME = "MyAppPrefs"
        private const val KEY_USER_NAME = "user_name"
        private const val KEY_USER_EMAIL = "user_email"
        private const val KEY_IS_FIRST_RUN = "is_first_run"
    }
    
    private val prefs: SharedPreferences = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
    
    var userName: String
        get() = prefs.getString(KEY_USER_NAME, "") ?: ""
        set(value) = prefs.edit().putString(KEY_USER_NAME, value).apply()
    
    var userEmail: String
        get() = prefs.getString(KEY_USER_EMAIL, "") ?: ""
        set(value) = prefs.edit().putString(KEY_USER_EMAIL, value).apply()
    
    var isFirstRun: Boolean
        get() = prefs.getBoolean(KEY_IS_FIRST_RUN, true)
        set(value) = prefs.edit().putBoolean(KEY_IS_FIRST_RUN, value).apply()
    
    fun clearAllData() {
        prefs.edit().clear().apply()
    }
}

// 使用例
class MainActivity : AppCompatActivity() {
    private lateinit var prefHelper: PreferenceHelper
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        prefHelper = PreferenceHelper(this)
        
        // データの読み書き
        prefHelper.userName = "John Doe"
        val name = prefHelper.userName
        
        if (prefHelper.isFirstRun) {
            // 初回起動時の処理
            setupFirstRun()
            prefHelper.isFirstRun = false
        }
    }
}

リスナーを使った変更監視

public class PreferenceWatcher implements SharedPreferences.OnSharedPreferenceChangeListener {
    private SharedPreferences prefs;
    
    public void startWatching(Context context) {
        prefs = PreferenceManager.getDefaultSharedPreferences(context);
        prefs.registerOnSharedPreferenceChangeListener(this);
    }
    
    public void stopWatching() {
        if (prefs != null) {
            prefs.unregisterOnSharedPreferenceChangeListener(this);
        }
    }
    
    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
        switch (key) {
            case "theme_setting":
                String newTheme = sharedPreferences.getString(key, "light");
                applyTheme(newTheme);
                break;
                
            case "notification_enabled":
                boolean notificationsEnabled = sharedPreferences.getBoolean(key, true);
                updateNotificationSettings(notificationsEnabled);
                break;
                
            case "language_setting":
                String language = sharedPreferences.getString(key, "en");
                updateLanguage(language);
                break;
        }
    }
    
    private void applyTheme(String theme) {
        // テーマ変更処理
    }
    
    private void updateNotificationSettings(boolean enabled) {
        // 通知設定変更処理
    }
    
    private void updateLanguage(String language) {
        // 言語変更処理
    }
}

暗号化されたSharedPreferences

// EncryptedSharedPreferencesの使用(API 23+)
public class SecurePreferenceManager {
    private static final String FILE_NAME = "encrypted_prefs";
    private SharedPreferences encryptedPrefs;
    
    public SecurePreferenceManager(Context context) {
        try {
            MasterKey masterKey = new MasterKey.Builder(context)
                .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
                .build();
            
            encryptedPrefs = EncryptedSharedPreferences.create(
                context,
                FILE_NAME,
                masterKey,
                EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
                EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
            );
        } catch (Exception e) {
            e.printStackTrace();
            // フォールバック:通常のSharedPreferences
            encryptedPrefs = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);
        }
    }
    
    public void saveSecureData(String key, String value) {
        encryptedPrefs.edit()
            .putString(key, value)
            .apply();
    }
    
    public String getSecureData(String key, String defaultValue) {
        return encryptedPrefs.getString(key, defaultValue);
    }
}