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
New Contributor
Wes_Scharf
Posts: 4
Registered: ‎02-05-2013
My Device: BlackBerry 9900
My Carrier: Rogers
Accepted Solution

Multiple instances of Application when using background thread

Hi all,

 

I recently added a background thread into an application that is launched from an alternate entry point. This background thread will constantly (every X seconds) do RMS checks and compare timestamps. When necesarry, it will send a notification to the user that launches the application when clicked. The problem is..

 

When the user clicks the notification, it will open the application normally (with the icon and everything), but it also opens a second instance that does not have an icon. I have determined that the code that actually launches the application is not the culprit (because if I take it out, it still opens the second instance). This is making me think it has something to do with the ApplicationDescriptor.

 

My notification manager has this line:

 

ApplicationDescriptor appDescriptor = new ApplicationDescriptor(ApplicationDescriptor.currentApplicationDescriptor(), APPLICATION_NAME, new String[] {});

 

If I change this to only return the currentApplicationDescriptor() or add any arguments in the string array, the notifications do not function at all.

 

Can anyone think of a reason why this might be happening?

Please use plain text.
Developer
peter_strange
Posts: 19,603
Registered: ‎07-14-2008
My Device: Not Specified

Re: Multiple instances of Application when using background thread

The thing you need to be aware of is that an alternate entry can be another instance of your application.  So if you start an alternate entry, and this runs in the background, you can have a second instance of your application.  it all depends on what you code in your Main.

 

So unless we see your main method we can not really comment on this.  but what you are seeing is possible.

Please use plain text.
New Contributor
Wes_Scharf
Posts: 4
Registered: ‎02-05-2013
My Device: BlackBerry 9900
My Carrier: Rogers

Re: Multiple instances of Application when using background thread

Hi Peter,

 

This is our main method. (Removed some preprocs and such to simplify).

 

private static void processMainArgs(String[] args) {
if (args != null && args.length != 0 && args[0].equals("rollover")) {
ApplicationManager appMan = ApplicationManager.getApplicationManager();
boolean keepGoing = true;
Bitmap regularIcon = Bitmap.getBitmapResource("icon.png");
Bitmap icon = Bitmap.getBitmapResource("icon_roll_over.png");
while (keepGoing) {
if (appMan.inStartup()) {
// BlackBerry is still starting up
try {
Thread.sleep(1000);
} catch (Exception e) {}
} else {
try {
HomeScreen.updateIcon(regularIcon, 0);
HomeScreen.setRolloverIcon(icon, 0);
keepGoing = false;
} catch (Exception e) {}
}
}
System.exit(0);
} else if (args != null && args.length != 0 && args[0].equals("notification")) {
initFolderRegistry();
}
}


This method is called when the alternate entry point sends "notification" through the main args. It will then call init() on our notification manager.

 

private static void initFolderRegistry() {
final NotificationManager notificationManager = new NotificationManager();

final EncodedImage indicatorIcon = EncodedImage.getEncodedImageResource(RESOURCE_COD_NAME, INDICATOR_ICON_NAME);
final ApplicationIcon applicationIcon = new ApplicationIcon(EncodedImage.getEncodedImageResource(RESOURCE_COD_NAME, INDICATOR_ICON_NAME));
final ApplicationIndicatorRegistry indicatorReg = ApplicationIndicatorRegistry.getInstance();
indicatorReg.register(applicationIcon, true, false);

final ApplicationMessageFolderRegistry reg = ApplicationMessageFolderRegistry.getInstance();
if (reg.getApplicationFolder(NotificationManager.INBOX_FOLDER_ID) == null) {
notificationManager.init();
}

notificationManager.enterEventDispatcher();
}

 

Lastly, this is the init() call that happens in the NotificationManager itself:

 

