73

Coming from the .NET-environment, I'm now looking to understand how Dialogs work in Android.

In .NET, when calling MessageBox.Show(...) that creates and shows a popup dialog. In the call to Show I can specify what buttons should be available in the popup, for example:

DialogResult myDialogResult = MessageBox.Show("My text here", "My caption here", MessageBoxButtons.YesNoCancel);

As you can see, the call to Show returns a DialogResult when a button is pressed in the popup, informing me what button was clicked. Note that in .NET, execution is halted at the line where the call to Show(...) is made, so it can return the value when a button is pressed.

If I in the above example press "No" the myDialogResult will be equal to

myDialogResult == DialogResult.No

Since I find the .NET-way of using/creating popups very easy and intuitive, I would like that way of creating popups in Android too.

So, the question is if anyone know how to "halt execution" like with the MessageBox.Show, and then return a value whenever the Button is pressed (and the dialog goes away)?

Edit 1

To be a little bit more clear:

I need for the execution to halt and wait until the user has chosen a button to click in the popup. The code that follow the call to show the Dialog is dependent on what button is clicked in the Dialog.

That's why I cannot use what Erich and Alex suggest, since writing code in the onClick-methods as suggested below is not going to work. The reason is that I cannot continue the "normal execution". Let me take an example:

Let me take an example:

int nextStep = 0; // this variable will not be reached from within the onClick-methods

AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Hello!")
       .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                nextStep = 1; // *** COMPILER ERROR!! ***
            }
        })
        .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                nextStep = 2; // *** COMPILER ERROR!! ***
            }
        })
        .create().show();

