設定画面と、設定値のファイル保存が一体となっているAndroidのPreferenceの使い方メモ
Preferenceの保存先
Preferenceの保存は、/data/data/com.example.test_app/shared_prefs/○○○.xmlにXML形式で保存されている。なお、ファイラーなどで確認する場合は、ルート権限が必要。xmlは次のような内容となっている。
<?xml version='1.0' encoding='utf-8' standalone='yes' ?> <map> <boolean name="keyCheckboxPref" value="true" /> <string name="keyEditTextPref">test</string> <string name="keyListPref">2</string> <string name="ringtone_pref">content://settings/system/ringtone</string> </map>
値をPreferenceに格納、読出する単純例
書き込みは次のように行う。書き込む変数の種類により、putBoolean, putInt, putFloat, putLong, putString, putStringSet などがあるので適宜使い分ける。
SharedPreferences pref = getSharedPreferences("SAMPLE_DIR_1", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = pref.edit();
editor.putString("TEST_ITEM_1", "テスト文字列");
editor.commit();
読み込みはこのような感じで
SharedPreferences pref = getSharedPreferences("SAMPLE_DIR_1", Context.MODE_PRIVATE);
String str = pref.getString("TEST_ITEM_1", "デフォルト値");
プリファレンス・データは、
/data/data/com.example.test_app/shared_prefs/SAMPLE_DIR_1.xmlに書き込まれる。
プリファレンス画面を表示する単純例(API 10以下も対応)
■ プリファレンス画面 XML の新規作成
Eclipseのパッケージ・エクスプローラまたはナビゲーターで、プロジェクトを選択した状態で、「ファイル」ー「新規」ー「その他」を選択して、「Android XMLファイル」の生成を選択する。
「リソース・タイプ」を“Preference”とし、「ルート要素」は“PreferenceScreen”として、「完了」ボタンを押す。
開発環境で生成されたres/xmlファイルを開き、
作成したいリソース、今回はチェックボックスを追加し、“Attribute from Preference”カテゴリーの“Key”と“Title”を記述する。“Key”は実際にXMLに書き込まれる時のキー名になるので、他のプリファレンス画面と重複しないようにする。
このようにして完成したプリファレンスxmlファイルは次のようなものになる
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<CheckBoxPreference android:key="TEST_CHECKBOX" android:title="チェックボックス"/>
</PreferenceScreen>
■ プリファレンス画面のクラスの新規作成
次に、このプリファレンスxmlを実装するクラスを作成する。
Eclipseのパッケージ・エクスプローラまたはナビゲーターで、プロジェクトを選択した状態で、「ファイル」ー「新規」ー「クラス」の新規作成を行う。
赤で囲った部分を設定していく。「スーパークラス」は“PreferenceActivity”クラスを指定する。クラスを作成したら、それを開いて、onCreate関数を作成する。パッケージ・エクスプローラまたはナビゲーターで、今回作成したプリファレンスのクラスを選択した状態で、「ソース」ー「メソッドのオーバーライド/実装」を選択する。
メソッド一覧の所で、キーボードから関数名を入力すると、インクリメントサーチが掛かる。onCreateのチェックボックスをONにして、OKボタンを押す。
最終的に、プリファレンスのクラスファイルは次のようになる。
package com.example.android_test_prefs;
import android.os.Bundle;
import android.preference.PreferenceActivity;
public class PreferenceTest extends PreferenceActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO 自動生成されたメソッド・スタブ
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preference_test);
}
}
赤で着色した部分のみ、手入力している。ここで、プリファレンス画面設計のxmlを紐付けている。プリファレンス・データの保存のためのコーディング無いのは、これが全て自動で行われてしまうから。さすが、便利だ…
プリファレンス・データの実体ファイルは
/data/data/com.example.test_app/shared_prefs/com.example.test_app_preferences.xml
に保存される。
■ プリファレンス画面の呼び出しと、値の取り出しの実装 (MainActivity)
そして、MainActivityからプリファレンス画面を呼び出す処理などを追加すれば、サンプルコードの完成だ。
package com.example.android_test_prefs;
import android.support.v7.app.ActionBarActivity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
public class MainActivity extends ActionBarActivity {
final int REQUEST_PREF_MENU = 0x1010;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if(id == R.id.menu_pref_old){
Intent intent = new Intent(this, PreferenceTest.class);
startActivityForResult(intent, REQUEST_PREF_MENU);
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onActivityResult(int arg0, int arg1, Intent arg2) {
// TODO 自動生成されたメソッド・スタブ
super.onActivityResult(arg0, arg1, arg2);
if(arg0 == REQUEST_PREF_MENU){
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
Boolean bool_checkbox = pref.getBoolean("TEST_CHECKBOX", false);
if(bool_checkbox) Toast.makeText(MainActivity.this, "チェックボックスは ON", Toast.LENGTH_LONG).show();
else Toast.makeText(MainActivity.this, "チェックボックスは OFF", Toast.LENGTH_LONG).show();
}
}
}
緑で着色した部分はEclipseで自動生成した所、赤で書かれた部分がて入力した所。intentの受け取り側関数onActivityResultも、プリファレンスのonCreate関数作成と同じく、ほぼ自動生成に頼っている。
■ 新規作成したプリファレンス画面クラスのjavaファイルをプロジェクトに追加する
プロジェクトを実行する前に、作成したプリファレンス・クラスを読み込むよう、Manifestファイルに追加してやる。AndroidManifest.xmlを開いて、アプリケーション画面の一番下に追加位置がある。
実際のxmlファイルは次のようになる
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android_test_prefs"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="10"
android:targetSdkVersion="16" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="PreferenceTest"></activity>
</application>
</manifest>
プリファレンス画面を表示する単純例(API 11以上の推奨例)
API 11位上ではPreferenceFragmentクラスを使うことが推奨されるため、Android 4以降でしか実行しないプログラムであれば、次のようにコーディングする。
■ プリファレンス画面のクラスの新規作成
Activity クラスでプリファレンス画面のクラスを新規作成し、実際のxmlはその内部クラスにPreferenceFragmentクラスを承継した新規クラスを作成し xml を紐付けるという、ひと手間掛かるめんどくささ…
上の例(API10版)のように、プリファレンス画面の新規クラスを作成し(但し、今回はActivityから派生する)、その後、下に示すような設定で「内部クラス」としてプリファレンス・フラグメントのクラスを作成する。
最終的に、プリファレンス画面のクラスは次のようになる。手入力したのは、赤で着色した部分のみ。
package com.example.android_test_prefs;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.preference.PreferenceFragment;
@SuppressLint("NewApi")
public class PreferenceTestNew extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO 自動生成されたメソッド・スタブ
super.onCreate(savedInstanceState);
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new PreferenceTestFragment())
.commit();
}
public class PreferenceTestFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
// TODO 自動生成されたメソッド・スタブ
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preference_test);
}
}
}
■ プリファレンス画面の呼び出しと、値の取り出しの実装 (MainActivity)
API10での例と同じだが、Android 2系で実行された場合の異常終了を避けるため、下の例のようにチェックを設けてもよい。
if(Build.VERSION.SDK_INT >= 11){
Intent intent = new Intent(this, PreferenceTestNew.class);
startActivityForResult(intent, REQUEST_PREF_MENU);
}
この部分以外はAPI10のサンプルコードと同じ。
PreferenceActivityやAlertDialogを使った画面例

