Blackberry - Show Dialog on startup and wait until dialog closes

谁都会走 提交于 2019-12-23 00:49:27

问题


I tried a lot, now I need your help. What I want to do is the following: When the Blackberry app starts a yes/no dialog pops up. If user chooses "yes", do something and AFTER that continue with the startup. If user chooses "no" exit the app.

I wrote an SSCCE which should vibrate if you choose "yes" and AFTER THAT you should hear a sound. Of course I know, that the code continues after the Alert.vibrate() is called and it doesn't wait for the vibraste to finish. Anyway, it is just an example. The call to vibrate() should come first and the dialogClosed() should be processed completely before the sound is played.

The SSCCE is what I got so far. I tried lots of other things. I'm sure it can't be that difficult. I just don't get it.

Here it is:

package TestDialog;

import net.rim.device.api.system.Alert;
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.Dialog;
import net.rim.device.api.ui.component.DialogClosedListener;

public class TestDialog extends UiApplication
{

public static short[] SOUND_ALERT = { 523, 200, //C for 200ms
                0, 200, //Pause 200ms
                554, 200, //C# 200ms
                0, 200, //Pause 200ms
                587, 200, //D 200ms
                0, 200, //Pause 200ms
                622, 200         //D# 200ms         
                                  };

/**
 * @param args
 */
public static void main(final String[] args)
{

    final TestDialog test = new TestDialog();
    test.enterEventDispatcher();

}

public TestDialog()
{

    //the dialog
    final Dialog d = new Dialog(Dialog.D_YES_NO, "vibrate?", Dialog.OK, Bitmap.getPredefinedBitmap(Bitmap.QUESTION), Dialog.FIELD_TOP);
    d.setDialogClosedListener(new DialogClosedListener()
    {

        public void dialogClosed(final Dialog dialog, final int choice)
        {
            if (d.getSelectedValue() == Dialog.YES)
            {
                Alert.startVibrate(2000);
                //do something which takes some time
            }
            else
            {
                System.exit(0);
            }

        }
    });

    //show the dialog
    showDialog(d);

    //now wait for the dialog to call notify
    try
    {
        synchronized (this)
        {
            this.wait();
        }
    }
    catch (final Exception e)
    {
        System.out.println(e.getMessage());
    }

    //finally AFTER the dialog has been closed and everything in dialogClosed() has been done, play a sound
    Alert.startAudio(SOUND_ALERT, 100);

}

private void showDialog(final Dialog d)
{

    UiApplication.getUiApplication().invokeLater(new Runnable()
    {
        public void run()
        {
            d.doModal();
            this.notify();
        }
    });

}
}

OK, some other SSCCE. This starts and shows a dialog, but then throws an IllegalMonitorExcpetion:

package TestDialog;

import net.rim.device.api.system.Bitmap;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.Dialog;

public class TestDialog extends UiApplication
{

public static short[] SOUND_ALERT = { 523, 200, //C for 200ms
                0, 200, //Pause 200ms
                554, 200, //C# 200ms
                0, 200, //Pause 200ms
                587, 200, //D 200ms
                0, 200, //Pause 200ms
                622, 200         //D# 200ms         
                                  };

/**
 * @param args
 */
public static void main(final String[] args)
{

    final TestDialog test = new TestDialog();
    test.enterEventDispatcher();

}

public TestDialog()
{

    UiApplication.getUiApplication().invokeLater(new Runnable()
    {
        public void run()
        {
            //the dialog
            final Dialog d = new Dialog(Dialog.D_YES_NO, "vibrate?", Dialog.OK, Bitmap.getPredefinedBitmap(Bitmap.QUESTION), Dialog.FIELD_TOP);

            if (d.doModal() == Dialog.YES)
            {
                System.out.println("selection made yes");
                this.notify();
            }
            else
            {
                System.out.println("selection made no");
                System.exit(0);
            }

        }
    });


        try
        {
            this.wait();
        }
        catch (final Exception e)
        {
            e.printStackTrace();
        }


    //finally AFTER the dialog has been closed and everything in dialogClosed() has been done, play a sound
    System.out.println("done");
}

}

So I put a synchronized block around the wait() call, since I read, that the object must be synchronized when calling wait(). But now the app shows nothing. It runs the main-method but somewhere stops. In Simulator very strange things happen: When the simulator is still in startup and "debugger attaching" is written on the display, the main-method of the app is called. Well, here is the SSCCE with the synchronized block. Still doesn't work.

package TestDialog;

import net.rim.device.api.system.Bitmap;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.Dialog;