if (nextStep == 1)
{
    // then do some damage
}
else if (nextStep == 2
    // dont do damage

If I wanted the execution to be dependent on the choice in the popup, I would somehow have to make all the variables in the "normal execution" (in this case nextStep) available in the onClick-methods, and that sounds like hell to me.

Edit 2

Another obvious example would be a popup asking "Do you want to continue" with the options "Yes" and "No".

If the user presses "Yes", the whole method should be aborted otherwise it should continue execution. How do you solve that nicely?

halfer
  • 19,824
  • 17
  • 99
  • 186
Ted
  • 19,727
  • 35
  • 96
  • 154
  • see if fupsduck's added paragraph helps – fupsduck Jan 08 '10 at 16:49
  • 4
    As an alternative, you could also design your "dialog" as an Activity that has the same look-and-feel as a dialog. If your dialog has a lot of logic, it might be easier to implement this way. – Erich Douglass Jan 08 '10 at 17:00
  • 3
    Regarding the alert dialog, .NET is great, and Android sucks. In a few cases I need MessageBox to help debugging. In .NET, the code after the MessageBox won't run until you close the MessageBox. However, in Android, it does not work. I think in Windows, there is another message loop when showing a modal dialog. In Android, I think the window and the dialog uses the same message loop. – Zach Aug 03 '14 at 03:53
  • Instead of having `If (nextStep == 1) { }` and `If (nextStep == 2) { }`, you need to have a void called, say, `public void nextStep1` and `public void nextStep2` that get called when the user clicks a certain button. If they share code afterwords, you can make another void that they each call afterwords with the rest of your code in it. – Cullub Oct 16 '14 at 12:54
  • I think the Android guy @Romain Guy just said that "you should not design a program that look nice and clean to make a choice and act according to the choice". If there is a sequence of similar choices and related each other, it might need a 100 times of code lines in android. I don't known what is the difficulty or side affect to add this to Android library, but I think maybe it is difficult from them. – rml Apr 23 '15 at 18:16
  • You can use this to show the dialog and block the background thread: https://github.com/jrummyapps/blocking-dialog – Jared Rummler Feb 16 '17 at 20:36

20 Answers20

49

Ted, you don't want to do this, really :) The biggest reason is that if you block the UI thread while you are displaying a Dialog, you will block the thread that's in charge of drawing and handling the events of your Dialog. Which means your dialog will be unresponsive. You will also cause ANRs if the user takes more than a few seconds to click the dialog.

Erich's answer is exactly what you need. I know it's not what you want, but that doesn't matter. We've designed Android to prevent developers from writing synchronous dialogs so you don't really have much of a choice.

Romain Guy
  • 97,993
  • 18
  • 219
  • 200
  • Hey Romain, thanks for the answer. I found [this thread](http://groups.google.com/group/android-developers/browse_thread/thread/f8f1ac25831adcf5/06f4f4868687fd6e?utoken=OFvxRDUAAACwwFf96muIoaCUrXmA7_-MBWr8sH0dHzLC3cUGCWl_v0ttVgZ6uIZjx_BoK4AXQSwmEzwNZNL90vKyYcNdWiMd) where some guy had the same problem. Sure, I dont have a choice, Im sure. – Ted Jan 08 '10 at 16:57
  • 1
    I have written applications where several modal Dialogs are presented after each other. the user has to answer all of them before proceeding. For example, there are a number of "control questions" that the User has to answer before proceeding. Let's say we have 3 such questions - that would be a complete mess to create in Android as I understand it. We need a bunch of pretty useless methods, one for each Dialog we are presenting for the user. The code gets "butchered" and split up, hard to follow and messy in general. That is a real shame I think =( (note: that I like Android in other ways) – Ted Jan 08 '10 at 16:59
  • 20
    It's a mess because you are architecting your code in a way that's not meant to be with Android. Just do it *differently*. If you refuse to do so, it's your problem. For instance, instead of using 3 blocking dialogs (which I find to be a terrible and lazy UI by the way), why don't you have an Activity will all the questions and only when the user validates you start doing whatever your app is supposed to be doing. You asked a question, we've answered and so far the only thing you've been saying is that you don't like our answers. Sorry, but they won't change. – Romain Guy Jan 09 '10 at 19:36
  • 65
    Stop telling people that they shouldn't try to do what they want to do. If anything's "terrible and lazy", that (answer) would be it. Of course you can make modal dialogs in Android, you just need to write more code. There's nothing bad about that UI, from a user's perspective. Lots of UI frameworks, not just Windows, support this concept. If there was a simple one-line answer, the poster probably wouldn't have needed to ask the question. If you don't want to do the work of answering his question, just leave it alone. – Nate Aug 12 '11 at 09:38
  • 6
    @radhoo Because of small details like this, is why I see so much horrendous mobile apps (iOS apps that look designed by a Java guy and Android aberrations designed by C++ people) (for example). You have to learn and understand the platform you're working in, not necessarily force your way though it with your own ideas. Each platform has its strengths and weaknesses, like it or not. The lifecycle model in Android is designed that way, deal with it and learn to architecture around it. – Martin Marconcini Apr 15 '13 at 21:46
  • 1
    @Nate I have read your answer. I think you are likely saying that "I do know how to do it and you should not try to do it because this is not good". But I think you are totally wrong. A function used to display a UI and wait for a user action and then go different way according to the user action is a very easy and useful way to handle user actions. Android just make it complicated by not support this method. You can say that you do not know how, or it can not be done, but you can not say something like "you are wrong to try get this function because this function is not good". – rml Sep 27 '13 at 16:44
  • 8
    @rml I work on the Android framework team and we've specifically designed the framework to not have modal dialogs that block the current execution thread. I know how it could be done but it's not the model we chose for Android. – Romain Guy Sep 27 '13 at 18:41
  • 38
    Please note that the OP certainly didn't want to actually stop the UI _thread_, just wanted to block the user _workflow_. Since that's a valid and common use case (as users hardly ever perform multiple _parallel_ interactions with their gadgets, and systems commonly need to _wait_ for them), it's natural to expect some trivial modal dialog API seamlessly matching the "single-threaded user" reality. It's understandable if it's not easy to do nicely. But if the Android team could come up with a smart way to make it as trivial as illustrated in the question, it could only help us all. Thx! – Sz. Jan 12 '14 at 13:12
  • 4
    I have to agree that this is a common scenario which is why it is supported by several frameworks including .NET. It doesn't make sense that Android doesn't provide a simple and straight-forward implementation for this. Now I have to break the logical flow of my code to accomodate Android's convoluted way of doing things. – W.K.S Jan 20 '14 at 13:38
  • 2
    @Romain The other frameworks do not block the main thread either. This is a convenience method. –  Apr 19 '14 at 19:38
  • 1
    @Sz. It's not at all clear that the OP didn't want to stop the UI thread. He says "execution is halted at the line where the call to Show(...) is made, so it can return the value when a button is pressed," and "I need for the execution to halt and wait until the user has chosen a button." The thread whose execution is halted is the UI thread, unless he's started an Async task. It's possible that he didn't mean what he said, but it's not obvious. – LarsH Mar 31 '16 at 19:28
22

In Android, the structure is different from .NET:

AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Hello!")
       .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
           public void onClick(DialogInterface dialog, int id) {
               // Handle Ok
           }
       })
       .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
           public void onClick(DialogInterface dialog, int id) {
               // Handle Cancel
           }
       })
       .create();