public void init() {

final ApplicationMessageFolderRegistry folderReg = ApplicationMessageFolderRegistry.getInstance();
final ApplicationDescriptor mainDescription = ApplicationDescriptor.currentApplicationDescriptor();
final ApplicationDescriptor appDescriptor = new ApplicationDescriptor(mainDescription, APPLICATION_NAME, new String[] {});

//#if BB_OS_VERSION >= 7.0
final ApplicationFolderIntegrationConfig inboxIntegration = new ApplicationFolderIntegrationConfig(true, true, mainDescription);
final ApplicationFolderIntegrationConfig deletedIntegration = new ApplicationFolderIntegrationConfig(false);
//#endif
final MessageListStore messages = MessageListStore.getInstance();
//#if BB_OS_VERSION >= 7.0
final ApplicationMessageFolder inbox = folderReg.registerFolder(NotificationManager.INBOX_FOLDER_ID, "Inbox", messages.getInboxMessages(), inboxIntegration );
final ApplicationMessageFolder deleted = folderReg.registerFolder(NotificationManager.DELETED_FOLDER_ID, "Deleted Messages", messages.getDeletedMessages(), deletedIntegration );
//#else
final ApplicationMessageFolder inbox = folderReg.registerFolder(NotificationManager.INBOX_FOLDER_ID, "Inbox", messages.getInboxMessages());
final ApplicationMessageFolder deleted = folderReg.registerFolder(NotificationManager.DELETED_FOLDER_ID, "Deleted Messages", messages.getDeletedMessages());
//#endif

//#if BB_OS_VERSION >= 7.0
inbox.addListener(this, ApplicationMessageFolderListener.MESSAGE_DELETED | ApplicationMessageFolderListener.MESSAGE_MARKED_OPENED | ApplicationMessageFolderListener.MESSAGE_MARKED_UNOPENED | ApplicationMessageFolderListener.MESSAGES_MARKED_OLD, appDescriptor);
deleted.addListener(this, ApplicationMessageFolderListener.MESSAGE_DELETED, appDescriptor);
//#else
inbox.addListener(this, ApplicationMessageFolderListener.MESSAGE_DELETED | ApplicationMessageFolderListener.MESSAGE_MARKED_OPENED | ApplicationMessageFolderListener.MESSAGE_MARKED_UNOPENED, appDescriptor);
deleted.addListener(this, ApplicationMessageFolderListener.MESSAGE_DELETED, appDescriptor);
//#endif

messages.setFolders(inbox, deleted);
folderReg.setRootFolderName(APPLICATION_NAME);

final ApplicationIcon icon = new ApplicationIcon(EncodedImage.getEncodedImageResource(RESOURCE_COD_NAME, INDICATOR_ICON_NAME));

folderReg.registerMessageIcon(MagmicMessage.MAGMIC_MESSAGE_TYPE, STATUS_NEW, icon);
folderReg.registerMessageIcon(MagmicMessage.MAGMIC_MESSAGE_TYPE, STATUS_OPENED, icon);
folderReg.registerMessageIcon(MagmicMessage.MAGMIC_MESSAGE_TYPE, STATUS_DELETED, icon);

final ApplicationMenuItem openMenuItem = new OpenContextMenu(0x230010);
final ApplicationMenuItem markOpenedMenuItem = new MarkOpenedContextMenu(0x230030);
final ApplicationMenuItem markUnopenedMenuItem = new MarkUnreadContextMenu(0x230040);

final ApplicationMenuItem[] newGuiMenuItems = new ApplicationMenuItem[] { openMenuItem };
final ApplicationMenuItem[] newDaemonMenuItems = new ApplicationMenuItem[] { markOpenedMenuItem };
final ApplicationMenuItem[] openedGuiMenuItems = new ApplicationMenuItem[] { openMenuItem };
final ApplicationMenuItem[] openedDaemonMenuItems = new ApplicationMenuItem[] { markUnopenedMenuItem };
final ApplicationMenuItem[] deletedGuiMenuItems = new ApplicationMenuItem[] { openMenuItem };

folderReg.registerMessageMenuItems(MagmicMessage.MAGMIC_MESSAGE_TYPE, STATUS_NEW, newGuiMenuItems, appDescriptor);
folderReg.registerMessageMenuItems(MagmicMessage.MAGMIC_MESSAGE_TYPE, STATUS_NEW, newDaemonMenuItems, appDescriptor);
folderReg.registerMessageMenuItems(MagmicMessage.MAGMIC_MESSAGE_TYPE, STATUS_OPENED, openedGuiMenuItems, appDescriptor);
folderReg.registerMessageMenuItems(MagmicMessage.MAGMIC_MESSAGE_TYPE, STATUS_OPENED, openedDaemonMenuItems, appDescriptor);
folderReg.registerMessageMenuItems(MagmicMessage.MAGMIC_MESSAGE_TYPE, STATUS_DELETED, deletedGuiMenuItems, appDescriptor);

folderReg.setBulkMarkOperationsSupport(MagmicMessage.MAGMIC_MESSAGE_TYPE, STATUS_NEW, true, false);
folderReg.setBulkMarkOperationsSupport(MagmicMessage.MAGMIC_MESSAGE_TYPE, STATUS_OPENED, false, true);

//#if QA_BUILD
int timerCheckInterval = 5000; // Five seconds for QA builds
//#else
int timerCheckInterval = 60000; // One minute for production builds
//#endif

UpdateThread updateThread = new UpdateThread(timerCheckInterval, messages, new ApplicationIcon(EncodedImage.getEncodedImageResource(RESOURCE_COD_NAME, INDICATOR_ICON_NAME)), ApplicationIndicatorRegistry.getInstance());
updateThread.run();

(new NotificationManager()).enterEventDispatcher();
}

 

