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
Posts: 132
Registered: ‎10-25-2011
My Device: Tour 9630
My Carrier: MTN

Alternate entry point and applicationmanager.scheduleapplication

Hello and good day .

Please iam bulding a blackberry aplication that requires an alternate entry point(aep) and a gui applicatio n , the background app is supposed to fetch data from server every 10minutes always , i was using a background thread but i upgraded to ApplicationManager.getApplicationManager().scheduleApplication method because on my os7 device the appliction resource monitor kept shutting down my app , isuspected it was the background thread that runs every 10 minutes so i changed it , now here is the problem 

1) I want the application to fetch data which is sorted out out from my main method 

2) when it fetches the data and the ui is in view it should update the ui with the data from server , i used global event listener but no update on my ui here is my main class code 

 

package carniriv;

import java.io.IOException;
import java.util.Vector;

import javax.microedition.io.file.FileSystemRegistry;

import net.rim.device.api.database.DatabaseException;
import net.rim.device.api.io.MalformedURIException;
import net.rim.device.api.system.Application;
import net.rim.device.api.system.ApplicationDescriptor;
import net.rim.device.api.system.ApplicationManager;
import net.rim.device.api.system.ControlledAccessException;
import net.rim.device.api.system.GlobalEventListener;
import carniriv.db.DBConnect;
import cv.db.PinDb;
import cv.interfaces.ObserverInterface;
import cv.logger.Logger;


/**
* This class extends the UiApplication class, providing a
* graphical user interface.
*/
public class Launcher extends Application implements GlobalEventListener , ObserverInterface
{


public static long GUID = 0xe44401a5e5012d2bL;
private static Launcher launcher = null;

public static Launcher getInstance()
{
if(launcher == null)
{
launcher = new Launcher();
}
return launcher ;
}

public Launcher()
{
//sleep until the device is started
while(ApplicationManager.getApplicationManager().inStartup())
{
try
{
Thread.sleep(500);
}
catch (Throwable error)
{
Logger.error("Launcher while app in start up"+ error.getMessage());
}
}


loadDB();


try {
// sleep for 10 secs before starting thread just to ensure that all is well
Thread.sleep(10000);
} catch (InterruptedException e)
{
Logger.error("CarnRiv waiting thread..." + e.getMessage());

}




}
public void startMessageFetcher()
{
// start the thread that fetches the data from server
MessageObserverThread mto = new MessageObserverThread(this);
mto.start();
// app manager to run this application every 10 minutes
ApplicationDescriptor current = ApplicationDescriptor.currentApplicationDescriptor();
current.setPowerOnBehavior(ApplicationDescriptor.DO_NOT_POWER_ON);
ApplicationManager manager = ApplicationManager.getApplicationManager();
manager.scheduleApplication(current, System.currentTimeMillis() + 600000, true);
}

public void addGlobalListener()
{
addGlobalEventListener(this);
}

public static void main( String[] args)
{


if ( args != null && args.length > 0 && args[0].equals("autoboot"))
{
//background process
Launcher l = Launcher.getInstance();
l.addGlobalListener();
l.startMessageFetcher();

}
else
{
// home icon clicked launch gui
LaunchUI ui = new LaunchUI();
ui.enterEventDispatcher();

}

}


public void updateMessage(Vector values)
{

try {
PinDb.save(values);

// fire the global event listener passing the vector that contains the data so far it always does every 10 mins 
ApplicationManager.getApplicationManager().postGlobalEvent(GUID, 0, 0, null, values);

}
catch (ControlledAccessException e)
{
errorOccured(e);
} catch (IllegalArgumentException e)
{

errorOccured(e);
}
catch (MalformedURIException e)
{

errorOccured(e);
} catch (IOException e) {

errorOccured(e);
} catch (DatabaseException e)
{
errorOccured(e);
}

}


public void errorOccured(Throwable t) {
Logger.error("Error in app Launcher"+ t.getMessage());

}


/**
*
* check if the sd card has been mounted
* @return
*/
private static boolean isSDCardPresent()
{
java.util.Enumeration roots = FileSystemRegistry.listRoots();
while (roots.hasMoreElements())
{
String root = (String) roots.nextElement();
if ( root.equals( "SDCard/" ) ) {
return true;
}
}

return false;
}



/**
*
* load the database into file system
*/

public static void loadDB()
{
try {
// is sdcard present
if(isSDCardPresent())
{
if(!DBConnect.isDBFileLoaded())
{
DBConnect.copyDBRecommendedWay();

}

}
} catch (IOException e) {

Logger.error(e.getMessage());
} catch (Throwable e)
{
Logger.error(e.getMessage());

}
}

public void eventOccurred(long guid, int data0, int data1, Object object0,
Object object1) {
// TODO Auto-generated method stub

}

 

 

 

 

The global event listening class that displays the ui also works very well , i believe that the something is wrong in the event firing , thanks.



}