Will get you a dialog with two buttons and you handle the button clicks with callbacks. You might be able to write some code to make the syntax more closely resemble .NET, but the dialog lifecycle is pretty intertwined with Activity, so in the end, it might be more trouble than it's worth. Additional dialog references are here.

LarsH
  • 27,481
  • 8
  • 94
  • 152
Erich Douglass
  • 51,744
  • 11
  • 75
  • 60
20

A simplified version of Daniel's answer above. This function gets a yes or no from user in an alert dialog but could easily be modified to get other input.

private boolean mResult;
public boolean getYesNoWithExecutionStop(String title, String message, Context context) {
    // make a handler that throws a runtime exception when a message is received
    final Handler handler = new Handler() {
        @Override
        public void handleMessage(Message mesg) {
            throw new RuntimeException();
        } 
    };

    // make a text input dialog and show it
    AlertDialog.Builder alert = new AlertDialog.Builder(context);
    alert.setTitle(title);
    alert.setMessage(message);
    alert.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
            mResult = true;
            handler.sendMessage(handler.obtainMessage());
        }
    });
    alert.setNegativeButton("No", new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
            mResult = false;
            handler.sendMessage(handler.obtainMessage());
        }
    });
    alert.show();

    // loop till a runtime exception is triggered.
    try { Looper.loop(); }
    catch(RuntimeException e2) {}

    return mResult;
}
MindSpiker
  • 1,437
  • 1
  • 14
  • 22
  • Thanks, this one works fine. I prefer Erich's way but it's not blocking execution (the solution I often use). At least your way works as intended by the question and the answer is interesting. – Solostaran14 Oct 22 '12 at 13:13
  • This is the most related answer to the question and it is a creative solution But it fails sometime with a Fatal error like this: A/libc﹕ Fatal signal 11 (SIGSEGV), code 1, fault addr 0x1 in tid 274... Is anyone get a solution about this? – rml Apr 23 '15 at 17:57
  • I'd like to say, that this also works for HTTP requests. I have just done a HTTP request via Volley, which has this idea that the code must continue (in the main threat) while doing the HTTP request. Great service, however, why not let us decide as programmers, whether or not we want to sit and make gymnastics with either an endless call-depth-level, or make our own threading if so? Your excellent example above worked without a single screw or nut added. And now I have modal HTTP calls.. I sorted out the AlertDialog via normal threading, though (!). Where can one share with the rest of you – David Svarrer Oct 15 '20 at 12:13
12

In Android Dialogs are asynchronous so you're going to have to structure your code a little differently.

So in C# your logic ran something like this in pseudocode:

void doSomeStuff() {
    int result = showDialog("Pick Yes or No");

    if (result == YES) {
        //do stuff for yes
    }
    else if (result == NO) {
        //do stuff for no
    }

    //finish off here
}

For Android it's going to have to be less neat. Think of it like so. You'll have an OnClickListener like this:

public void onClick(DialogInterface dialog, int whichButton) {
   if (whichButton == BUTTON_POSITIVE) {
      doOptionYes();
   }
   else if (whichButton == BUTTON_NEGATIVE) {
      doOptionNo();
   }
}

Which is then supported by the following methods:

void doOptionYes() {
    //do stuff for yes
    endThings();
}

void doOptionNo() {
    //do stuff for no
    endThings();
}

void endThings() {
    //clean up here
}

So what was one method is now four. It may not seem as neat but that's how it works I'm afraid.

David Webb
  • 190,537
  • 57
  • 313
  • 299
  • 1
    Thx Dave! Yes, that was what I have learned from all these answers. Unfortunately I have to say... Thx again =) – Ted Jan 08 '10 at 20:42
  • 3
    i find this a bit frustrating because sometimes my flow of execution bypasses the dialog if everything ok. if there is a problem i ask "keep going" or "forget it". so now i have 2 ways of getting to the keep going code. so i have to put that in its own method. so i have to redo all the setup that got to the dialog all over again. bad design IMHO. – steveh Feb 11 '13 at 08:46
