やまものブログ

メモ書きブログです (^_^;A

フォトフレームアプリ (3/4) ー Android 4.1.2 動作OK

2週前に頓挫した LESSON30 (下記)を、ターゲットにしてる 4.1.2 で動かせました

10日でおぼえる Androidアプリ開発入門教室 Android SDK2.3対応
LESSON 30 スライドショーの更新間隔を設定しよう


問題は2週前の冒頭にも述べた下記2つのメソッドが deprecated になったことです。
addPreferencesFromResource(int)
findPreference(CharSequence)

これを暗中模索で対策したところ、アプリは起動するものの、新たに追加された「設定」メニューをクリックすると、"Unfortunately, Chapter08 has stopped." で異常終了するようになりました。そのデバッグが進まずに頓挫していました。

ようやくデバッグできて動いたので、deprecated を含むコードの対策前と対策後を以下に掲載します。

【deprecated 対策前】
11 import android.preference.PreferenceActivity;
12 import android.preference.Preference.OnPreferenceChangeListener;
13
14 public class PhotoFramePreferenceActivity extends PreferenceActivity implements
15     OnPreferenceChangeListener {
16   @Override
17   protected void onCreate(Bundle savedInstanceState) {
18     super.onCreate(savedInstanceState);
19     addPreferencesFromResource(R.xml.prefwidget);
20
21     // 各設定のオブジェクトを取得する
22      ListPreference list = (ListPreference) findPreference("interval_key");
23      CheckBoxPreference chk = (CheckBoxPreference) findPreference("content_key");
24
25     // 変更時のリスナーを設定する
26     list.setOnPreferenceChangeListener(this);
27     chk.setOnPreferenceChangeListener(this);
28 }

【deprecated 対策後】
11 import android.preference.PreferenceFragment;
12 import android.preference.Preference.OnPreferenceChangeListener;
13 import android.app.Activity;
14

15 public class PhotoFramePreferenceActivity extends Activity implements
16     OnPreferenceChangeListener {
17   @Override
18   protected void onCreate(Bundle savedInstanceState) {
19     super.onCreate(savedInstanceState);
20     PrefsFragment pf = new PrefsFragment();
21        getFragmentManager().beginTransaction()
22            .replace(android.R.id.content, pf).commit();
23    }
24
25   public class PrefsFragment extends PreferenceFragment {
26     @Override
27     public void onCreate(Bundle savedInstanceState) {
28       super.onCreate(savedInstanceState);
29       addPreferencesFromResource(R.xml.prefwidget);
30
31       // 各設定のオブジェクトを取得する
32       ListPreference list = (ListPreference)findPreference("interval_key");
33        CheckBoxPreference chk = (CheckBoxPreference)findPreference("content_key");
34
35       // 変更時のリスナーを設定する
36       list.setOnPreferenceChangeListener(PhotoFramePreferenceActivity.this);
37        chk.setOnPreferenceChangeListener(PhotoFramePreferenceActivity.this);
38   }
39
40 }

修正のポイントは以下の通りで、上記コードの赤字で示したクラス名やメソッドが鍵です。
修正内容は  PreferenceActivityPreferenceFragment に置き換えたことと要約できそうです。

1) [L.11] import するパッケージを変更
2) [L.14] PhotoFramePreferenceActivity の親クラスは Activity に変更
3) [修正後 L.25] PreferenceFragment を継承する内部クラス PrefsFragment を新設
4) [修正後 L.27,L.29,L.32,L.33] その onCreate() の中で  addPreferencesFromResource() と findPreference() を使う
5) [修正後 L.36,L37] アウタークラス PhotoFramePreferenceActivity を .this で参照
6) [修正後 L.20-22] 新設した内部クラス PrefsFragment を使ってお呪いを唱える


PreferenceFragment を理解していなく内容を技術解説できませんので、とりあえず SDK 4.1.2 でそれっぽく動いたという事実だけご報告します。


最後に、"Unfortunately, Chapter08 has stopped." で異常終了していた直接の原因についてです。上記の修正後のコードでは findPreference()を PrefsFragment クラスの onCreate()内でコールしています。異常終了していた時のコードでは、onCreate()の外でコールしていて、findPreference()が null を返していました。findPreference() は onCreate() のスコープ内でしか使えないのだろうか…
このあたりも、いずれは PreferenceFragment を体系的に理解してスッキリさせたい…