Developer
Posts: 19,636
Registered: ‎07-14-2008
My Device: Not Specified

Re: Alternate entry point and applicationmanager.scheduleapplication

You seem to having problems with this, since this is very similar to your previous posts:

 

1) http://supportforums.blackberry.com/t5/Java-Development/Alternate-entry-point-background-application...

 

2) http://supportforums.blackberry.com/t5/Java-Development/background-process-issue/m-p/1969285#M210877

 

I'm not sure you have appreciated what Simon and i have told you in these Threads.  I recommend you read them and our responses again.

 

Anyway, I recommend that you approach your development a step at a time and not try to solve all your problems at once since they are related and complicating the situation.

 

So I'm going to suggest you build this Application in parts. The first part to look at is the background process that communicates with the Server.  To make this easier to develop and debug, we build it in the foreground first. 

 

You said:

"i was using a background thread but i upgraded to ApplicationManager.getApplicationManager().scheduleApplication method because on my os7 device the application resource monitor kept shutting down my app"

 

I suspect that there is a problem in this 'background' processing, which is why the monitor shut it down.  So we will start by getting this working correctly.

 

So create a start-up UiApplication.  In the UiApplication, have it check that it is safe to run, and then once it is so, it should push a screen, and start a Background Thread that downloads the data from the Server.  This Background Thread is the code that you are using to update the data every 10 minutes.  When the application starts up and displays the screen, leave it for a few minutes to make sure the background Thread is working fine with the screen in the foreground.  If you are sure this is working fine, then use the task switcher to put the Screen in the background.  Do not, repeat not, close the screen.  Leave this running in the background.  Now leave it running for sometime and make sure the monitor does not shut it down. 

 

As a aside, I would program this as a Timer that triggers every 10 minutes.  When it is triggered, it should start a network Thread.  The network Thread will do the actual communication.  Do not run the networking on the Timer process. 

 

I suspect you will have some problems with this, especially on 7.1, and we need to resolve these before you can go much further with your processing. 

 

But if there was a general problem in OS 7.1 with this sort of processing, (i.e. fetching data at regular intervals from a background Thread), then there would loads of applications that didn't work properly, so my suspicion is that there is a problem with your code.  And you need to sort it out before you start moving into Alternate Entry processing. 

 

Anyway, let us know when you get his working fine, and we can move onto the next phase - updating the Ui!

 

Also I think this is better start up code:

http://supportforums.blackberry.com/t5/Java-Development/Write-safe-initialization-code/ta-p/444795

Developer
Posts: 132
Registered: ‎10-25-2011
My Device: Tour 9630
My Carrier: MTN

Re: Alternate entry point and applicationmanager.scheduleapplication

Thanks peter , like i said the fetch process is working perfectly fine the only problem is the updating the ui , if u check the code for this post u will notice what i said the it is working , my problem is updating the ui.

Developer
Posts: 19,636
Registered: ‎07-14-2008
My Device: Not Specified

Re: Alternate entry point and applicationmanager.scheduleapplication

[ Edited ]

It may be working, but I do not believe it is working correctly.  In my opinion, if it was working correctly you would not have the problem with the Monitor shutting it down.  You appear to have worked around this problem not solved it, at least to my mind.  I think we should solve it. 

 

Similarly, if I look at the code you have supplied it is not clear that the background process actually starts an Application which enters the dispatcher - which is what I suggested.  Nor do you appear to have removed the static code which looks unnecessary, which is what Simon recommended. 

 

So I would prefer to discard the code you currently have, since it appears to me it is likely to be flawed and not best practice anyway.  I would prefer to start again and  build something that is possibly more robust and that you understand.. 

 

But that is my opinion.  It is your application and your decision as to whether you really need to look at the areas I have pointed out.  If you want to continue just focusing on fixing the UI, then go ahead. 

Developer
Posts: 132
Registered: ‎10-25-2011
My Device: Tour 9630
My Carrier: MTN

Re: Alternate entry point and applicationmanager.scheduleapplication

Ok i will take my time to reengineer , will continue aftertrying something out , thanks for your time 

