I am following this guide to learn about 'Creating App Settings using Preference Headers'. This question deals with "Supporting older (than HoneyComb) versions with preference headers".
I think I have followed all the steps, but still am getting this exception. So what am I missing?
LOG:
...
07-10 18:45:31.935: E/AndroidRuntime(1285): FATAL EXCEPTION: main
07-10 18:45:31.935: E/AndroidRuntime(1285): java.lang.RuntimeException: Unable to start activity ComponentInfo{practice_projects.minimalpreferencesusingpreferenceheadersoldversions/practice_projects.minimalpreferencesusingpreferenceheadersoldversions.MyPreferenceActivity}: java.lang.ClassCastException: practice_projects.minimalpreferencesusingpreferenceheadersoldversions.MyPreferenceFragment cannot be cast to android.app.Fragment
...
07-10 18:45:31.935: E/AndroidRuntime(1285): Caused by: java.lang.ClassCastException: practice_projects.minimalpreferencesusingpreferenceheadersoldversions.MyPreferenceFragment cannot be cast to android.app.Fragment
...
07-10 18:45:31.935: E/AndroidRuntime(1285): at practice_projects.minimalpreferencesusingpreferenceheadersoldversions.MyPreferenceActivity.onCreate(MyPreferenceActivity.java:16)
...
MainActivity.java:
public class MainActivity extends FragmentActivity implements DrawerLayout.DrawerListener, ListView.OnItemClickListener {
private static final String TAG = MainActivity.class.getSimpleName();
private final String [] drawerListItems = {"Settings"};
private DrawerLayout drawerLayout;
private FrameLayout frameLayout;
private ListView drawerListView;
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);//******LINE # 16***********
drawerListView = (ListView) findViewById(R.id.mainActivity_listView);
drawerListView.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, drawerListItems));
drawerListView.setOnItemClickListener(this);
drawerLayout = (DrawerLayout) findViewById(R.id.mainActivity_drawerLayout);
drawerLayout.setDrawerListener(this);
frameLayout = (FrameLayout) findViewById(R.id.mainActivity_frameLayout);
textView = (TextView) findViewById(R.id.mainActivity_textView);
}
/****************************************************************************************************************************************/
/************************************************DrawerLayout.DrawerListener IMPLEMENTATION**********************************************/
/****************************************************************************************************************************************/
@Override
public void onDrawerClosed(View arg0) {
frameLayout.setBackgroundColor(Color.parseColor("#6A0888")); /* Dark Purple Color */
}
@Override
public void onDrawerOpened(View arg0) {
frameLayout.setBackgroundColor(Color.parseColor("#FE642E")); /* Orange Color */
}
@Override
public void onDrawerSlide(View arg0, float arg1) {}
@Override
public void onDrawerStateChanged(int arg0) {}
/****************************************************************************************************************************************/
/************************************************OnDrawerClickListener IMPLEMENTATION**********************************************/
/****************************************************************************************************************************************/
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
frameLayout.setBackgroundColor(Color.parseColor("#F7FE2E")); /* Yellow Color */
startActivity(new Intent(this, MyPreferenceActivity.class));
drawerListView.setItemChecked(position, true);
drawerLayout.closeDrawer(drawerListView);
}
}
MyPreferenceActivity.java:
public class MyPreferenceActivity extends PreferenceActivity {
private static final String TAG = MyPreferenceActivity.class.getSimpleName();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(TAG, "onCreate of MyPreferenceActivity called.");// check
String intentAction = getIntent().getAction();
Log.i(TAG, "The action retrieved from the intent is " + intentAction + ".");// check
if (intentAction != null && intentAction.equals("practice_projects.minimalpreferencesusingpreferenceheadersoldversions.DB")) {
Log.i(TAG, "YES intentAction!=null && intentAction.equals(\"practice_projects.minimalpreferencesusingpreferenceheadersoldversions.DB\"");// check
addPreferencesFromResource(R.xml.db_preferences);
Log.i(TAG, "Added preferences from R.xml.db_preferences.");// check
} else if (intentAction != null && intentAction.equals("practice_projects.minimalpreferencesusingpreferenceheadersoldversions.UI")) {
Log.i(TAG, "YES intentAction!=null && intentAction.equals(\"practice_projects.minimalpreferencesusingpreferenceheadersoldversions.UI\"");// check
addPreferencesFromResource(R.xml.ui_preferences);
Log.i(TAG, "Added preferences from R.xml.ui_preferences.");// check
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
Log.i(TAG, "Build version is LESS than honeycomb.");// check
// Load the preference_headers_legacy.xml
addPreferencesFromResource(R.xml.preference_headers_legacy);
Log.i(TAG, "Added preferences from R.xml.preference_headers_legacy.");// check
} else {
Log.i(TAG, "Build version is HIGHER than honeycomb. "
+ "NO *******intentAction!=null && intentAction.equals(\"practice_projects.minimalpreferencesusingpreferenceheadersoldversions"
+ ".DB\"*******."
+ " NO *******intentAction!=null && intentAction.equals(\"practice_projects.minimalpreferencesusingpreferenceheadersoldversions"
+ ".UI\"*******.");// check
}
}
// Called only on HoneyComb and later
// Although the @TargetApi annotation is not for compiler, and is for Lint only, but no problem, as the system will call this method for honeycomb and later
// only
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
public void onBuildHeaders(List<Header> target) {
loadHeadersFromResource(R.xml.preference_headers, target);
}
}
MyPreferenceFragment.java:
public class MyPreferenceFragment extends PreferenceFragment {
private static final String TAG = MyPreferenceFragment.class.getSimpleName();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String preferenceHeaderExtraValue = getArguments().getString("preference_extra_key");
if (preferenceHeaderExtraValue!=null) {
if (preferenceHeaderExtraValue.equals("db")) {
//getView().setBackgroundColor(Color.parseColor("#81F7BE")); /* Aqua towards green */ //NPE because the layout is not created yet**********
Log.i(TAG, "The value of the preference intent with the key "+preferenceHeaderExtraValue+" is \"db\".");
addPreferencesFromResource(R.xml.db_preferences);
} else if (preferenceHeaderExtraValue.equals("ui")) {
//getView().setBackgroundColor(Color.parseColor("#A9D0F5")); /* Aqua towards blue */ //NPE because the layout is not created yet**********
Log.i(TAG, "The value of the preference intent with the key "+preferenceHeaderExtraValue+" is \"ui\".");
addPreferencesFromResource(R.xml.ui_preferences);
} else {
Log.i(TAG, "The value of the preference intent with the key "+preferenceHeaderExtraValue+" is neither \"db\" nor \"ui\".");
}
} else {
Log.i(TAG, "getArguments() returns null.");
}
}
}
PreferenceFragment.java (Taken from PreferenceFragment for Pre-HoneyComb by Christophe Beyls):
/**
* A PreferenceFragment for the support library. Based on the platform's code with some removed features and a basic ListView layout.
*
* @author Christophe Beyls https://gist.github.com/cbeyls/7475726
*
*/
public abstract class PreferenceFragment extends Fragment {
private static final int FIRST_REQUEST_CODE = 100;
private static final int MSG_BIND_PREFERENCES = 1;
private static final int MSG_REQUEST_FOCUS = 2;
private static final String PREFERENCES_TAG = "android:preferences";
private static final float HC_HORIZONTAL_PADDING = 16;
@SuppressLint("HandlerLeak")
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_BIND_PREFERENCES:
bindPreferences();
break;
case MSG_REQUEST_FOCUS:
mList.focusableViewAvailable(mList);
break;
}
}
};
private boolean mHavePrefs;
private boolean mInitDone;
private ListView mList;
private PreferenceManager mPreferenceManager;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
Constructor<PreferenceManager> c = PreferenceManager.class.getDeclaredConstructor(Activity.class, int.class);
c.setAccessible(true);
mPreferenceManager = c.newInstance(this.getActivity(), FIRST_REQUEST_CODE);
} catch (Exception ignored) {
}
}
@Override
public View onCreateView(LayoutInflater layoutInflater, ViewGroup viewGroup, Bundle savedInstanceState) {
ListView listView = new ListView(getActivity());
listView.setId(android.R.id.list);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
final int horizontalPadding = (int) (HC_HORIZONTAL_PADDING * getResources().getDisplayMetrics().density);
listView.setPadding(horizontalPadding, 0, horizontalPadding, 0);
}
return listView;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (mHavePrefs) {
bindPreferences();
}
mInitDone = true;
if (savedInstanceState != null) {
Bundle container = savedInstanceState.getBundle(PREFERENCES_TAG);
if (container != null) {
final PreferenceScreen preferenceScreen = getPreferenceScreen();
if (preferenceScreen != null) {
preferenceScreen.restoreHierarchyState(container);
}
}
}
}
public void onStop() {
super.onStop();
try {
Method m = PreferenceManager.class.getDeclaredMethod("dispatchActivityStop");
m.setAccessible(true);
m.invoke(mPreferenceManager);
} catch (Exception ignored) {
}
}
public void onDestroyView() {
mList = null;
mHandler.removeCallbacksAndMessages(null);
super.onDestroyView();
}
public void onDestroy() {
super.onDestroy();
try {
Method m = PreferenceManager.class.getDeclaredMethod("dispatchActivityDestroy");
m.setAccessible(true);
m.invoke(mPreferenceManager);
} catch (Exception ignored) {
}
}
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
PreferenceScreen preferenceScreen = getPreferenceScreen();
if (preferenceScreen != null) {
Bundle container = new Bundle();
preferenceScreen.saveHierarchyState(container);
outState.putBundle(PREFERENCES_TAG, container);
}
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
try {
Method m = PreferenceManager.class.getDeclaredMethod("dispatchActivityResult", int.class, int.class, Intent.class);
m.setAccessible(true);
m.invoke(mPreferenceManager, requestCode, resultCode, data);
} catch (Exception ignored) {
}
}
public PreferenceManager getPreferenceManager() {
return mPreferenceManager;
}
public void setPreferenceScreen(PreferenceScreen screen) {
try {
Method m = PreferenceManager.class.getDeclaredMethod("setPreferences", PreferenceScreen.class);
m.setAccessible(true);
boolean result = (Boolean) m.invoke(mPreferenceManager, screen);
if (result && (screen != null)) {
mHavePrefs = true;
if (mInitDone) {
postBindPreferences();
}
}
} catch (Exception ignored) {
}
}
public PreferenceScreen getPreferenceScreen() {
try {
Method m = PreferenceManager.class.getDeclaredMethod("getPreferenceScreen");
m.setAccessible(true);
return (PreferenceScreen) m.invoke(mPreferenceManager);
} catch (Exception e) {
return null;
}
}
public void addPreferencesFromIntent(Intent intent) {
requirePreferenceManager();
try {
Method m = PreferenceManager.class.getDeclaredMethod("inflateFromIntent", Intent.class, PreferenceScreen.class);
m.setAccessible(true);
PreferenceScreen screen = (PreferenceScreen) m.invoke(mPreferenceManager, intent, getPreferenceScreen());
setPreferenceScreen(screen);
} catch (Exception ignored) {
}
}
public void addPreferencesFromResource(int resId) {
requirePreferenceManager();
try {
Method m = PreferenceManager.class.getDeclaredMethod("inflateFromResource", Context.class, int.class, PreferenceScreen.class);
m.setAccessible(true);
PreferenceScreen screen = (PreferenceScreen) m.invoke(mPreferenceManager, getActivity(), resId, getPreferenceScreen());
setPreferenceScreen(screen);
} catch (Exception ignored) {
}
}
public Preference findPreference(CharSequence key) {
if (mPreferenceManager == null) {
return null;
}
return mPreferenceManager.findPreference(key);
}
private void requirePreferenceManager() {
if (this.mPreferenceManager == null) {
throw new RuntimeException("This should be called after super.onCreate.");
}
}
private void postBindPreferences() {
if (!mHandler.hasMessages(MSG_BIND_PREFERENCES)) {
mHandler.sendEmptyMessage(MSG_BIND_PREFERENCES);
}
}
private void bindPreferences() {
final PreferenceScreen preferenceScreen = getPreferenceScreen();
if (preferenceScreen != null) {
preferenceScreen.bind(getListView());
}
}
public ListView getListView() {
ensureList();
return mList;
}
private void ensureList() {
if (mList != null) {
return;
}
View root = getView();
if (root == null) {
throw new IllegalStateException("Content view not yet created");
}
View rawListView = root.findViewById(android.R.id.list);
if (rawListView == null) {
throw new RuntimeException("Your content must have a ListView whose id attribute is 'android.R.id.list'");
}
if (!(rawListView instanceof ListView)) {
throw new RuntimeException("Content has view with id attribute 'android.R.id.list' that is not a ListView class");
}
mList = (ListView) rawListView;
mHandler.sendEmptyMessage(MSG_REQUEST_FOCUS);
}
preference_headers.xml:
<?xml version="1.0" encoding="utf-8"?>
<preference-headers xmlns:android="http://schemas.android.com/apk/res/android" >
<header
android:fragment="practice_projects.minimalpreferencesusingpreferenceheadersoldversions.MyPreferenceFragment"
android:title="@string/preferenceHeaders_title1"
android:summary="@string/preferenceHeaders_summary1" >
<extra android:name="preference_extra_key" android:value="db" />
</header>
<header
android:fragment="practice_projects.minimalpreferencesusingpreferenceheadersoldversions.MyPreferenceFragment"
android:title="@string/preferenceHeaders_title2"
android:summary="@string/preferenceHeaders_summary2" >
<extra android:name="preference_extra_key" android:value="ui" />
</header>
</preference-headers>
ui_preferences.xml:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<EditTextPreference
android:title="@string/UIPreferences_editTextPreference_title"
android:summary="@string/UIPreferences_editTextPreference_summary"
android:key="preferences_UIPditTextPreference_key"
android:defaultValue="UIPreferences_editTextPreference_defaultValue" />
<EditTextPreference
android:title="@string/UIPreferences_editTextPreference_title1"
android:summary="@string/UIPreferences_editTextPreference_summary1"
android:key="UIPreferences_editTextPreference_key1"
android:defaultValue="UIPreferences_editTextPreference_defaultValue1" />
</PreferenceScreen>
db_preferences.xml:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<CheckBoxPreference
android:title="@string/DBPreferences_checkBoxPreference_title"
android:summary="@string/DBPreferences_checkBoxPreference_summary"
android:key="DBPreferences_checkBoxPreference_key"
android:defaultValue="DBPreferences_checkBoxPreference_defaultValue" />
<CheckBoxPreference
android:title="@string/DBPreferences_checkBoxPreference_title1"
android:summary="@string/DBPreferences_checkBoxPreference_summary1"
android:key="DBPreferences_checkBoxPreference_key1"
android:defaultValue="DBPreferences_checkBoxPreference_defaultValue1" />
</PreferenceScreen>
preference_headers_legacy:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<Preference
android:title="@string/preferenceHeaders_title1"
android:summary="@string/preferenceHeaders_summary1" >
<intent
android:targetPackage="practice_projects.minimalpreferencesusingpreferenceheadersoldversions"
android:targetClass="practice_projects.minimalpreferencesusingpreferenceheadersoldversions.MyPreferenceActivity"
android:action="practice_projects.minimalpreferencesusingpreferenceheadersoldversions.DB" />
</Preference>
<Preference
android:title="@string/preferenceHeaders_title2"
android:summary="@string/preferenceHeaders_summary2" >
<intent
android:targetPackage="practice_projects.minimalpreferencesusingpreferenceheadersoldversions"
android:targetClass="practice_projects.minimalpreferencesusingpreferenceheadersoldversions.MyPreferenceActivity"
android:action="practice_projects.minimalpreferencesusingpreferenceheadersoldversions.UI" />
</Preference>
</PreferenceScreen>
strings.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Minimal Preferences Using Preference headers OLD VERSIONS</string>
<string name="mainActivity_textView">I am a TextView.</string>
<string name="preferenceHeaders_title">Preference Header Title</string>
<string name="preferenceHeaders_summary">Preference Header Summary</string>
<string name="preferenceHeaders_title1">Preference Header Title</string>
<string name="preferenceHeaders_summary1">Preference Header Summary</string>
<string name="preferenceHeaders_title2">Preference Header Title</string>
<string name="preferenceHeaders_summary2">Preference Header Summary</string>
<string name="DBPreferences_checkBoxPreference_title">Preference Title</string>
<string name="DBPreferences_checkBoxPreference_summary">Preference Summary</string>
<string name="DBPreferences_checkBoxPreference_defaultValue">DBPreferences_checkBoxPreference_defaultValue</string>
<string name="DBPreferences_checkBoxPreference_title1">Preference Title</string>
<string name="DBPreferences_checkBoxPreference_summary1">Preference Summary</string>
<string name="DBPreferences_checkBoxPreference_defaultValue1">DBPreferences_checkBoxPreference_defaultValue1</string>
<string name="UIPreferences_editTextPreference_title">Preference Title</string>
<string name="UIPreferences_editTextPreference_summary">Preference Summary</string>
<string name="UIPreferences_editTextPreference_defaultValue">UIPreferences_editTextPreference_defaultValue</string>
<string name="UIPreferences_editTextPreference_title1">Preference Title</string>
<string name="UIPreferences_editTextPreference_summary1">Preference Summary</string>
<string name="UIPreferences_editTextPreference_defaultValue1">UIPreferences_editTextPreference_defaultValue1</string>
<string name="title_activity_my_preference">MyPreferenceActivity</string>
<string name="hello_world">Hello world!</string>
</resources>