Question

I have been attempting to use an android.preference.DialogPreference inflated from XML, but the documentation seems to be missing some essential bits, and I cannot find a working example anywhere. My XML now looks like this (I tried many permutations but this seems like a reasonable minimum):

<DialogPreference
android:key="funThing" android:title="Fun Thing"
android:dialogLayout="@layout/fun_layout"
android:positiveButtonText="OK"
android:negativeButtonText="Cancel"
/>

My supposition at this point is that it is required to subclass DialogPreference and not to use it directly. For one, I cannot find a way to associate the actual preference value with an element in the dialog itself, which upon reflection is kind of a giveaway. And also, looking at the source to DialogPreference.java seems to confirm it. And I also just noticed that the official documentation refers to it as a "base class". But at very least, it would be nice to establish a definitive-enough source on the net which would help the next N people figure this out faster than I did.

For the record, the logfile looks like this:

I/ActivityManager(   61): Starting: Intent { cmp=org.jeremy.android/.PreferencesActivity } from pid 2755
W/Resources( 2755): Converting to string: TypedValue{t=0x10/d=0x4b0 a=-1}
W/Resources( 2755): Converting to string: TypedValue{t=0x10/d=0x20 a=-1}
D/AndroidRuntime( 2755): Shutting down VM
W/dalvikvm( 2755): threadid=1: thread exiting with uncaught exception (group=0x40015560)
E/AndroidRuntime( 2755): FATAL EXCEPTION: main
E/AndroidRuntime( 2755): java.lang.RuntimeException: Unable to start activity ComponentInfo{org.jeremy.android/org.jeremy.android.PreferencesActivity}: android.view.InflateException: Binary XML file line #28: Error inflating class java.lang.reflect.Constructor
E/AndroidRuntime( 2755):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1647)
E/AndroidRuntime( 2755):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663)
E/AndroidRuntime( 2755):    at android.app.ActivityThread.access$1500(ActivityThread.java:117)
E/AndroidRuntime( 2755):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
E/AndroidRuntime( 2755):    at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime( 2755):    at android.os.Looper.loop(Looper.java:123)
E/AndroidRuntime( 2755):    at android.app.ActivityThread.main(ActivityThread.java:3683)
E/AndroidRuntime( 2755):    at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime( 2755):    at java.lang.reflect.Method.invoke(Method.java:507)
E/AndroidRuntime( 2755):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
E/AndroidRuntime( 2755):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
E/AndroidRuntime( 2755):    at dalvik.system.NativeStart.main(Native Method)
E/AndroidRuntime( 2755): Caused by: android.view.InflateException: Binary XML file line #28: Error inflating class java.lang.reflect.Constructor
E/AndroidRuntime( 2755):    at android.preference.GenericInflater.createItem(GenericInflater.java:397)
E/AndroidRuntime( 2755):    at android.preference.GenericInflater.onCreateItem(GenericInflater.java:417)
E/AndroidRuntime( 2755):    at android.preference.GenericInflater.createItemFromTag(GenericInflater.java:428)
E/AndroidRuntime( 2755):    at android.preference.GenericInflater.rInflate(GenericInflater.java:481)
E/AndroidRuntime( 2755):    at android.preference.GenericInflater.rInflate(GenericInflater.java:493)
E/AndroidRuntime( 2755):    at android.preference.GenericInflater.inflate(GenericInflater.java:326)
E/AndroidRuntime( 2755):    at android.preference.GenericInflater.inflate(GenericInflater.java:263)
E/AndroidRuntime( 2755):    at android.preference.PreferenceManager.inflateFromResource(PreferenceManager.java:251)
E/AndroidRuntime( 2755):    at android.preference.PreferenceActivity.addPreferencesFromResource(PreferenceActivity.java:262)
E/AndroidRuntime( 2755):    at org.jeremy.android.PreferencesActivity.onCreate(PreferencesActivity.java:40)
E/AndroidRuntime( 2755):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
E/AndroidRuntime( 2755):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611)
E/AndroidRuntime( 2755):    ... 11 more
E/AndroidRuntime( 2755): Caused by: java.lang.InstantiationException: android.preference.DialogPreference
E/AndroidRuntime( 2755):    at java.lang.reflect.Constructor.constructNative(Native Method)
E/AndroidRuntime( 2755):    at java.lang.reflect.Constructor.newInstance(Constructor.java:415)
E/AndroidRuntime( 2755):    at android.preference.GenericInflater.createItem(GenericInflater.java:383)
E/AndroidRuntime( 2755):    ... 22 more
W/ActivityManager(   61):   Force finishing activity org.jeremy.android/.PreferencesActivity
W/ActivityManager(   61):   Force finishing activity org.jeremy.android/.SplashActivity
Was it helpful?

Solution

This one is weird, you need to subclass DialogPreference. The subclass does not need to do anything. So

public class MyDialogPreference extends DialogPreference {

    public MyDialogPreference(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
    }

} 

can be instantiated. While a plane old DialogPreference can not. Very weird, they should be the exact same thing.

OTHER TIPS

Here is an example of how to use the dialog preference (subclassing as you mentioned).

package dk.myapp.views;

import android.content.Context;
import android.preference.DialogPreference;
import android.util.AttributeSet;

/**
 * The OptionDialogPreference will display a dialog, and will persist the
 * <code>true</code> when pressing the positive button and <code>false</code>
 * otherwise. It will persist to the android:key specified in xml-preference.
 */
public class OptionDialogPreference extends DialogPreference {

    public OptionDialogPreference(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onDialogClosed(boolean positiveResult) {
        super.onDialogClosed(positiveResult);
        persistBoolean(positiveResult);
    }

}

The preferences.xml should contain

<dk.myapp.views.OptionDialogPreference
            android:key="@string/prefKeyResetQuests"
            android:dialogIcon="@android:drawable/ic_dialog_alert"
            android:title="Reset Quests"
            android:summary="Reset all quest-progress."
            android:dialogMessage="Are you sure you wish to reset your quest progress? This action cannot be undone!"
            android:positiveButtonText="Clear Quests"
            android:negativeButtonText="Cancel"/>

I have a res/value containing (though the key-name can also be declared explicitly above).

<string name="prefKeyResetQuests">resetQuests</string>  

My PreferenceActivity does the actual resetting from onPause. Note that onStop may be too late since the onStop will not always be called immediately after pressing back:

@Override
public void onPause() {
    SharedPreferences prefs = android.preference.PreferenceManager.
        getDefaultSharedPreferences(getBaseContext());
    if(prefs.getBoolean(
        getResources().getString(R.string.prefKeyResetQuests), false)) {
        // apply reset, and then set the pref-value back to false
    }
}

Or equivalently since we are still in the PreferenceActivity:

@Override
protected void onPause() {
    Preference prefResetQuests =
        findPreference(getResources().getString(R.string.prefKeyResetQuests));
    if(prefResetQuests.getSharedPreferences().
        getBoolean(prefResetQuests.getKey(), false)){
        // apply reset, and then set the pref-value back to false 
    }
}

First:

Create your own class which extends DialogPreference as bellow:

package com.test.view;

import android.preference.DialogPreference;

public class DialogExPreference extends DialogPreference 
{
    public DialogExPreference(Context oContext, AttributeSet attrs)
    {
        super(oContext, attrs);     
    }
}

Second:

Modify the xml file as bellow:

<PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android">

    <com.test.view.DialogExPreference
        android:title="@string/title"
        android:dialogMessage="@string/lite"              
                android:negativeButtonText="test"/> 

</PreferenceScreen>

Then it's OK.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top