Really sorry for duplicate threads for my bad network connection, but I was not advertising. I hope there is someone could help get rid of it. I admitted it's a terrible hack and not versions compatible.
It's a long story that I didn't get another choice but have to make a real modal dialog, otherwise, the worst situation is to build my own widget toolkit and ui framework. Anyway, sorry again if bothering. On Thu, Jun 2, 2011 at 9:05 PM, Mark Murphy <mmur...@commonsware.com> wrote: > IMHO, anybody who uses this code is a fool. > > This code assumes a certain implementation, let alone certain method > signatures, of the internal message-handling logic. This may not be > consistent across Android versions. Anyone using this is simply asking > for trouble. > > On Thu, Jun 2, 2011 at 8:51 AM, Qi Luo <regcollect...@gmail.com> 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 Developers" group. > > To post to this group, send email to android-developers@googlegroups.com > > To unsubscribe from this group, send email to > > android-developers+unsubscr...@googlegroups.com > > For more options, visit this group at > > http://groups.google.com/group/android-developers?hl=en > > > > -- > Mark Murphy (a Commons Guy) > http://commonsware.com | http://github.com/commonsguy > http://commonsware.com/blog | http://twitter.com/commonsguy > > Android 3.0 Programming Books: http://commonsware.com/books > > -- > You received this message because you are subscribed to the Google > Groups "Android Developers" group. > To post to this group, send email to android-developers@googlegroups.com > To unsubscribe from this group, send email to > android-developers+unsubscr...@googlegroups.com > For more options, visit this group at > http://groups.google.com/group/android-developers?hl=en -- You received this message because you are subscribed to the Google Groups "Android Developers" group. To post to this group, send email to android-developers@googlegroups.com To unsubscribe from this group, send email to android-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/android-developers?hl=en