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
wantoun
Posts: 165
Registered: ‎10-04-2010
My Device: P'9982 & Z10
My Carrier: alfa Lebanon
Accepted Solution

Global Dialog - show when application is in background

I have a function that pops-up a dialog for the user, and the user has to choose one of two options. The thing is, this function can be called when the user presses a certain button, or when the applciation is in the background. So to do this I'm using the following code:

 

synchronized(Application.getEventLock()){
	    	final Dialog d = new Dialog(Dialog.D_YES_NO, msg,
	   				Dialog.NO, Bitmap.getPredefinedBitmap(Bitmap.EXCLAMATION), Manager.VERTICAL_SCROLL);
	    	// So I would identify it as a Dialog
	    	if ( Application.isEventDispatchThread() ) {
		    	// We have the Event Thread, can just show the Dialog
		    	UiApplication.getUiApplication().pushModalScreen(d);
	    	} else {
		    	// running in background
		    	UiApplication.getUiApplication().invokeAndWait(new Runnable() {
		    	public void run() {
			    	NotificationsManager.triggerImmediateEvent(ID, 0, null, null);
			    	UiApplication.getUiApplication().pushGlobalScreen(d, 1, UiEngine.GLOBAL_MODAL);  
			    	NotificationsManager.cancelImmediateEvent(ID, 0, null, null);
		    		}
		    	});
	    	}
	    	return ( d.getSelectedValue() == Dialog.YES );
		}

 It works fine when the user presses the button that calls this function. However, when the function is called when the application is in the background nothing happens.

If you press the application icon again it doensn't get launched, the debugger says the application is requesting forground, but then says it's already running and doesn nothing. So the application gets stuck and you can't access it anymore.

 

How can I fix this and make the dialog pop-up to the user evern if the application is not in focus?

 

Thank you for your time.

 

 

Wadi
Please use plain text.
Contributor
jinchang
Posts: 44
Registered: ‎06-07-2010
My Device: 9630
My Carrier: Verizon

Re: Global Dialog - show when application is in background

Following might do the trick:

 

Application.getApplication().requestForeground();

 

Also, you can check to see if the application is in foreground using:

 

Application.getApplication().isForeground()

Please use plain text.
Developer
wantoun
Posts: 165
Registered: ‎10-04-2010
My Device: P'9982 & Z10
My Carrier: alfa Lebanon

Re: Global Dialog - show when application is in background

Thank you for your reply, but how would checking help me? The problem isn't that the application isn't being pushed to the foreground anymore, that's just a side effect. The problem is that the dialog is not being pushed when the appl

Wadi
Please use plain text.
Contributor
jinchang
Posts: 44
Registered: ‎06-07-2010
My Device: 9630
My Carrier: Verizon

Re: Global Dialog - show when application is in background

I was thinking that you can push the application to foreground (if in background) before showing the dialog.  If that is not what you want, then I'm not sure if it's possible to show only the dialog.

Please use plain text.
Developer
jprofitt
Posts: 604
Registered: ‎12-27-2010
My Device: Not Specified

Re: Global Dialog - show when application is in background

I've had issues with invokeAndWait() freezing up everything before. Unless you really need it, I'd use invokeLater().

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

Re: Global Dialog - show when application is in background

I realize this Thread has been solved, but thought I would contribute some thoughts, as the original code demonstrates some of the issues that you can face when trying to interact with the user when not being clear on how the Event Thread and Event Lock actually work.

 

I'm not saying that I actually understand it, I think I don't really, but the following 'model' has always worked for me.  Hopefully it will help you too.   Here goes..

 

There are two important points that sound similar but are not.  These points are distinct but work together.  You need to get your head around these.  So read the following carefully:

 

1) Event Lock: To make sure that UI changes are always synchronized, the BlackBerry will only update the UI when the Thread doing the update has the Event Lock, i,e,

 synchronized(Application.getEventLock()){
}

 

2) Event Thread: The BlackBerry is 'event driven', and is a multi-threaded.  To handle User Events, like key presses, it has a special Thread, called the Event Thread.  So the Event Thread is Thread that the OS will stick on short bits of processing.  These short bits of processing are 'Runnable's and include things like Menu items. 

 

OK, got this?

 

Because most of the "Events", like key presses, involve some change to the User Interface, there is, in fact, one more thing you need to know.  Things that are run on the Event Thread, automatically run with the Event Lock. So this is why you can update the Ui from a Menu tem, or fieldChanged event or touchEvent without getting the Event Lock, because you are running on the Event Thread. 

 

Now we are ready to look at the code.  I'm going to go through the important lines in order:

 

a) synchronized(Application.getEventLock()){

This means that the code has the EventLock.  If this bit of processing is running as a result of a menu press of touch Event or the like, this actually does nothing - the processing will be running on the Event Thread and will already have the Event Lock.  If it is running from a background Thread, then this will get the Event lock.  As a result, the Event Thread will be stopped - so nothing can process any user interaction. 

 

b) if ( Application.isEventDispatchThread() ) {
As the comment states, if the processing is running on the Event Thread, then the modal screen can be pushed.  Since the synchronized was not needed, perhaps this code could be restructured to test this first. 

 

c) UiApplication.getUiApplication().invokeAndWait(new Runnable() ....

Now we use invokeAndWait when we are not running on the EventThread, but we wish to wait.  So this code has asked the processing to stop the current Thread, place the Runnable in the queue for the Event Thread, and wait till the Event Thread runs it!  However, the synchronized done at (a) has blocked the Event Thread.  So we are deadlocked. 

 

I hope this explains what you see in this case. 

 

One solution is to do what has been suggested, and use invokeLater.  In this case, the Runnable is just placed on the queue for the Event Thread to process, then we exit the synchronized block and let the Event Thread get on with what it needs to do.  So this solution will work.  (In addition, it does not need the Event Lock, so the synchronized block can go completely.) 

 

The issue with this solution is that it does not directly stop the background Thread until the answer has been obtained.  I am not aware of an easy way to do this.  The DialogClosedListener is the 'standard' way to do this, using a wait() in the background Thread and a notify() in the DialogClosedListener to wake up the background Thread. 

 

Final thoughts:

 

synchronized(Application.getEventLock()){
}

is dangerous code.  Only use it when you know what tyou are doing.  If you are not sure, use

 

UiApplication.getUiApplication().invokelater(...);

when do don't want to wait and

 

UiApplication.getUiApplication().invokeAndWait(...);

when you do. 

 

Hope this helps. 

Please use plain text.