8
PasswordDialog dlg = new PasswordDialog(this);

if(dlg.showDialog() == DialogResult.OK)

{

    //blabla, anything your self

}


public class PasswordDialog extends Dialog
{
    int dialogResult;
    Handler mHandler ;

    public PasswordDialog(Activity context, String mailName, boolean retry)
    {

        super(context);
        setOwnerActivity(context);
        onCreate();
        TextView promptLbl = (TextView) findViewById(R.id.promptLbl);
        promptLbl.setText("Input password/n" + mailName);
    }
    public int getDialogResult()
    {
        return dialogResult;
    }
    public void setDialogResult(int dialogResult)
    {
        this.dialogResult = dialogResult;
    }
    /** Called when the activity is first created. */

    public void onCreate() {
        setContentView(R.layout.password_dialog);
        findViewById(R.id.cancelBtn).setOnClickListener(new android.view.View.OnClickListener() {

            @Override
            public void onClick(View paramView)
            {
                endDialog(DialogResult.CANCEL);
            }
            });
        findViewById(R.id.okBtn).setOnClickListener(new android.view.View.OnClickListener() {

            @Override
            public void onClick(View paramView)
            {
                endDialog(DialogResult.OK);
            }
            });
        }

    public void endDialog(int result)
    {
        dismiss();
        setDialogResult(result);
        Message m = mHandler.obtainMessage();
        mHandler.sendMessage(m);
    }

    public int showDialog()
    {
        mHandler = new Handler() {
            @Override
              public void handleMessage(Message mesg) {
                  // process incoming messages here
                //super.handleMessage(msg);
                throw new RuntimeException();
              }
          };
        super.show();
        try {
            Looper.getMainLooper().loop();
        }
        catch(RuntimeException e2)
        {
        }
        return dialogResult;
    }

}
Daniel
  • 391
  • 4
  • 8
  • wow 3 simple lines of code in Windows is translated on about 100 weird lines of code in Android, this is all except user friendly – Windgate Sep 01 '22 at 07:20
5

Developers of Android and iOS decided that they are powerful and smart enough to reject Modal Dialog conception (that was on market for many-many years already and didn't bother anyone before), unfortunately for us. I believe that there is work around for Android - since you can show dialog from non-ui thread using Runnable class, there should be a way to wait in that thread (non-ui) until dialog is finished.

Edit: Here is my solution, it works great:

    int pressedButtonID;
    private final Semaphore dialogSemaphore = new Semaphore(0, true);
    final Runnable mMyDialog = new Runnable()
    {
        public void run()
        {
            AlertDialog errorDialog = new AlertDialog.Builder( [your activity object here] ).create();
            errorDialog.setMessage("My dialog!");
            errorDialog.setButton("My Button1", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    pressedButtonID = MY_BUTTON_ID1;
                    dialogSemaphore.release();
                    }
                });
            errorDialog.setButton2("My Button2", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    pressedButtonID = MY_BUTTON_ID2;
                    dialogSemaphore.release();
                    }
                });
            errorDialog.setCancelable(false);
            errorDialog.show();
        }
    };

    public int ShowMyModalDialog()  //should be called from non-UI thread
    {
        pressedButtonID = MY_BUTTON_INVALID_ID;
        runOnUiThread(mMyDialog);
        try
        {
            dialogSemaphore.acquire();
        }
        catch (InterruptedException e)
        {
        }
        return pressedButtonID;
    }
art926
  • 151
  • 2
  • 4
5

In an attempt to optimize memory and performance dialogs in Android are asynchronous (they are also managed for this reason). Comming from the Windows world, you are used to modal dialogs. Android dialogs are modal but more like non-modal when it comes to execution. Execution does not stop after displaying a dialog.

The best description of Dialogs in Android I have seen is in "Pro Android" http://www.apress.com/book/view/1430215968

This is not a perfect explanation but it should help you to wrap your brain around the differences between Dialogs in Windows and Android. In Windows you want to do A, ask a question with a dialog, and then do B or C. In android design A with all the code you need for B and C in the onClick() of the OnClickListener(s) for the dialog. Then do A and launch the dialog. You’re done with A! When the user clicks a button B or C will get executed.

Windows
-------
A code
launch dialog
user picks B or C
B or C code
done!

