黑莓 - 启动时显示对话框,等待对话框关闭

时间:2012-05-16 14:23:01

标签: blackberry dialog startup

我尝试了很多,现在我需要你的帮助。我想做的是以下内容: 当Blackberry应用程序启动时,会弹出“是/否”对话框。 如果用户选择“是”,请执行一些操作并继续启动。如果用户选择“否”退出应用程序。

我写了一个SSCCE,如果你选择“是”并且你应该听到声音,它应该振动。当然我知道,在调用Alert.vibrate()之后代码会继续,并且它不会等待vibraste完成。无论如何,这只是一个例子。对vibrate()的调用应首先进行,并且在播放声音之前应完全处理dialogClosed()。

SSCCE是我到目前为止所得到的。我尝试了很多其他的东西。我敢肯定它不会那么难。我只是不明白。

这是:

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();
        }
    });

}
}

好的,其他一些SSCCE。这将启动并显示一个对话框,但随后会抛出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");
}

}

所以我在wait()调用周围放了一个synchronized块,因为我读过,调用wait()时必须同步该对象。但现在应用程序什么也没显示。它运行主方法,但某处停止。在模拟器中发生了非常奇怪的事情:当模拟器仍处于启动状态并且在显示器上写入“调试器附加”时,将调用应用程序的主要方法。好吧,这是带有synchronized块的SSCCE。仍然无效。

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");
}

}

最后我尝试利用忙碌的等待。仍然没有成功。对话框不会弹出。即使在主线程的while循环中使用Thread.sleep(1000),UI线程似乎也无法工作。这是忙着等待的SSCCE:

    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");
    }

}

感谢您的帮助。

Haferblues

2 个答案:

答案 0 :(得分:1)

使用invokeAndWait代替invokeLater。

private void showDialog(final Dialog d)
{

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

}

答案 1 :(得分:1)

我终于在黑莓论坛得到了答案:http://supportforums.blackberry.com/t5/Java-Development/Startup-YES-NO-Dialog-should-stop-the-launchign-process-of-the/m-p/1725085

最终解决方案对我有用(并且看起来比我上面所做的更好)如下:

    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));

        }

    }

}

感谢双方的大力支持。