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

Alternate entry point background application thread issues

Hello and good day ,

I have a blackberry applicaton (one project) in the eclipse workspace that consists of an application class and a uiapplication class i have an issue with the background application the task is to check the server for new messages and store it to the sdcard , when the ui application is launched all it needs to do is fetch the messages from the db , i used globaleventlistener to display the messages on the ui screen if the uiapplication is on the foreground ,

i have two issues one is that the background thread seems to stop as time goes on here is the background app code 

 

package carniriv;

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

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

import org.json.me.JSONArray;
import org.json.me.JSONException;
import net.rim.blackberry.api.browser.URLEncodedPostData;
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 carniriv.db.DBConnect;
import carniriv.utilities.Utilities;
import cv.beans.Messages;
import cv.beans.Users;
import cv.db.PinDb;
import cv.interfaces.ObserverInterface;
import cv.logger.Logger;
import cv.network.HttpRequest;

/*
*
* background application to fetch data and do background tasks
* @author insolsoft-lab
*
*/
public final class BackgroundApp extends Application implements GlobalEventListener, ObserverInterface
{
public static final long GUID = 0x1157fd5912e85d7bL;
private boolean _initialized = false;

private static BackgroundApp bApp = null;

private BackgroundApp()
{
initializeGlobalListener();
// instantiate thread

}

void initializeGlobalListener()
{
synchronized (this)
{
if (!_initialized)
{
registerGlobalEventListener();

//do other setup stuff if needed

_initialized = true;
}
}
}

void registerGlobalEventListener()
{
addGlobalEventListener(this);
}
public void removeGlobalEventListener()
{
//clean up listeners and shutdown the app
removeGlobalEventListener(this);

}

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

return false;
}

public static synchronized BackgroundApp getInstance()
{
if (bApp == null)
{
bApp = new BackgroundApp();
}
return bApp;
}

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

public void loadDB()
{
try {
if(isSDCardPresent())
{
if(!DBConnect.isDBFileLoaded())
{
DBConnect.copyDBRecommendedWay();

}

}
} catch (IOException e) {

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

}
}

// start the thread that will fetch for messages every 10mins
public void startMessageFetcher()
{
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());

}
MessageObserverThread message_thread = new MessageObserverThread(this);
message_thread.start();

}

 