Android
-------
OnClick for B code (does not get executed yet)
OnClick for C code (does not get executed yet)
A code
launch dialog
done!
user picks B or C
fupsduck
  • 3,129
  • 1
  • 19
  • 18
  • 1
    If there is nothing else in this thread, then this is your case. But you always have something else there. So you have to prevent the other things from happening or to handle dozens or millions of cases that may change the status and makes B or C functions do not work correctly. The Android way makes it too much complicated. – rml Sep 27 '13 at 16:53
  • It's not really any more complicated, it's just different. – Cullub Oct 16 '14 at 12:49
  • 2
    If there is a lots similar questions to be answered in sequence, and each choice will affect the later process, then, it will be a big mess use non stop dialog used in android, but it will be much much more easier using windows dialog. ABSOLUTELY NOT JUST different. – rml Apr 23 '15 at 17:56
4

Ted, as you probably found out, you unfortunately can't do that on Android. Dialogs are modal, but asynchronous, and it will definitely disrupt the sequence you're trying to establish as you would have done on .NET (or Windows for that matter). You will have to twist your code around and break some logic that would have been very easy to follow based on your example.

Another very simple example is to save data in a file, only to find out that the file is already there and asking to overwrite it or not. Instead of displaying a dialog and having an if statement to act upon the result (Yes/No), you will have to use callbacks (called listeners in Java) and split your logic into several functions.

On Windows, when a dialog is shown, the message pump continues in the background (only the current message being processed is on hold), and that works just fine. That allows users to move your app and let is repaint while you're displaying a dialog box for example. WinMo supports synchronous modal dialogs, so does BlackBerry but just not Android.

user545076
  • 41
  • 1
  • 16
    Microsoft implemented 2 decades ago modal dialog boxes without any blocking that makes the code very fluid and easy to read (any Windows developer can attest that), by using a second message pump to handle the dialog box interaction while dispatching non-dialog box messages to the app, which remains unblocked while the dialog box is shown. Android has no such implementation so you are required to split your code. Android designers prefer to tell us "this is our way or the highway", instead of listening the what their customers (developers) need – user545076 Apr 13 '11 at 14:59
2

The cleanest and simplest solution is to use your own listener interface so that when the user clicks on the ok button your listener is called with the return value. This method does nothing fancy or complicated and respects android principles.

Define your listener interface as follows:

public interface EditListener
/* Used to get an integer return value from a dialog
 * 
 */
{
 void returnValue(int value); 
}

For my application I created an EditValue class which uses AlertDialog and which I call whenever I want to edit an integer value. Note how the EditListener interface is passed as an argument to this code. When the user clicks on the OK button the value will be returned to your calling code via the EditListener method:

public final class EditValue
/* Used to edit a value using an alert dialog
 * The edited value is returned via the returnValue method of the supplied EditListener             interface
 * Could be modified with different constructors to edit double/float etc
 */
{
 public EditValue(final Activity parent, int value, String title, String message,
                  final EditListener editListener)
 {AlertDialog.Builder alert= new AlertDialog.Builder(parent);
  if(title==null) title= message;
  else if(message==null) message= title;
  if(title!=null) alert.setTitle(title);
  if(message!=null) alert.setMessage(message);

  // Set an EditText view to get user input 
  final EditText input = new EditText(parent);
  input.setText(String.valueOf(value));
  input.setInputType(InputType.TYPE_CLASS_NUMBER);
  alert.setView(input);

  alert.setPositiveButton("OK",new DialogInterface.OnClickListener()
  {public void onClick(DialogInterface dialog, int which)
   {try
    {int newValue= Integer.valueOf(input.getText().toString());
     editListener.returnValue(newValue);
     dialog.dismiss();
    }catch(NumberFormatException err) { }
   }
  });

  alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener()
  {public void onClick(DialogInterface dialog, int which)
   {dialog.dismiss();
    }
  });

  alert.show();
 }
}

Finally when you use EditValue you need to declare your EditListener and you can now access the return value and do what you want to do:

 new EditValue(main,AnchorManager.anchorageLimit,
               main.res.getString(R.string.config_anchorage_limit),null,
               new EditListener()
 {public void returnValue(int value) {AnchorManager.anchorageLimit= value;}
  }
 );
1