The thread that is opened at the bottom of init() is what we use to do our RMS checks. It will continuously run and notify the user when our daily lottery goes off.

 

Is there a better way to do this besides using a background thread? Would I be able to make all of this work in a single application? That would ultimately be much better.

 

Thanks a lot for the response.

 

Please use plain text.
New Contributor
Wes_Scharf
Posts: 4
Registered: ‎02-05-2013
My Device: BlackBerry 9900
My Carrier: Rogers

Re: Multiple instances of Application when using background thread

Actual main() if that is important too:

 

public static void main(String[] args) {
processMainArgs(args);
BlackBerry controller = new BlackBerry();
//#if USES_BB_MESSENGER && BB_OS_VERSION >= 5.0
controller.checkBBMIntegration(args);
//#endif
controller.setAcceptableScreenDirections();
controller.enableKeyUpEvents(true);
Core core = Core.create(controller);
core.setCanvas(controller.canvas);
controller.pushScreen(controller.canvas);
core.start();
controller.enterEventDispatcher();
}

Please use plain text.
New Contributor
Wes_Scharf
Posts: 4
Registered: ‎02-05-2013
My Device: BlackBerry 9900
My Carrier: Rogers

Re: Multiple instances of Application when using background thread

I have resolved the problem I was having.

 

In the end, I ended up changing this code:

 

final ApplicationDescriptor mainDescription = ApplicationDescriptor.currentApplicationDescriptor();
final ApplicationDescriptor appDescriptor = new ApplicationDescriptor(mainDescription, APPLICATION_NAME, new String[] {});

 

to:

 

int moduleHandle = CodeModuleManager.getModuleHandle(APPLICATION_NAME);
ApplicationDescriptor mainDescriptor;

if (moduleHandle != 0)
{
ApplicationDescriptor[] apDes = CodeModuleManager.getApplicationDescriptors(moduleHandle);
mainDescriptor = apDes[0];

ApplicationMessageFolderRegistry folderReg = ApplicationMessageFolderRegistry.getInstance();

if (folderReg.getApplicationFolder(NotificationManager.INBOX_FOLDER_ID) == null) {
notificationManager.init(folderReg, mainDescriptor);
}
}

 

 

Instead of using the currentApplicationDescriptor(), I had to reference the application module itself using the CoreModuleManager. My init method takes in the ApplicationDescriptor and uses it for everything.

 

Thanks to everyone who took any time to read through my post!

 

Please use plain text.