Question

I am trying to implement a "Wait Screen" in my BlackBerry app. The screen is to appear when the user clicks "Login" and it should go away after login has successfully been made. I am calling the screen in the "Login" listener after which I call a methd to fetch data from webs ervice. When the data is fetched, and the new screen is shown, the "Wait Screen" should disappear. However, on clicking login I get Uncaught - RuntimeException after which new screen is displayed with the "Waiting Screen" on top of it. Can somebody help me with this?

public class MessageScreen extends PopupScreen
{
    private String message;

    public MessageScreen (String message)
    {
        super( new HorizontalFieldManager(), Field.NON_FOCUSABLE);
        this.message = message;
        final BitmapField logo = new BitmapField(Bitmap.getBitmapResource( "cycle.gif"));
        logo.setSpace( 5, 5 );
        add(logo);

        RichTextField rtf = new RichTextField(message, Field.FIELD_VCENTER | Field.NON_FOCUSABLE | Field.FIELD_HCENTER);
        rtf.setEditable( false );

        add(rtf);
    }
}

I am calling this in the "Login" click event - button listener.

public void fieldChanged(Field field, int context)
{
    // Push appropriate screen depending on which button was clicked
    String uname = username.getText();
    String pwd = passwd.getText();
    if (uname.length() == 0 || pwd.length()==0) {
        Dialog.alert("One of the textfield is empty!");
    } else {
        C0NNECTION_EXTENSION=checkInternetConnection();
        if(C0NNECTION_EXTENSION==null)
        {
            Dialog.alert("Check internet connection and try again");
        }
        else
        {
            UiApplication.getUiApplication().invokeLater( new Runnable()
            {
                public void run ()
                {
                    UiApplication.getUiApplication().pushScreen( new MessageScreen("Signing in...") );
                }
            } );
            doLogin(uname, pwd);
        }
    }
}

private String doLogin(String user_id, String password)
{
    String URL ="";
    String METHOD_NAME = "ValidateCredentials";
    String NAMESPACE = "http://tempuri.org/";
    String SOAP_ACTION = NAMESPACE+METHOD_NAME;
    SoapObject resultRequestSOAP = null;
    HttpConnection httpConn = null;
    HttpTransport httpt;
    SoapPrimitive response = null;
    SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
    request.addProperty("username", user_id);
    request.addProperty("password", password);
    System.out.println("The request is=======" + request.toString());
    SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
    envelope.dotNet = true;
    envelope.setOutputSoapObject(request);
    httpt = new HttpTransport(URL+C0NNECTION_EXTENSION);
    httpt.debug = true;
    try
    {
        httpt.call(SOAP_ACTION, envelope);
        response = (SoapPrimitive) envelope.getResponse();
        String result =  response.toString();
        resultRequestSOAP = (SoapObject) envelope.bodyIn;
        String[] listResult = split(result, sep);
        strResult = listResult[0].toString();
        strsessionFirstName = listResult[1].toString();
        strsessionLastName = listResult[2].toString();
        strsessionPictureUrl = MAINURL + listResult[3].substring(2);
        strsessionStatusId = listResult[4].toString();
        strsessionStatusMessage = listResult[5].toString();
        strsessionLastUpdateTst = listResult[6].toString();

        if(strResult.equals("credentialaccepted"))
        {
            if(checkBox1.getChecked() == true)
            {
                persistentHashtable.put("username", user_id);
                persistentHashtable.put("password", password);
            }
            Bitmap bitmap = getLiveImage(strsessionPictureUrl, 140, 140);
            StatusActivity nextScreen = new StatusActivity();
            nextScreen.getUsername(user_id);
            nextScreen.getPassword(password);
            nextScreen.setPictureUrl(bitmap);
            nextScreen.setImage(strsessionPictureUrl);
            nextScreen.setFirstName(strsessionFirstName, strsessionLastName, strsessionLastUpdateTst, strsessionStatusMessage);
            UiApplication.getUiApplication().pushScreen(nextScreen);
            UiApplication.getUiApplication().invokeLater( new Runnable()
            {
                public void run ()
                {
                    UiApplication.getUiApplication().pushScreen( UiApplication.getUiApplication().getActiveScreen() );
                }
            } );
        }
        if(strResult.equals("credentialdenied"))
        {
            Dialog.alert("Invalid login details.");
            UiApplication.getUiApplication().pushScreen(new LoginTestScreen() );
        }
    } catch (IOException e) {
        // TODO Auto-generated catch block
        System.out.println("The exception is IO==" + e.getMessage());
    } catch (XmlPullParserException e) {
        // TODO Auto-generated catch block
        System.out.println("The exception xml parser example==="
        + e.getMessage());
    }

    System.out.println( resultRequestSOAP);
    //UiApplication.getUiApplication().pushScreen( UiApplication.getUiApplication().getActiveScreen() );
    return response + "";

    //UiApplication.getUiApplication().pushScreen(new InfoScreen());
    //Open a new Screen
} 
Was it helpful?

Solution

Like Eugen said, you should run doLogin() on a background Thread:

final String uname = username.getText();
final String pwd = passwd.getText();

Thread backgroundWorker = new Thread(new Runnable() {
    public void run() {
        doLogin(uname, pwd);
    }
});

backgroundWorker.start();

If you do that, you'll need to use UiApplication.invokeLater() (or another similar technique) to show your screens (back on the main/UI thread). You can't leave the doLogin() method exactly as it originally was, because it makes calls to change the UI. For example, you have a couple calls to directly use pushScreen(), which should not be called (directly) from the background.

This is not ok (from the background):

        UiApplication.getUiApplication().pushScreen(nextScreen);

But, this is:

        UiApplication.getUiApplication().invokeLater( new Runnable()
        {
            public void run ()
            {
                UiApplication.getUiApplication().pushScreen(nextScreen);
            }
        } );

But, also, what is this code supposed to do? :

        UiApplication.getUiApplication().pushScreen(nextScreen);
        UiApplication.getUiApplication().invokeLater( new Runnable()
        {
            public void run ()
            {
                UiApplication.getUiApplication().pushScreen( UiApplication.getUiApplication().getActiveScreen() );
            }
        } );

This doesn't make sense to me. What are you trying to do with those lines of code?

OTHER TIPS

I see only one issue so far - networking in the UI thread. Please put all your networ operations into another Thread.run().

You could also get more detailed error description by: 1) Navigate to home screen 2) Hold alt button and press LGLG on the keyboard 3) Explore showed event log for specific error

try this -

public void fieldChanged(Field field, int context)
{
// Push appropriate screen depending on which button was clicked
String uname = username.getText();
String pwd = passwd.getText();
if (uname.length() == 0 || pwd.length()==0) {
    Dialog.alert("One of the textfield is empty!");
} else {
    C0NNECTION_EXTENSION=checkInternetConnection();
    if(C0NNECTION_EXTENSION==null)
    {
        Dialog.alert("Check internet connection and try again");
    }
    else
    {

    Dialog busyDialog = new Dialog("Signing in...", null, null, 0, Bitmap.getPredefinedBitmap(Bitmap.HOURGLASS));
    busyDialog.setEscapeEnabled(false);
    synchronized (Application.getEventLock()) {
    busyDialog.show();
    }
    doLogin(uname, pwd);
    }
}
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top