Developer
Posts: 132
Registered: ‎10-25-2011
My Device: Tour 9630
My Carrier: MTN

Re: Alternate entry point and applicationmanager.scheduleapplication

Ok nowi have been able to place the thread in my timertask and used safe methods and it works great i get my messages in the db every 10mins , now my problem still lies in updating the ui here is my code 

package carniriv;

import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;

import javax.microedition.io.file.FileSystemListener;
import javax.microedition.io.file.FileSystemRegistry;

import net.rim.device.api.database.DatabaseException;
import net.rim.device.api.io.MalformedURIException;
import net.rim.device.api.system.Application;
import net.rim.device.api.system.ApplicationManager;
import net.rim.device.api.system.ControlledAccessException;
import net.rim.device.api.system.GlobalEventListener;
import net.rim.device.api.system.SystemListener;
import net.rim.device.api.ui.component.Dialog;
import carniriv.db.DBConnect;
import cv.db.PinDb;
import cv.interfaces.ObserverInterface;
import cv.logger.Logger;


/**
* This class extends the UiApplication class, providing a
* graphical user interface.
*/
public class Launcher extends Application implements SystemListener,FileSystemListener, ObserverInterface, GlobalEventListener
{


public static long GUID = 0xe44401a5e5012d2bL;


public Launcher()
{

}


public static void main( String[] args)
{

if ( args != null && args.length > 0 && args[0].equals("autoboot"))
{
//background process

Launcher launcher = new Launcher();
// If system startup is still in progress when this
// application is run.
if (ApplicationManager.getApplicationManager().inStartup())
{
launcher.addSystemListener(launcher);
launcher.addFileSystemListener(launcher);
launcher.addGlobalEventListener(launcher);
// wait a little before starting timers
try {
Thread.sleep(1000);
} catch (InterruptedException e)
{
Logger.error("Error"+ e.getMessage());
}

// timer starts in this method
launcher.startMessageFetcher(launcher);

}
else
{
launcher.doStartupWorkLater();

}

//launcher.doStartupWorkLater();
launcher.enterEventDispatcher();


}
else
{
// home icon clicked launch gui
LaunchUI ui = new LaunchUI();
ui.enterEventDispatcher();

}

}

/**
*
* class to start the timer threads to fetch message from server
*/
private void startMessageFetcher(Launcher l)
{
//Dialog.alert("Woo");
final Launcher launcher = l;
TimerTask timer_task = new TimerTask()
{
public void run()
{

MessageObserverThread messenger = new MessageObserverThread(launcher);
messenger.start();
}
};
Timer timer = new Timer();
timer.scheduleAtFixedRate(timer_task, 1000, 600000);
}

/** @see SystemListener#powerUp() */
public void powerUp()
{
removeSystemListener(this);
loadDB();
}


private void doStartupWorkLater() {
invokeLater(new Runnable() {
public void run() {
loadDB();
}
});
}

/**
*
* check if the sd card has been mounted
* @return
*/
private static boolean isSDCardPresent()
{
java.util.Enumeration roots = FileSystemRegistry.listRoots();
while (roots.hasMoreElements())
{
String root = (String) roots.nextElement();
if ( root.equals( "SDCard/" ) ) {
return true;
}
}

return false;
}



/**
*
* load the database into file system
*/

public static void loadDB()
{
try {
// is sdcard present
if(isSDCardPresent())
{
if(!DBConnect.isDBFileLoaded())
{
DBConnect.copyDBRecommendedWay();

}

}
} catch (IOException e) {

Logger.error(e.getMessage());
} catch (Throwable e)
{
Logger.error(e.getMessage());

}
}

 

 

public void batteryGood() {
// TODO Auto-generated method stub

}

 

 

public void batteryLow() {
// TODO Auto-generated method stub

}

 

 

public void batteryStatusChange(int status) {
// TODO Auto-generated method stub

}

 

 

public void powerOff() {
// TODO Auto-generated method stub

}


public void rootChanged(int state, String rootName)
{

loadDB();
FileSystemRegistry.removeFileSystemListener(this);



}



public void updateMessage(Vector values)
{
try {

PinDb.save(values);
//PinManager.getInstance().update(values);
ApplicationManager.getApplicationManager().postGlobalEvent(GUID, 0, 0, null, values);

}
catch (ControlledAccessException e)
{
errorOccured(e);
} catch (IllegalArgumentException e)
{

errorOccured(e);
}
catch (MalformedURIException e)
{

errorOccured(e);
} catch (IOException e)
{

errorOccured(e);
} catch (DatabaseException e)
{
errorOccured(e);
}

}

 


public void errorOccured(Throwable t)
{
Logger.error("Error in app Launcher"+ t.getMessage());


}


public void eventOccurred(long guid, int data0, int data1, Object object0,
Object object1) {
// TODO Auto-generated method stub

}

 

 

 

 

 

 

 





}

