Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Java Development

Reply
Developer
aleitzinger
Posts: 47
Registered: ‎06-05-2009
My Device: Not Specified

Something so simple is so difficult - App that monitors inbox

Hi, I have simple (should be) requirements for an app with a Listfield on the MainScreen that displays info extracted from emails.

 

when the app starts up I need to scan the inbox so I can update the Mainscreen with new data.

 

THE PROBLEM:  My messages are bigger than 2kb so I need to use the MessageListener.  In the Changed() event handler for the MessageListener I need to refresh my ListField. In my Main() I use UIApplication.getUIApplication.invokeandwait(...) to run my code.

It doesn't work. My code in Run()... blows up because I and access the UI controls from whatever thread/state/whatever my code is in.

 

This must be a common pattern. Starting a listener at startup with a callback that executes and has to update the MainScreen (some UI?)

 

Are there samples, docs etc etc ANYTHING that would show how this should be done?

Developer
EpicDraws
Posts: 109
Registered: ‎02-09-2009
My Device: Not Specified

Re: Something so simple is so difficult - App that monitors inbox

Set the list field to dirty using setDirty(true) and then invalidate() the manager.
Developer
simon_hain
Posts: 16,282
Registered: ‎07-29-2008
My Device: Z10 LE, Z30, Passport

Re: Something so simple is so difficult - App that monitors inbox

aleitzinger your assumption is correct, the listener runs in the context of its host application, in your case the mail application.
you have to give the listener a reference to your application (i use an interface called applicationservice) and run invokelater on it to return to the correct context.
----------------------------------------------------------
feel free to press the like button on the right side to thank the user that helped you.
please mark posts as solved if you found a solution.
@SimonHain on twitter
Developer
aleitzinger
Posts: 47
Registered: ‎06-05-2009
My Device: Not Specified

Re: Something so simple is so difficult - App that monitors inbox

Hi, I did use the invokeAndWait() but I'm still getting exceptions accessing the ListField control  (invalid context or the like).

 

The issue is I'm calling the the code which attaches the MessageListener from the  Main() method.  I read somewhere that this code gets

executed in a separate process from the application not just a separate thread?

 

This is a simple scenario to test.  Implement MessageListener on the UIApplication subclass.  Attach the listener in the Main() of the app

and in the changed() (or other callback) try to update a TextField on the application's MainScreen.

 

 

Developer
simon_hain
Posts: 16,282
Registered: ‎07-29-2008
My Device: Z10 LE, Z30, Passport

Re: Something so simple is so difficult - App that monitors inbox

you have A, your application. and there is M, the mail appliction.
i A, you add a listener L to M.

M receives a message and triggers the listener method.
The listener is executed by M.

To circumvent this you do the following:
Create L with A as a parameter.
In Ls method call A.invokeLater(new Runnable(){public void run(){YOUR CODE HERE}});

now 'YOUR CODE HERE' gets executed in the context of A.

Do not execute blocking code like this. if you want to do networking or anything else you have to wrap your code into an own thread.
----------------------------------------------------------
feel free to press the like button on the right side to thank the user that helped you.
please mark posts as solved if you found a solution.
@SimonHain on twitter
Developer
Developer
CMY
Posts: 1,123
Registered: ‎02-10-2009
My Device: 8130 / 8350 / 9530 / 9550 / 9850 / PlayBook

Re: Something so simple is so difficult - App that monitors inbox

I believe you are correct. Main is static and therefore not part of the actual UiApplication, calling UiApplication from within main should not work as your app has not been created yet. You can create a method in your calls and then call it before you enter the event dispatcher.

 

ie

 

class MyClass {

 

   myClass(){ //intialize }

   void invokeListener(){ //do work }

 

   public void main(String [] args) {

      MyClass mc = new MyClass();

      mc.invokeListener();

      mc.enterEventDispatcher();

   }

 

}

Developer
aleitzinger
Posts: 47
Registered: ‎06-05-2009
My Device: Not Specified

Re: Something so simple is so difficult - App that monitors inbox

[ Edited ]

Hi,

 

That's what I did and it does not work.

I see simplified code snippet below.

 

 

MyUIApp extends UIApplication implements MessageListener

     static MyUIApp objMyUIAppSingleton;

     MyScreen objMyScreen;

     public MyUIApp() {

         objMyScreen = new MyScreen();

         pushScreen(objMyScreen);

     }

 

     public static void main(String[] args) {
         objMyUIAppSingleton = new MyUIApp();

         // now process the inbox and if we find a multipart message we have to add 

         // "this" as the MessageListener

         Message objSomeMessage = // some multipart emailmessage

         objSomeMessage.addListener(this);

         objMyUIAppSingleton.enterEventDispatcher();
     }

 

     // MessageListener Event Handler

     void changed(...) {

       // in here I update my MainScreen

      UIApplication.getUIApplication().invokeAndWait(new runnable() {

           void run() {

                  objMyUIAppSingleton.objMyScreen.objTextField.setText("Blablabla");  // THIS CAUSES EXCEPTION - Invalid state 

           }

     }  

 

    class MyUIApp extends MainScreen {

         TextField objTextField;

          public  MyUIApp() {

              objTextField = new TextField("mylabel","blank");

              // ... standard code - add control to the screen

         }

    }

}

Message Edited by aleitzinger on 07-31-2009 10:40 AM
Developer
aleitzinger
Posts: 47
Registered: ‎06-05-2009
My Device: Not Specified

Re: Something so simple is so difficult - App that monitors inbox

Hi,

The problem is that the event handler on MAIN gets called when the rest of the multi-part email arrives which can/will be after the UIApplication has started.  The Event handler in Main needs to notify the UIApplication to refresh because the shared data in GlobalResource has been modified.

 

I can't sit and wait for the Multi-part emails to arrive before launching the app since I can't control when that will finish.

 

Is there some way to do some work AUTOMATICALLY once the Screen is loaded and the UIApp is executing? Maybe I can spin up a thread that polls the data to see if it's changed (simplified for discussion) by the MessageListener code?

 

Thanks

Developer
simon_hain
Posts: 16,282
Registered: ‎07-29-2008
My Device: Z10 LE, Z30, Passport

Re: Something so simple is so difficult - App that monitors inbox

no, you use UIApplication.getUIApplication().invokeLater, not yourApp.invokeLater.

if you use UIApplication.getUIApplication() within the listener method you get the mail application.

please also note that you can not create a singleton in a static context like this, at least not if you want to use it in a different entry point. you will have to use RuntimeStore for that (but don't let it disturb you now, i just wanted to amend it).

do not use the same class name for the MainScreen as for your main application (or is it just a copy and paste error?)
----------------------------------------------------------
feel free to press the like button on the right side to thank the user that helped you.
please mark posts as solved if you found a solution.
@SimonHain on twitter
Developer
Developer
CMY
Posts: 1,123
Registered: ‎02-10-2009
My Device: 8130 / 8350 / 9530 / 9550 / 9850 / PlayBook

Re: Something so simple is so difficult - App that monitors inbox

Simon is right, and in your main method you are passing this as the argument to the listener, but this does not refer to your app since it is called in main. Pass your MyUiApp as the argument to the listener as that is the reference for your app.