I am new to the Android/Java world and was surprised to find out here (unless I don't understand what I read) that modal dialogs don't work. For some very obscure reasons for me at the moment, I got this "ShowMessage" equivalent with an ok button that works on my tablet in a very modal manner.

From my TDialogs.java module:

class DialogMes 
{

  AlertDialog alertDialog ;
  private final Message NO_HANDLER = null;
  public DialogMes(Activity parent,String aTitle, String mes)
  {
    alertDialog = new AlertDialog.Builder(parent).create();
    alertDialog.setTitle(aTitle);    
    alertDialog.setMessage(mes) ;  
    alertDialog.setButton("OK",NO_HANDLER) ;    
    alertDialog.show() ; 
  } 
}

Here's part of the test code:

public class TestDialogsActivity extends Activity implements DlgConfirmEvent
{

   @Override
  public void onCreate(Bundle savedInstanceState)
  {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    Button btShowMessage = (Button) findViewById(R.id.btShowMessage);
    btShowMessage.setOnClickListener(new View.OnClickListener() {
      public void onClick(View view) 
      {
        DialogMes dlgMes = new DialogMes( TestDialogsActivity.this,"Message","life is good") ;                
      }  
    }); 

I also implemented a modal Yes/No dialog following the interface approach suggested above by JohnnyBeGood, and it works pretty good too.

Correction:

My answer is not relevant to the question that I misunderstood. For some reason, I interpreted M. Romain Guy "you don't want to do that" as a no no to modal dialogs. I should have read: "you don't want to do that...this way".

I apologize.

Guyt
  • 39
  • 4
1

Rewriting:

There are radical differences between mobile and desktop environment, as well as between the way in which applications were developed to a handful of years ago and today:

a) mobile devices need to conserve energy. Part of the value they offer. So you need to save resources. Threads are an expensive resource. Halt the progress of a thread is an unacceptable waste of this resource.

b) Nowadays the user is much more demanding. To assist them, we believe that it deserves to have full working CPU and the smallest possible expenditure of energy. Its application is not alone on the device, there is an unknow number of another apps running at same time and your app is not necessarily the most urgent.

c) system-level locks are not an option: a mobile device works with a number of events and services in the background and it is not right for any of them can be locked by an application.

Think about the user receiving a phone call while your "system lock" is working...

Based on the above facts, the answer to the proposed question are:

  • There is a viable way to build a dialog that blocks the main thread until a response from the user?

No. Workarounds do user experience get worse and it may make the mistake of blaming the system itself. This is unfair and penalizes the platform and all its developers.

  • Is there a way to block the entire system with a dialogue?

No. This is strictly forbidden on the platform. No application can interfere with the operation of the system or other applications.

  • I need to refactor my application, or rethink my way of programming to suit me on the Android mobile system architecture.

Yes. Including this aspect.

Renascienza
  • 1,647
  • 1
  • 13
  • 16
0

you set onclick listeners to you buttons. dissmis dialog and do your action. Don't need to halt anything

protected Dialog onCreateDialog(int id) {
  return new AlertDialog.Builder(this).setTitle(R.string.no_connection).setIcon(android.R.drawable.ic_dialog_alert).setView(textEntryView).setPositiveButton(R.string.exit, new DialogInterface.OnClickListener() 
{

   public void onClick(DialogInterface dialog, int whichButton) {

  // Here goes what you want to do
  }

})
}

to call - ex - showDialog(DIALOG_ERROR_PREF);

More http://developer.android.com/guide/topics/ui/dialogs.html

Alex Volovoy
  • 67,778
  • 13
  • 73
  • 54
  • Hey, that was not really what I wanted I think. Whenever a popup is display, the code that follows should NOT be executed until after I have pressed one of the buttons in the popup. The value of the button-press should be returned to the caller, so that the caller then can decide what to do... I will update my question above. – Ted Jan 08 '10 at 16:07
  • 2
    Since it's not really a .Net i think you have to adapt. And it's not a desktop either. Break your flow into events. You've did some action to display dialog. Now User reacts by pressing the buttons. Well - call doDamage(); dontDoDamage() methods. And continue from there – Alex Volovoy Jan 08 '10 at 16:37
0
UserSelect =null

AlertDialog.Builder builder = new Builder(ImonaAndroidApp.LoginScreen);
            builder.setMessage("you message");
            builder.setPositiveButton("OK", new OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int which) {
                    UserSelect = true ;

                }
            });

            builder.setNegativeButton("Cancel", new OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int which) {
                    UserSelect = false ;

                }
            });
           // in UI thread
        builder.show();             
        // wait until the user select
            while(UserSelect ==null);
  • That last line of yours, "while (UserSelect == null);" - that one is a killer. Your phone will enter into an endless loop, and will actually heat up the CPU for no reason and empty the battery, and make the entire phone slow. – David Svarrer Oct 15 '20 at 12:24