Developer
Posts: 19,636
Registered: ‎07-14-2008
My Device: Not Specified

Re: Alternate entry point and applicationmanager.scheduleapplication

You Background startup code looks wrong to me.

 

The if looks like it is the wrong way round.  You should leave as much initialization till after the device has gone through start-up as you can.  So please review the safe initialization link I gave you previously and check that regardless of whether your code is invoked in a start up situation or not, it still ends up doing exactly the same things.  You need to think about this to get your head around it, but it will come. 

 

Now the second question, why is the background task a global listener.  Surely the UI should be the listener.  The background task will fire the events.

 

So think about these two things and work on the code. 

 

Remember that a background task still has a Event Dispatch Thread, and so you can still do this:

Application.getApplication().invokeLater(new Runnable() {

public void run() {

// code in here will run on the tasks Event Thread

}

});

 

The good thing about this code, especially at start-up, is it not run until you really have a working application, running in the dispatcher.  So this is in fact a good place to put start up code. 

Developer
Posts: 132
Registered: ‎10-25-2011
My Device: Tour 9630
My Carrier: MTN

Re: Alternate entry point and applicationmanager.scheduleapplication

Thanks peter , are u saying that my start up code should be in a while loop instead something like this while(applicationmanager.instartup) loop and in that loop I wait a little , and then after the loop is done , I use my invoke later to run my start up codes such as starting the timer? , throw me an example pls it will make me understand better , thanks .
Developer
Posts: 132
Registered: ‎10-25-2011
My Device: Tour 9630
My Carrier: MTN

Re: Alternate entry point and applicationmanager.scheduleapplication

As for the if thats the way the app works on autostartup , im not sure its the other way round 

public static void main( String[] args)
{

if ( args != null && args.length > 0 && args[0].equals("autoboot"))
{
//background process

Launcher launcher = new Launcher();
// If system startup is still in progress when this
// application is run.
if (ApplicationManager.getApplicationManager().inStartup())
{
launcher.addSystemListener(launcher);
launcher.addFileSystemListener(launcher);

// wait a little before starting timers
try {
Thread.sleep(1000);
} catch (InterruptedException e)
{
Logger.error("Error"+ e.getMessage());
}

// background process starts here 
launcher.startMessageFetcher(launcher);

}
else
{
launcher.doStartupWorkLater();

}


launcher.enterEventDispatcher();


}
else
{
// home icon clicked launch gui
LaunchUI ui = new LaunchUI();
ui.enterEventDispatcher();

}

}

Developer
Posts: 19,636
Registered: ‎07-14-2008
My Device: Not Specified

Re: Alternate entry point and applicationmanager.scheduleapplication

The boolean

ApplicationManager.getApplicationManager().inStartup()

a) is true if the application is in start-up.  This will happen to autostart programs when the device is rebooted (like a battery out restart). 

b) is false when the device is already up and running.  Typically this will happen when you have just installed the app, say via App World, and the device has not been restarted. 

 

When this value is true you typically need to wait until the device is no longer in start-up to start your application.  There are two ways of doing this.  Have a wait loop, or set a SystemListener - using a SystemListener you know you app has started when it goes through powerUp.  The second method is the one demonstrated in the KB article I pointed you at and is more complicated but is the approach I prefer.  However since it is more complicated, in your case you might want to use the wait approach.  The reason I don't like this wait approach is this statement from the API:

"During startup, all threads must quiesce in order for the startup process to move on to the next startup tier."

So it seems to me that by waiting in the Thread you could in fact be slowing down the start-up.  But perhaps not, this is not something I have asked RIM about and the wait loop comes from a RIM KB article too. 

 

Regardless, you need to make sure that your processing through both values is the same.  It doesn't look like it is too me.

 

The comment about using invokeLater was just FYI, using it might make your startup processing simpler because when this code runs, you know you have a fully functioning application.  So I typically would put things like the globalEventListener or start the network processing in there.  But that is again just me trying to be 'tidy' in the  way I interact with the OS.  It is more confusing code.  Since this is not something you are familiar with, perhaps simple is best.