Search code examples
javaandroidxmlmodal-dialogillegalstateexception

How to call removeView() on dialog box number one so as to show dialog number 2


I am working with an application that involves to dialog boxes that should appear one after the other. What I mean is that, when I click on the positive button of the first dialog box it should then bring up another second dialog box. The issue I am facing is with the second dialog box, the second one will not pop up and it causes the application to crash.

I get an error that says "java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first."

public static void showBusinessOrPrivateStartDialog(final Context context, final CallLogEntry call)
       {
          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
          {
             // If new version of android, then check permission
             if (!Settings.canDrawOverlays(context))
             {
                Log.e(TAG, "Permission Denied: Draw overlays (for popup)");
                return;
             }
          }

          LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
          //View view = inflater.inflate(R.layout.dialog_call_type, null);

          AlertDialog.Builder builder = new AlertDialog.Builder(context, Theme_Material_Light_Dialog_Alert);

          builder.setTitle("Was this a private or a business call?");
          builder.setMessage("Please select a call type");
          builder.setIcon(R.drawable.ic_deviceinsight);
          builder.setCancelable(true);
          //builder.setView(view);

          builder.setOnCancelListener(new DialogInterface.OnCancelListener() {
             @Override
             public void onCancel(DialogInterface dialog) {
                // Occurs when user cancels the dialog, or clicks somewhere else in the screen or presses the back button
                Log.i(TAG, "cancelled");

                saveCallEntry(context, call, CLASSIFICATION_TYPE_BUSINESS, "", true, "");
             }
          });

          builder.setPositiveButton("Business", new DialogInterface.OnClickListener() {
             public void onClick(DialogInterface dialog, int which) {
                CallClassification.showBusinessCallPopup(context, call);
             }
          });
          builder.setNegativeButton("Private", new DialogInterface.OnClickListener() {
             public void onClick(DialogInterface dialog, int which) {
                saveCallEntry(context, call, CLASSIFICATION_TYPE_PRIVATE, "", false, "");
             }
          });

          AlertDialog dialog = builder.create();
          // Rather use something like TYPE_SYSTEM_ALERT, if possible.
          dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); // TYPE_SYSTEM_ERROR
          dialog.show();
       }

This is the second method for the second dialog box and my app crashes on dialog.show

public static void showBusinessCallPopup(final Context context, final CallLogEntry call)
       {
          // NEW NRF
          if (AppPreferences.isNRF(context)) {
             CallItem callItem = saveCallEntry(context, call, CLASSIFICATION_TYPE_BUSINESS, "", false, "");

             // SHOW NEW FORM
             Intent intent = new Intent(context, CallClassificationFormActivity.class);
             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
             EventBus.getDefault().postSticky(callItem);
             context.startActivity(intent);

             return;
          }

          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
          {
             // If new version of android, then check permission
             if (!Settings.canDrawOverlays(context))
             {
                Log.e(TAG, "Permission Denied: Draw overlays (for popup)");
                return;
             }
          }

          LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
          View view = inflater.inflate(R.layout.dialog_call_details, null);

          AlertDialog.Builder builder = new AlertDialog.Builder(context, Theme_Material_Light_Dialog_Alert);

          String toOrFrom = call.Type == CallLog.Calls.INCOMING_TYPE ? "from" : "to";

          //builder.setTitle("Business call");
          builder.setCustomTitle(view);
          //builder.setMessage("Please enter reference details for the call " + toOrFrom + " " + call.Number);
          //builder.setIcon(R.drawable.ic_deviceinsight);
          builder.setCancelable(true);
          builder.setView(view);

          final EditText etReference = (EditText)view.findViewById(R.id.etReference);
          final EditText etComment = (EditText)view.findViewById(R.id.etComment);

          builder.setPositiveButton("Confirm", new DialogInterface.OnClickListener() {
             public void onClick(DialogInterface dialog, int which) {

                String reference = etReference.getText().toString();
                String comment = etComment.getText().toString();

                saveCallEntry(context, call, CLASSIFICATION_TYPE_BUSINESS, reference, false, comment);
             }
          });
          builder.setOnCancelListener(new DialogInterface.OnCancelListener() {
             @Override
             public void onCancel(DialogInterface dialog) {
                Log.i(TAG, "cancelled");
             }
          });

          AlertDialog dialog = builder.create();
          dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); // TYPE_SYSTEM_ERROR
          dialog.show();
       }

and here is my xml. I have included the xml in this post because I read somewhere that the way the height and width of my textboxes is defined might be causing an issue.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:app="http://schemas.android.com/apk/res-auto"
              xmlns:tools="http://schemas.android.com/tools"
              android:id="@+id/layout"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:orientation="vertical"
              android:paddingLeft="5dp"
              android:paddingRight="5dp"
              android:paddingTop="5dp"
              tools:context=".calls.CallClassification">

  <TextView
         android:id="@+id/tvMessage"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_marginBottom="5dp"
         android:padding="5dp"
         android:text="Please enter reference details for the call "
         android:textColor="@color/colorPrimaryDark"
         android:textSize="16sp"/>

   <AutoCompleteTextView
         android:id="@+id/etReference"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:backgroundTint="@color/colorAccent"
         android:hint="Matter Code *"
         android:imeOptions="actionNext"
         android:inputType="text"
         android:maxLength="255"
         android:text=""
         android:textColor="@color/colorPrimary"
         android:textColorHint="@color/colorTextHint"
         android:textSize="14sp"/>

   <CheckBox
         android:id="@+id/cbBillable"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_marginLeft="5dp"
         android:layout_marginRight="5dp"
         android:button="@null"
         android:buttonTint="@color/colorAccent"
         android:checked="true"
         android:drawableRight="?android:attr/listChoiceIndicatorMultiple"
         android:paddingBottom="3dp"
         android:paddingTop="3dp"
         android:text="Billable"
         android:textColor="@color/colorPrimaryDark"
         android:textSize="14sp"/>

   <EditText
         android:id="@+id/etComment"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:backgroundTint="@color/colorAccent"
         android:hint="Enter comment"
         android:imeOptions="actionDone"
         android:inputType="text"
         android:lines="1"
         android:maxLength="1000"
         android:maxLines="4"
         android:minLines="1"
         android:text=""
         android:textColor="@color/colorPrimary"
         android:textColorHint="@color/colorTextHint"
         android:textSize="14sp"/>

   <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:orientation="horizontal">

      <Button
            android:id="@+id/bCancel"
            style="@style/Widget.AppCompat.Button.Borderless.Colored"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Cancel"/>

      <Button
            android:id="@+id/bOk"
            style="@style/Widget.AppCompat.Button.Borderless.Colored"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="GO"/>
   </LinearLayout>


</LinearLayout>

Solution

  • After hearing to your experience, I could think of one more solution. Rather than declaring AlertDialog variable inside each of the methods, declare one global variable so that you can make sure that only one Dialog is shown at any instance.

    While declaring, make

    AlertDialog dialog = null;

    in class Then in,

        showBusinessOrPrivateStartDialog() {
        if(dialog == null) {
        dialog = build.create();
        }
        }
    
    
        builder.setPositiveButton("Business", new DialogInterface.OnClickListener() {
              public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                        CallClassification.showBusinessCallPopup(context, call);
                     }
                  });
    
    builder.setOnDismissListener(new OnDismissListener() {
    public void onDismiss() {
    dialog = null;
    }
    }
    

    Then again in showBusinessCallPopup(),

    if(dialog == null) {
        dialog = build.create();
        }
    

    Hope this helps you.