0

I am using Xamarin.Android (MonoDroid), and I have requirments for developing UI Blocking confirm box. I am not going to argue with the client because I can see good reasons for why they want that (details here), so I need to implement this. I tried @Daniel and @MindSpiker above, but these did not work on MonoForAndroid, the moment the message is sent between the threads, the app is crashed. I assume it is something to do with Xamarin mapping.

I ended up creating a separate thread from the UI thread and then blocking that and waiting for the user response as follows:

// (since the controllers code is shared cross-platforms)
protected void RunConfirmAction(Action runnableAction)
{
    if (runnableAction != null)
    {
        if (Core.Platform.IsAndroid)
        {
            var confirmThread = new Thread(() => runnableAction());
            confirmThread.Start();
        }
        else
        {
            runnableAction();
        }
    }
}

// The call to the logout method has now changed like this:
RunConfirmAction(Logout);

// the implemtation of the MessageBox waiting is like this:
public DialogResult MessageBoxShow(string message, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton)
{
    if (_CurrentContext != null && _CurrentContext.Screen != null && MainForm.MainActivity != null)
    {
        Action<bool> callback = OnConfirmCallBack;
        _IsCurrentlyInConfirmProcess = true;
        Action messageBoxDelegate = () => MessageBox.Show(((Activity)MainForm.MainActivity), callback, message, caption, buttons);
        RunOnMainUiThread(messageBoxDelegate);
        while (_IsCurrentlyInConfirmProcess)
        {
            Thread.Sleep(1000);
        }               
    }
    else
    {
        LogHandler.LogError("Trying to display a Message box with no activity in the CurrentContext. Message was: " + message);
    }
    return _ConfirmBoxResult ? DialogResult.OK : DialogResult.No;

}

private void OnConfirmCallBack(bool confirmResult)
{
    _ConfirmBoxResult = confirmResult;
    _IsCurrentlyInConfirmProcess = false;
}

private bool _ConfirmBoxResult = false;
private bool _IsCurrentlyInConfirmProcess = false;

Full details on how to do this can be found in my blog post here

Has AlTaiar
  • 4,052
  • 2
  • 36
  • 37
0

just to answer your question...btw sry that i'm 9 months late:D...there's a "workaround" 4 this kind of problems. i.e.

new AlertDialog.Builder(some_class.this).setTitle("bla").setMessage("bla bla").show();
wait();

simply add wait();

and them in the OnClickListener start the class again with notify() something like this

@Override
    public void onClick(DialogInterface dialog, int item) {
        Toast.makeText(getApplicationContext(), "test", Toast.LENGTH_LONG).show();
        **notify**();
        dialog.cancel();
    }

the same workaround goes 4 toasts and other async calls in android

derekerdmann
  • 17,696
  • 11
  • 76
  • 110
mc_fish
  • 17
  • 1
  • Thanks =) If I ever start looking at Android again, I will try it. I have however dropped Android. At least for now. – Ted Nov 22 '10 at 20:28
  • hehe i said i'm sorry:P just had the same problem and wanted people to know the workaround...of course it not simple as this...i ended up needing a new thread and 2 new runnables that where synchronized and so on...a little devilish problem if someone needs the full code...ask:) its big, i mean the code um oh hm – mc_fish Nov 25 '10 at 18:45
  • Hehe, thx for the info =) I'll remember that If I get into Android developement again =) – Ted Nov 29 '10 at 17:24
  • 2
    If you use this "workaround" you will get an ANR error in your app if your user doesn't reply with 10 seconds. This won't work. – Justin Breitfeller Dec 29 '11 at 16:49
0

Try this in a Thread (not the UI-Thread):

final CountDownLatch latch = new CountDownLatch(1);
handler.post(new Runnable() {
  @Override
  public void run() {
    OnClickListener okListener = new OnClickListener() {
    @Override
    public void onClick(DialogInterface dialog, int which) {
      dialog.dismiss();
      latch.countDown();
    }
  };

  AlertDialog dialog = new AlertDialog.Builder(context).setTitle(title)
    .setMessage(msg).setPositiveButton("OK", okListener).create();
  dialog.show();
}
});
try {
  latch.await();
} catch (InterruptedException e) {
  e.printStackTrace();
}
Konrad Viltersten
  • 36,151
  • 76
  • 250
  • 438
