tsukimi
tsukimi

Reputation: 1645

Msg: android.app.Activity.createDialog: (Activity#onCreateDialog did not create a dialog for id xxxxx)

I get this error sometimes reported when creating a dialog, i haven't experienced the error myself and it doesnt seem to happen for every user since i am getting data send with the dialog. I have tested android 2.2.This is the code.

private static final int DIALOG_CONTEST_ENTRY = 939321;

showDialog(DIALOG_CONTEST_ENTRY);

protected Dialog onCreateDialog(int id) {

    switch (id) {
    case DIALOG_CONTEST_ENTRY: 
        final Dialog dialog = new Dialog(this);
        dialog.setContentView(R.layout.contest_entry_dialog);
        dialog.setTitle(getString(R.string.ContestEntryDialogTitle));
        dialog.setCanceledOnTouchOutside(true);
        TextView text = (TextView) dialog.findViewById(R.id.contest_text); 
        text.setText(getString(R.string.ContestEntryDialogText));
        Button sendButton = (Button) dialog.findViewById(R.id.ButtonSend);
        Button cancelButton = (Button) dialog.findViewById(R.id.ButtonCancel);
        final EditText name = (EditText) dialog.findViewById(R.id.editName);
        final EditText email = (EditText) dialog.findViewById(R.id.editEmail);
        final TextView score = (TextView) dialog.findViewById(R.id.textScore);

        final Prefs prefs = new Prefs(xxxActivity.this);

        name.setText(prefs.ReadString("Name"));
        email.setText(prefs.ReadString("Email"));
        score.setText("Score: " + scoreCurrent);

        sendButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                                            //Send form
                    dialog.dismiss();
                }
            }
        });
        cancelButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                dialog.dismiss();
            }
        });
        dialog.show();
        return dialog;
    default:
        break;
    }
    return super.onCreateDialog(id);
}


<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
  android:layout_height="match_parent" android:orientation="vertical" android:padding="10dp" android:background="#FFF">

<TextView
    android:id="@+id/contest_text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/ContestEntryDialogText"
    android:textColor="#000" />

<EditText
    android:id="@+id/editName"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:inputType="textPersonName" android:hint="Enter Name"/>

<EditText
    android:id="@+id/editEmail"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:inputType="textEmailAddress" android:hint="Enter Email">

    <requestFocus />
</EditText>
<TextView
    android:id="@+id/textScore"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Score: " android:textSize="20dp"/>

<LinearLayout
    android:id="@+id/linearLayout1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >

    <Button
        android:id="@+id/ButtonSend"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Send" />

    <Button
        android:id="@+id/ButtonCancel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Cancel" />

</LinearLayout>

Upvotes: 0

Views: 613

Answers (1)

Shankar Agarwal
Shankar Agarwal

Reputation: 34765

After experiencing this same issue (and finding that calling removeDialog from within onPause doesn't work reliably), I developed a workaround that seems to function (although it's admittedly a hack).

As seen in the grepcode link posted by antslava, in method performRestoreInstanceState, onRestoreInstanceState is called right before restoreManagedDialogs and is passed the same instance of Bundle savedInstanceState.

final void performRestoreInstanceState(Bundle savedInstanceState) {
    onRestoreInstanceState(savedInstanceState);
    restoreManagedDialogs(savedInstanceState);
}

Thus, there is opportunity to modify the Bundle savedInstanceState that is passed to restoreManagedDialogs from within the onRestoreInstanceState method.

To prevent any and all managed dialogs from being restored, one could implement onRestoreInstanceState in the following way:

// This same variable is defined as private in the Activity class. I need
// access to it, so I redefine it here.
private static final String SAVED_DIALOGS_TAG = "android:savedDialogs";

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    final Bundle b = savedInstanceState.getBundle(SAVED_DIALOGS_TAG);
    if (null != b) {
        savedInstanceState.remove(SAVED_DIALOGS_TAG);
    }
}

This causes the Bundle referenced by key "android:savedDialogs" to be removed from Bundle savedInstanceState, which subsequently causes the call to restoreManagedDialogs to immediately return when it finds that this key cannot be found:

private void restoreManagedDialogs(Bundle savedInstanceState) {
    final Bundle b = savedInstanceState.getBundle(SAVED_DIALOGS_TAG);
    if (b == null) {
        return;
    }
    ...
}

This will cause onCreateDialog to not be called while restoring the Activity, effectively "hiding" any dialogs, thus preventing the scenario where one must return null from onCreateDialog from occurring.

This isn't a 'one size fits all' solution, but given my requirements it seems to fit the bill. By reviewing the code in grepcode for several platform versions (1.6, 2.1, 2.2, 2.2.2, and 4.0.3), it appears that this solution should work consistently given these existing implementations.

Upvotes: 1

Related Questions