public void updateMessage(Vector values)
{
try {
PinDb.save(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(t.getClass().getName() + "Message:"+t.getMessage());


}


public void eventOccurred(long guid, int data0, int data1, Object object0,Object object1)
{
if (guid == LaunchUI.GUID)
{

}

}

 

/**
*
* Thread that runs behind the scenes to fetch json feed data @ intervals
* by default 10 mins
* @author insolsoft-lab
*
*/
private class MessageObserverThread extends Thread
{

private static final int RUNNING_TIME = 600000;
boolean stopThread = false;
ObserverInterface oi;

public synchronized void stop()
{
stopThread = true;
}

public MessageObserverThread(ObserverInterface oi)
{
this.oi = oi;

}



/**
* fetch the json data from the server that contains all the latest feeds
*
* @return vector
*/
private Vector fetchData() throws IOException, JSONException, NullPointerException
{

URLEncodedPostData post_data = new URLEncodedPostData(URLEncodedPostData.DEFAULT_CHARSET, false);
post_data.append("user_id", Users.getUserID());

Vector v = new Vector();
try {
HttpRequest post = new HttpRequest(Utilities.SERVER_HOST+"pinboard/load_messages.php", post_data,HttpConnection.POST);
JSONArray result = new JSONArray(post.postData());
int chunk = result.length();
//Messages[] msg = new Messages[chunk];
// check if there are any results from the server
if(chunk == 0)
{

return null;
}
for(int i = 0 ; i < chunk; i++)
{
Messages messages = new Messages();
messages.setMessages(result.getJSONObject(i).getString("messages"));
messages.setId(result.getJSONObject(i).getString("id"));
messages.setDate_time(result.getJSONObject(i).getString("time_mins"));
messages.setUser_id(result.getJSONObject(i).getString("user_id"));
messages.setProfile_pic_name(result.getJSONObject(i).getString("profile_pic"));
messages.setUser_name(result.getJSONObject(i).getString("user_name"));
messages.setDisplay_name(result.getJSONObject(i).getString("display_name"));


v.addElement(messages);





}
return v;

} catch (IOException e)
{

throw new IOException(e.getMessage());
} catch (JSONException e) {

throw new JSONException("Unable to retrieve data from our servers at this time.");
}
catch (NullPointerException e)
{

throw new NullPointerException(e.getMessage());
}

}


// thread runner method
public void run()
{

Vector tasks;


try {
while( ! stopThread)
{
tasks = fetchData();
if(tasks != null)
{

synchronized(tasks)
{
oi.updateMessage(tasks);
}

}
sleep(RUNNING_TIME);
}

} catch (NullPointerException e)
{
Logger.error("NullPointer @ MessageObserverThread run()"+e.getMessage());
} catch (IOException e)
{
Logger.error("IO @ MessageObserverThread run()"+e.getMessage());
} catch (JSONException e) {
Logger.error("JSON @ MessageObserverThread run()"+e.getMessage());
} catch (InterruptedException e)
{
Logger.error("Thread fetch error BackgroundApp run()"+e.getMessage());
}



}

 

 

2) the second issue is  the ui application does not display the messages after it gets a notification  and i wonder why cause the globalevent listener  is registered to it here is the ui application class 

package carniriv;

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

import carniriv.db.DBConnect;
import carniriv.pinboard.PinManager;
import carniriv.utilities.Utilities;
import cv.beans.Users;
import cv.logger.Logger;
import net.rim.device.api.system.GlobalEventListener;
import net.rim.device.api.ui.UiApplication;

public final class LaunchUI extends UiApplication implements GlobalEventListener
{


private boolean acceptsForeground = false;
private static LaunchUI launcher_ui = null;
private boolean _initialized = false;
public final static long GUID = 0x86b7d64e823da44fL;
/**
*
* Entry point for application
* @param args Command line arguments (not used)
*/
protected boolean acceptsForeground()
{

return acceptsForeground;

}

private LaunchUI()
{
//register global event listener
initialize();
doStartupWork();
}

void initialize()
{
synchronized (this)
{
if (!_initialized)
{
registerGlobalEventListener();

//do other setup stuff if needed

_initialized = true;
}
}
}


public void removeGlobalEventListener()
{
//clean up listeners and shutdown the app
removeGlobalEventListener(this);

}


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

public static synchronized LaunchUI getInstance()
{
if(launcher_ui == null)
{
launcher_ui = new LaunchUI();
}
return launcher_ui;
}


/**
*
* do start up work
*/
private void doStartupWork()
{
try {
if(!Utilities.isSDCardAvailable())
throw new IOException("Please insert an sd card to use carniriv");
// check if the db file is in the sd card
if(DBConnect.isDBFileLoaded())
{
acceptsForeground = true;


UiApplication.getUiApplication().requestForeground();
// check if the user is authenticated
String val = Users.isAuthenticated();
// nothing is returned that means he is not registered
if(val == null)
{
pushScreen(new RegisterScreen());
}
// if true take him straight to app console
else if(val.equals("true"))
{

pushScreen( ConsoleScreen.getInstance());
}
//if not any of the above take him to the login screen
else
{
pushScreen( new WelcomeScreen(true));
}
}
else
{
// copy the db file to sd card
DBConnect.copyDBRecommendedWay();
pushScreen( new WelcomeScreen());
}
} catch (Throwable e)
{
Logger.error(e.getMessage());
}
}


public void eventOccurred(long guid, int data0, int data1, Object object0,Object object1)
{

if(guid == BackgroundApp.GUID)
{
Vector v = (Vector)object1;

PinManager.getInstance().update(v);
v.removeAllElements();


}


}

 

}

 

}

}

 

thanks.

Please use plain text.
Developer
simon_hain
Posts: 16,010
Registered: ‎07-29-2008
My Device: Z10 LE
My Carrier: O2 Germany

Re: Alternate entry point background application thread issues

i would suggest to avoid static variables to share stuff between instances, as each instance has its own set.
public static synchronized BackgroundApp getInstance() <-- this code will not work as expected when called from the ui part, better use runtime store or global events for IPC.

for the background thread it seems that you don't enter the event dispatcher:
http://www.blackberry.com/developers/docs/7.1.0api/net/rim/device/api/system/Application.html#enterE...
without that i suspect that your application object is just cleaned up after it is created, or at least after the spawned thread is finished.

i would suggest that you check some sample applications to see how they use enterEventDispatcher.
----------------------------------------------------------
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
Please use plain text.