Geso
  • 1
0

let me as a thank you to the StackOverflow community, share something nice with you, where I have used the above example in Android code for HTTP calls, which now turns MODAL instead of the usual extra thread and the complexities of merging the threads by use of the a bit peculiar threading. (This is working in our app right now - 15 Oct 2020)

public JSONArray genericHttpModal(Context context, final String url, final JSONObject request) {

    this.url = url;    
    genericHttpRequestQueue = Volley.newRequestQueue(context);      
    class MyJsonReturn {
        JSONArray returnJsonArray;

        public void set(JSONArray i) {
            returnJsonArray = i;
        }

        public void set(String i) {
            try {
                returnJsonArray.put(0, i);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        public JSONArray get() {
            return returnJsonArray;
        }
    }

    final MyJsonReturn mymy = new MyJsonReturn();

    // Positive Response / HTTP OK.
    final Handler handler = new Handler() {
        @Override
        public void handleMessage(@NonNull Message msg) {
            throw new RuntimeException();
        }
    };

    final Response.Listener responseListener = new Response.Listener<String>() {
        @Override
        public void onResponse(String response) {
            try {
                mymy.set(new JSONArray(response));
            } catch (JSONException e) {
                mymy.set("[{\"JSONException:\"" + e.getMessage() + "\"}]");
            }
            handler.sendMessage(handler.obtainMessage());
        }
    };

    // Negative Response / HTTP NOT OK
    final Response.ErrorListener errorListener = new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            result = "fail";

            try {
                mymy.set(new JSONArray("[{\"JSONException:\"" + result + "\"}]"));
            } catch (JSONException e) {
                mymy.set("[{\"JSONException:\"" + e.getMessage() + "\"}]");
            }
            handler.sendMessage(handler.obtainMessage());
        }
    };


    final StringRequest httpRequest = new StringRequest(Request.Method.POST, URL_POINTER + url,
            responseListener,
            errorListener) {

        // Here the mRequestQueue handler will get the parameters for this request here.
        // Ref: https://stackoverflow.com/questions/33573803/how-to-send-a-post-request-using-volley-with-string-body#33578202
        // Ref: Multi Threaded solution 14 Oct 2020 (David Svarrer) : https://stackoverflow.com/questions/2028697/dialogs-alertdialogs-how-to-block-execution-while-dialog-is-up-net-style (This stackoverflow here)
        @Override
        protected java.util.Map<String, String> getParams() throws AuthFailureError {
            return jsonObjectToMap(request);
        }
    };
    httpRequest.setShouldCache(false); // Elijah: Could work on dropping the cache !!!
    genericHttpRequestQueue.add(httpRequest);    

    try {
        Looper.loop();
    } catch (RuntimeException re) {
    }
    return mymy.get();
}
0

Hu! Damn I was struggling whole day for this. Somehow I got workaround though I would't recommend it. You will have to use Handler to achieve this.
call getDialogBack function to get

boolean result =  getDialogBack(this);
Log.d(TAG, "onCreate: "+result);   

In getDialogBack write dialog and handler code to make it synchronous

public int getDialogBack(Context context,int i) {
        final Handler handler = new Handler(Looper.getMainLooper()) {

            @Override
            public void handleMessage(Message mesg) {
                throw new RuntimeException();
            }
        };

        AlertDialog.Builder alert = new AlertDialog.Builder(context);
        alert.setTitle("Title");
        alert.setMessage("Message");
        alert.setPositiveButton("Want to print next", new
                DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        handler.sendMessage(handler.obtainMessage());
                    }
                });
        alert.setNegativeButton("Return False", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                handler.sendMessage(handler.obtainMessage());
            }
        });
        alert.show();

        try {
            Looper.loop();
        } catch (RuntimeException e) {
        }

        return true;
    }
Kunchok Tashi
  • 2,413
  • 1
  • 22
  • 30
-1

This is the simplest way:

new AlertDialog.Builder(this).setTitle("title").setMessage("message").create().show();
Cytown
  • 1,539
  • 9
  • 7
  • Yes, but that doesnt solve the problem Im addressing I think, see my "EDIT 1" aboive in my question =) regards – Ted Jan 08 '10 at 16:24