メイン画面(Preference現在値を表示)とメニュー表示

Preference設定画面

Preferenceテキスト入力ダイアログ

Preferenceリスト選択ダイアログ
XMLでPreference設定画面を定義し、表示する場合
■ プリファレンス画面の XML
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<CheckBoxPreference
android:key="keyCheckboxPref"
android:summary="現在の値:-"
android:title="チェックボックス" />
<EditTextPreference
android:key="keyEditTextPref"
android:summary="現在の値:-"
android:title="テキスト入力"
android:inputType="text"
android:maxLength="10" />
<!-- inputType=text : 改行禁止 -->
<ListPreference
android:key="keyListPref"
android:entries="@array/listOptions"
android:entryValues="@array/listValues"
android:summary="現在の値:-"
android:title="リスト選択" />
<PreferenceCategory
android:key="pref_category_2"
android:title="第2階層の設定画面を表示" >
<RingtonePreference
android:key="keyRingtonePref"
android:title="Ringtone"
android:summary="現在の値:-"
android:ringtoneType="ringtone" />
</PreferenceCategory>
</PreferenceScreen>
■ リスト項目定義のXML
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="listOptions">
<item>選択肢1</item>
<item>選択肢2</item>
<item>選択肢3</item>
</string-array>
<string-array name="listValues">
<item>1</item>
<item>2</item>
<item>3</item>
</string-array>
</resources>
■ プリファレンスう画面のクラス
Preferenceへの値の格納は、特にコードを記述しなくても自動で行われる。次のコーディングは、設定値を即時プリファレンス・メニュー画面上(summary)に反映するためのもので、それが必要無いのであれば、このクラス関数onCreateは自動作成された状態の「空」で構わない。
package com.example.android_settings_menu_1;
import android.os.Bundle;
import android.preference.*;
import android.preference.Preference.OnPreferenceChangeListener;
public class SettingsMenu extends PreferenceActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings_menu);
// チェックボックスの現在値表示
CheckBoxPreference cCheckBox1 = (CheckBoxPreference)findPreference("keyCheckboxPref");
// 画面初期化時
if(cCheckBox1.isChecked()){ cCheckBox1.setSummary("現在の値:ON"); }
else{ cCheckBox1.setSummary("現在の値:OFF"); }
// ユーザによる選択書き換え時
cCheckBox1.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference pref, Object value) {
if(((Boolean)value).booleanValue()) {
pref.setSummary("現在の値:ON");
}
else {
pref.setSummary("現在の値:OFF");
}
return true;
}
});
// テキストボックスの現在値表示
EditTextPreference cEditText1 = (EditTextPreference)findPreference("keyEditTextPref");
// 画面初期化時
cEditText1.setSummary("現在の値:" + cEditText1.getText());
// ユーザによる選択書き換え時
cEditText1.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference pref, Object value) {
pref.setSummary("現在の値:" + value.toString());
return true;
}
});
// リスト選択の現在値表示
ListPreference cList1 = (ListPreference)findPreference("keyListPref");
// 画面初期化時
cList1.setSummary("現在の値:" + cList1.getValue());
// ユーザによる選択書き換え時
cList1.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference pref, Object value) {
pref.setSummary("現在の値:" + value.toString());
return true;
}
});
}
}
■ プリファレンスの呼び出し・値の読み込みの実装 (MainActivity)
package com.example.android_settings_menu_1;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBar;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.os.Build;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.app.AlertDialog;
import android.widget.EditText;
import android.text.InputType;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.widget.Toast;
public class MainActivity extends ActionBarActivity {
private int idText = 0x1001;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 現在の設定値を表示するテキスト領域を確保する
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
setContentView(layout);
TextView text = new TextView(this);
text.setId(idText);
layout.addView(text);
// 画面に現在の設定値を表示する
DisplayPrefOnScreen();
}
// 画面に現在の設定値を表示する
private void DisplayPrefOnScreen() {
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
String str;
if(pref.getBoolean("keyCheckboxPref", false)) { str = "チェックボックス:ON\n"; }
else { str = "チェックボックス:ON\n"; }
str = str + "テキスト入力:" + pref.getString("keyEditTextPref", "") + "\n";
str = str + "リスト選択:" + pref.getString("keyListPref", "---");
TextView text = (TextView) this.findViewById(idText);
text.setText(str);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
// SettingsMenuクラスを呼び出して、プリファレンスメニューの初期化と表示を行う
Intent intent = new Intent(this, SettingsMenu.class);
// 設定完了時のコールバック
startActivityForResult(intent, 10011);
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
if (requestCode == 10011){
// 画面に現在の設定値を表示する
DisplayPrefOnScreen();
}
}
}
■ 新規作成したプリファレンス画面クラスのjavaファイルをプロジェクトに追加する
src/.../SettingsMenu.javaを手動登録する必要がある。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android_settings_menu_1"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="10"
android:targetSdkVersion="10" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.android_settings_menu_1.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".SettingsMenu" >
</activity>
</application>
</manifest>
プログラム中でPreferenceデータを読み書きする
メニューにPreferenceデータを読み書きする「テキスト入力」を追加する場合の説明
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
// SettingsMenuクラスを呼び出して、プリファレンスメニューの初期化と表示を行う
Intent intent = new Intent(this, SettingsMenu.class);
// 設定完了時のコールバック
startActivityForResult(intent, 10011);
return true;
}
else if (id == R.id.action_edittext) {
// 現在の「テキスト入力値」をプリファレンスxmlより読みだす
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
String str = pref.getString("keyEditTextPref", "");
// テキスト入力AlertDialogを表示する
final EditText editView = new EditText(MainActivity.this);
editView.setLines(1); // 1行
editView.setInputType(InputType.TYPE_CLASS_TEXT); // 改行を許可しない
// AlertDialogを構築する
AlertDialog.Builder dlg = new AlertDialog.Builder(this);
dlg.setTitle("テキスト入力");
dlg.setView(editView);
editView.setText(str);
dlg.setPositiveButton("OK", new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog, int which) {
// 入力された文字列をプリファレンスxmlに書き込む
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
SharedPreferences.Editor edit = pref.edit();
edit.putString("keyEditTextPref", editView.getText().toString());
edit.commit();
// 画面に現在の設定値を表示する
DisplayPrefOnScreen();
}
});
dlg.setNegativeButton("キャンセル", null);
dlg.show();
return true;
}
return super.onOptionsItemSelected(item);
}
javaでPreference設定画面を定義し、表示する場合
package com.example.android_settings_menu_2;
import android.os.Bundle;
import android.preference.*;
import android.preference.Preference.OnPreferenceChangeListener;
public class SettingsMenu extends PreferenceActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
PreferenceScreen pref = getPreferenceManager().createPreferenceScreen(this);
// チェックボックスを作成
CheckBoxPreference cCheckBox1 = new CheckBoxPreference(this);
cCheckBox1.setKey("keyCheckboxPref");
cCheckBox1.setTitle("チェックボックス");
// メニューに追加
pref.addPreference(cCheckBox1);
// 画面初期化時
if(cCheckBox1.isChecked()){ cCheckBox1.setSummary("現在の値:ON"); }
else{ cCheckBox1.setSummary("現在の値:OFF"); }
// ユーザによる選択書き換え時
cCheckBox1.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference pref, Object value) {
if(((Boolean)value).booleanValue()) {
pref.setSummary("現在の値:ON");
}
else {
pref.setSummary("現在の値:OFF");
}
return true;
}
});
// チェックボックスを作成
EditTextPreference cEditText1 = new EditTextPreference(this);
cEditText1.setKey("keyEditTextPref");
cEditText1.setTitle("テキスト入力");
cEditText1.setDialogTitle("テキスト入力");
// メニューに追加
pref.addPreference(cEditText1);
// 画面初期化時
cEditText1.setSummary("現在の値:" + cEditText1.getText());
// ユーザによる選択書き換え時
cEditText1.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference pref, Object value) {
pref.setSummary("現在の値:" + value.toString());
return true;
}
});
CharSequence[] arrayListTitle = new String[] { "選択肢1", "選択肢2", "選択肢3" };
CharSequence[] arrayListValue = new String[] { "1", "2", "3" };
// リストを作成
ListPreference cList1 = new ListPreference(this);
cList1.setKey("keyListPref");
cList1.setTitle("リスト選択");
cList1.setEntries(arrayListTitle);
cList1.setEntryValues(arrayListValue);
// メニューに追加
pref.addPreference(cList1);
// 画面初期化時
cList1.setSummary("現在の値:" + cList1.getValue());
// ユーザによる選択書き換え時
cList1.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference pref, Object value) {
pref.setSummary("現在の値:" + value.toString());
return true;
}
});
// プリファレンス メニューを画面表示する
setPreferenceScreen(pref);
}
}





