STOP PROMOTING THIS.  I am serious.  You are telling people to do something
that will cause their app to break.

On Thu, Jun 2, 2011 at 5:42 AM, Qi Luo <[email protected]> wrote:

>
> I saw much people wanted such a feature, me either. These days I've google-ed 
> around and tried serveral ways to get it right, finally ended up with 
> following solution. No thread synchronization, no dialog-themed activities, 
> really simple.
> Some useful resource and background,
>
>
> http://groups.google.com/group/android-developers/browse_thread/thread/5616a220c97a13fc/5e722e601f33d884#5e722e601f33d884
>
> http://stackoverflow.com/questions/2028697/dialogs-alertdialogs-how-to-block-execution-while-dialog-is-up-net-style
>
> Modal dialog is a typical widget in Win32, it could
> 1. block current workflow
>
> 2. capture all input (key, mouse) events, but still properly dispatch other 
> events, like paint
> 3. wait for response and quit
>
>
> People who's familiar with Win32 programming possibly knows how to implement 
> a modal dialog. Generally it runs a nested message loop (by 
> GetMessage/PostMessage) when there is a modal dialog up. So, I tried to 
> implement my own modal dialog in this traditional way.
>
> At the first, android didn't provide interfaces to inject into ui thread 
> message loop, or I didn't find one. When I looked into source, Looper.loop(), 
> I found it's exactly what I wanted. But still, MessageQueue/Message haven't 
> provided public interfaces. Fortunately, we have reflection in java.
>
> Basically, I just copied exactly what Looper.loop() did, it blocked workflow 
> and still properly handled events. I haven't tested nested modal dialog, but 
> theoretically it would work.
>
> Here's my source code,
>
> public class ModalDialog {
>     private boolean mChoice = false;
>     private boolean mQuitModal = false;
>     private Method mMsgQueueNextMethod = null;
>     private Field mMsgTargetFiled = null;
>     public ModalDialog() {
>     }
>     public void showAlertDialog(Context context, String info) {
>         if (!prepareModal()) {
>             return;
>         }
>         // build alert dialog
>         AlertDialog.Builder builder = new AlertDialog.Builder(context);
>         builder.setMessage(info);
>         builder.setCancelable(false);
>
>         builder.setPositiveButton("Yes", new 
> DialogInterface.OnClickListener() {
>             public void onClick(DialogInterface dialog, int id) {
>                 ModalDialog.this.mQuitModal = true;
>                 dialog.dismiss();
>             }
>         });
>         AlertDialog alert = builder.create();
>         alert.show();
>         // run in modal mode
>         doModal();
>     }
>     public boolean showConfirmDialog(Context context, String info) {
>         if (!prepareModal()) {
>             return false;
>         }
>         // reset choice
>         mChoice = false;
>         AlertDialog.Builder builder = new AlertDialog.Builder(context);
>         builder.setMessage(info);
>         builder.setCancelable(false);
>
>         builder.setPositiveButton("Yes", new 
> DialogInterface.OnClickListener() {
>             public void onClick(DialogInterface dialog, int id) {
>                 ModalDialog.this.mQuitModal = true;
>                 ModalDialog.this.mChoice = true;
>                 dialog.dismiss();
>             }
>         });
>
>         builder.setNegativeButton("Cancel", new 
> DialogInterface.OnClickListener() {
>             public void onClick(DialogInterface dialog, int id) {
>                 ModalDialog.this.mQuitModal = true;
>                 ModalDialog.this.mChoice = false;
>                 dialog.cancel();
>             }
>         });
>         AlertDialog alert = builder.create();
>         alert.show();
>         doModal();
>         return mChoice;
>     }
>     private boolean prepareModal() {
>         Class<?> clsMsgQueue = null;
>         Class<?> clsMessage = null;
>         try {
>             clsMsgQueue = Class.forName("android.os.MessageQueue");
>         } catch (ClassNotFoundException e) {
>             e.printStackTrace();
>             return false;
>         }
>         try {
>             clsMessage = Class.forName("android.os.Message");
>         } catch (ClassNotFoundException e) {
>             e.printStackTrace();
>             return false;
>         }
>         try {
>
>             mMsgQueueNextMethod = clsMsgQueue.getDeclaredMethod("next", new 
> Class[]{});
>         } catch (SecurityException e) {
>             e.printStackTrace();
>             return false;
>         } catch (NoSuchMethodException e) {
>             e.printStackTrace();
>             return false;
>         }
>         mMsgQueueNextMethod.setAccessible(true);
>         try {
>             mMsgTargetFiled = clsMessage.getDeclaredField("target");
>         } catch (SecurityException e) {
>             e.printStackTrace();
>             return false;
>         } catch (NoSuchFieldException e) {
>             e.printStackTrace();
>             return false;
>         }
>         mMsgTargetFiled.setAccessible(true);
>         return true;
>     }
>     private void doModal() {
>         mQuitModal = false;
>         // get message queue associated with main UI thread
>         MessageQueue queue = Looper.myQueue();
>         while (!mQuitModal) {
>             // call queue.next(), might block
>             Message msg = null;
>             try {
>
>                 msg = (Message)mMsgQueueNextMethod.invoke(queue, new 
> Object[]{});
>             } catch (IllegalArgumentException e) {
>                 e.printStackTrace();
>             } catch (IllegalAccessException e) {
>                 e.printStackTrace();
>             } catch (InvocationTargetException e) {
>                 e.printStackTrace();
>             }
>             if (null != msg) {
>                 Handler target = null;
>                 try {
>                     target = (Handler)mMsgTargetFiled.get(msg);
>                 } catch (IllegalArgumentException e) {
>                     e.printStackTrace();
>                 } catch (IllegalAccessException e) {
>                     e.printStackTrace();
>                 }
>                 if (target == null) {
>
>                     // No target is a magic identifier for the quit message.
>                     mQuitModal = true;
>                 }
>                 target.dispatchMessage(msg);
>                 msg.recycle();
>             }
>         }
>     }
> }
>
> Hopefully this would help.
>
>
> --
> You received this message because you are subscribed to the Google Groups
> "android-ndk" group.
> To post to this group, send email to [email protected].
> To unsubscribe from this group, send email to
> [email protected].
> For more options, visit this group at
> http://groups.google.com/group/android-ndk?hl=en.
>



-- 
Dianne Hackborn
Android framework engineer
[email protected]

Note: please don't send private questions to me, as I don't have time to
provide private support, and so won't reply to such e-mails.  All such
questions should be posted on public forums, where I and others can see and
answer them.

-- 
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en

Reply via email to