public class TestDialog extends UiApplication
{

public static short[] SOUND_ALERT = { 523, 200, //C for 200ms
                0, 200, //Pause 200ms
                554, 200, //C# 200ms
                0, 200, //Pause 200ms
                587, 200, //D 200ms
                0, 200, //Pause 200ms
                622, 200         //D# 200ms         
                                  };

/**
 * @param args
 */
public static void main(final String[] args)
{

    final TestDialog test = new TestDialog();
    test.enterEventDispatcher();

}

public TestDialog()
{

    UiApplication.getUiApplication().invokeLater(new Runnable()
    {
        public void run()
        {
            //the dialog
            final Dialog d = new Dialog(Dialog.D_YES_NO, "vibrate?", Dialog.OK, Bitmap.getPredefinedBitmap(Bitmap.QUESTION), Dialog.FIELD_TOP);

            if (d.doModal() == Dialog.YES)
            {
                System.out.println("selection made yes");
                this.notify();
            }
            else
            {
                System.out.println("selection made no");
                System.exit(0);
            }

        }
    });

    synchronized (this)
    {
        try
        {
            this.wait();
        }
        catch (final Exception e)
        {
            e.printStackTrace();
        }
    }

    //finally AFTER the dialog has been closed and everything in dialogClosed() has been done, play a sound
    System.out.println("done");
}

}

And finally I tried making use of busy waiting. Still no success. The Dialog just doesn't pop up. Even with the Thread.sleep(1000) in the while loop in the main thread the UI thread seems not to work. Here is the SSCCE with the busy waiting:

    package TestDialog;

import net.rim.device.api.system.Bitmap;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.Dialog;

public class TestDialog extends UiApplication
{
    /**
     * @param args
     */
    public static void main(final String[] args)
    {

        final TestDialog test = new TestDialog();
        test.enterEventDispatcher();

    }

    private volatile boolean _blocked = true;

    public TestDialog()
    {

        UiApplication.getUiApplication().invokeLater(new Runnable()
        {
            public void run()
            {
                //the dialog
                final Dialog d = new Dialog(Dialog.D_YES_NO, "vibrate?", Dialog.OK, Bitmap.getPredefinedBitmap(Bitmap.QUESTION), Dialog.FIELD_TOP);

                if (d.doModal() == Dialog.YES)
                {
                    System.out.println("selection made yes");
                    _blocked = false;
                }
                else
                {
                    System.out.println("selection made no");
                    System.exit(0);
                }

            }
        });

        while (_blocked)
        {
            try
            {
                Thread.sleep(1000);
            }
            catch (final Exception e)
            {
                //safety catch
            }
        }
        finish();

    }

    private void finish()
    {
        System.out.println("done");
    }

}

Thanks for your help.

Haferblues


回答1:


HI I finally got an answer in the Blackberry forum here: http://supportforums.blackberry.com/t5/Java-Development/Startup-YES-NO-Dialog-should-stop-the-launchign-process-of-the/m-p/1725085

The final solution, which works for me (and looks much nicer then everything I did above) is as follows:

    package TestDialog;

import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.Dialog;
import net.rim.device.api.ui.component.LabelField;
import net.rim.device.api.ui.component.RichTextField;
import net.rim.device.api.ui.container.MainScreen;

public class TestDialog extends UiApplication implements Runnable
{
    /**
     * @param args
     */
    public static void main(final String[] args)
    {

        final TestDialog test = new TestDialog();
        test.invokeLater(test);

        test.enterEventDispatcher();

    }

    public TestDialog()
    {

    }

    public void run()
    {

        final int answer = Dialog.ask(Dialog.D_YES_NO, "continue?");
        //        pushGlobalScreen(new Dialog(Dialog.D_YES_NO, "continue?", 0, null, Dialog.GLOBAL_STATUS), 1, TestDialog.GLOBAL_QUEUE | TestDialog.GLOBAL_MODAL);

        if (answer == Dialog.YES)
        {
            System.out.println("user clicked yes");
        }
        else
        {
            System.exit(0);
        }

        pushScreen(new MyScreen("App loaded"));
    }

    class MyScreen extends MainScreen
    {

        public MyScreen(final String msg)
        {

            final LabelField title = new LabelField("First Screen", LabelField.ELLIPSIS | LabelField.USE_ALL_WIDTH);
            setTitle(title);
            this.add(new RichTextField(msg));

        }

    }

}

Thanks for the great support on both sides.




回答2:


Use invokeAndWait instead invokeLater.

private void showDialog(final Dialog d)
{

    UiApplication.getUiApplication().invokeAndWait(new Runnable()
    {
        public void run()
        {
            d.doModal();
            this.notify();
        }
    });

}


来源:https://stackoverflow.com/questions/10620605/blackberry-show-dialog-on-startup-and-wait-until-dialog-closes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!