Home » Android » "android.util.AndroidRuntimeException: requestFeature() must be called before adding content" on showDialog(dialogId)

"android.util.AndroidRuntimeException: requestFeature() must be called before adding content" on showDialog(dialogId)

Posted by: admin June 15, 2020 Leave a comment

Questions:

This one is driving me to the brink of insanity!

I have an activity where I initialize a Button view with an onClickListener, like so:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.myLayout);

    mMyButton = (Button) findViewById(R.id.myButtonId);
    mMyButton.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            showDialog(ID_MYDIALOG);
        }
    });
}

I have also written my own dialog builder class (a singleton) since I have several other Activity’s in my application which will be using a common set of dialogs, hence in the onCreateDialog(int id) function for the given Activity I call:

@Override
protected Dialog onCreateDialog(int id) {
    Dialog dialog;

    switch (id) {
        case ID_MYDIALOG:
            dialog = DialogBuilder.getInstance().getMyDialog(this, mUri, mListener);
            break;

        default:
            dialog = null;
            break;
    }

    return dialog;
}

The mUri and mListener variables are defined elsewhere and I have verified that they are valid. The relevant parts of the singleton DialogBuilder class looks like this:

public AlertDialog getMyDialog(Context context, Uri uri, DialogInterface.OnClickListener listener) {
    // Inflate the custom body for the AlertDialog.
    LayoutInflater layoutInflater = LayoutInflater.from(context);
    View view = layoutInflater.inflate(R.layout.myDialogBody, null);

    // Get the data to show in the dialog.
    Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
    cursor.moveToFirst();

    // Create a suitable data adapter and use it to populate the dialog body with data.
    MyDialogDataAdapter adapter = new MyDialogDataAdapter(context, cursor);

    // Populate the GridView in the dialog body with data.
    GridView grid = (GridView) view.findViewById(R.id.myDialogDataGrid);
    grid.setAdapter(adapter);

    return new AlertDialog.Builder(context)
    .setIcon(R.drawable.myDialogIcon)
    .setTitle(R.string.myDialogTitle)
    .setView(view)
    .setPositiveButton(R.string.myDialogDone, listener)
    .create();
}

Now, when I run my application and tap the button (i.e. mMyButton) I get the following exception stack trace:

E/AndroidRuntime( 1247): FATAL EXCEPTION: main
E/AndroidRuntime( 1247): android.util.AndroidRuntimeException: requestFeature() must be called before adding content
E/AndroidRuntime( 1247):    at com.android.internal.policy.impl.PhoneWindow.requestFeature(PhoneWindow.java:181)
E/AndroidRuntime( 1247):    at com.android.internal.app.AlertController.installContent(AlertController.java:203)
E/AndroidRuntime( 1247):    at android.app.AlertDialog.onCreate(AlertDialog.java:251)
E/AndroidRuntime( 1247):    at android.app.Dialog.dispatchOnCreate(Dialog.java:307)
E/AndroidRuntime( 1247):    at android.app.Activity.createDialog(Activity.java:886)
E/AndroidRuntime( 1247):    at android.app.Activity.showDialog(Activity.java:2557)
E/AndroidRuntime( 1247):    at android.app.Activity.showDialog(Activity.java:2524)
E/AndroidRuntime( 1247):    at com.dbm.myApp.myActivity$4.onClick(myActivity.java:266)
E/AndroidRuntime( 1247):    at android.view.View.performClick(View.java:2534)
E/AndroidRuntime( 1247):    at android.view.View$PerformClick.run(View.java:9210)
E/AndroidRuntime( 1247):    at android.os.Handler.handleCallback(Handler.java:587)
E/AndroidRuntime( 1247):    at android.os.Handler.dispatchMessage(Handler.java:92)
E/AndroidRuntime( 1247):    at android.os.Looper.loop(Looper.java:123)
E/AndroidRuntime( 1247):    at android.app.ActivityThread.main(ActivityThread.java:3652)
E/AndroidRuntime( 1247):    at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime( 1247):    at java.lang.reflect.Method.invoke(Method.java:507)
E/AndroidRuntime( 1247):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
E/AndroidRuntime( 1247):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
E/AndroidRuntime( 1247):    at dalvik.system.NativeStart.main(Native Method)
W/ActivityManager(  212):   Force finishing activity com.dbm.myApp/.myActivity

If I interpret the stack trace correctly the issue is triggered the very moment I tap my button (as of com.dbm.myApp.myActivity$4.onClick(myActivity.java:266) which is the exact showDialog(ID_MYDIALOG); line).

What do you, fellow Android developers say? What du you think is causing my problem?

It’s fair to assume that the above code is valid, as per compilation and unit tests etc. The given code is, however, simplified and stripped to fit the forum, hence, please don’t put an effort to comment the naming conventions etc.

How to&Answers:

I think I might have solved the issue: If I for some reason create the AlertDialog with:

return new AlertDialog.Builder(context)
    .setIcon(R.drawable.myDialogIcon)
    .setTitle(R.string.myDialogTitle)
    .setView(view)
    .setPositiveButton(R.string.myDialogDone, listener)
    .show();

I.e. with .show(); instead of .create(); The issue is no longer present. I don’t know why this works or what differs the AlertDialog.Builder::show() function from the AlertDialog.Builder::create(); function (more than the obvious difference reflected in respective function names).

Answer:

Try to call the .setView(view) right after constructor.

return new AlertDialog.Builder(context)
    .setView(view)
    .setIcon(R.drawable.myDialogIcon)
    .setTitle(R.string.myDialogTitle)
    .setPositiveButton(R.string.myDialogDone, listener)
    .create();

Does it help?

Answer:

It may not be the solution..but I was a bit suprised by this piece:

mMyButton.setOnClickListener(new View.OnClickListener() {
    showDialog(ID_MYDIALOG);

I thought you should implement onClick inside the listener? am I wrong?