07-18-2012 09:31 PM
I have a question about bringing dialogs/applications to the foreground from applications running in the background. I've been looking at the developer documents, the HTTPPush applications, the forums and SO threads and really not gotten a good solution.
My application basically receives push notifications and displays them to the user - nothing fancy. However, given the nature of these notifications, I need to be able to notify the user as soon as they are recieved. My application registers and begins listening for pushes on startup, and continues listening in the background if they close the application (unless they choose to exit the application altogether.) Now, I need to be able to do two things:
1) Ask the user whether they wish to respond to the notification (that is, open the application and view detailed information), and
2) If they select to respond, bring them to the notification display screen in my application.
I've looked around at solutions for both of these, and I'm not clear on the best way to go about implementing these.
Now, as for 1), I was thinking of showing the user a popup (a Dialog object). However, I need the dialog to show up regardless of which application is currently in the foreground.
I don't think requestForeground() is the right choice: I'm calling this from my push listener thread, and I don't want to spawn a thread for each notification. I also just want to ask the user whether they want to restore my application to view the notification, not actually do it. (That's 2).)
I was hoping to use UiApplication.pushGlobalScreen() but that doesn't return anything (it takes the Dialog as an argument). Is there a way around this?
Is there some way to use the GLOBAL_STATUS flag to make one of the static methods show a global dialog? Could I create a thread just for the popup that brings it to the foreground and somehow get it to return the user's response?
For 2), once the user has responded in the affirmative (they want to display the notification), how do I send the user to the notification screen? I call a seperate method that spawns a thread updating the notification screen. Do I define a new entry point to bring the user to it, or are there other ways of accomplishing this?
Thanks a lot in advance,
07-18-2012 09:51 PM
For the sake of not starting two threads in quick succession, I have another semi-related question:
The API I am using has a class that handles listening for pushes. To use it, I have to instantiate an object. I want to actually place the thread code and push listener object in my because I don't want to check whether it's running every time the user enters the notification screen. I want to place it in main(), or at least in the app's constructor. However, then my PushListener isn't visible to any of my screens, so I'm not sure how to deregister on exit. Do you have any advice? Do I have to suck it up and just stick it in the notification screen class?
07-19-2012 04:48 AM
Good question and well explained.
There are actually a number of approaches. Here is the one I would take given my experience but I will tell you of some options I have not tried.
Firstly the way to notify the user. As you have seen, the option is a GLOBAL screen, either a Dialog pushed or one of your screens pushed with GLOBAL_STATUS. I have never done the later. So I would push a Dialog using UiApplication.pushGlobalScreen().
This approach is documented here:
There is another approach, which I can't find the KB article for, but as an example, this Thread uses it:
You don't need to do this because you have only one Application, that is a UiApplication and so can come to the foreground. So it is slightly easy and makes more sense to use the first approach. You need to use the second approach if your Listener was a Background Application that was started and always runs.
OK so now the question is what do you do on the DialogCloseListener, or the Button Click of however you decide to get the request back from the user. I normally do it using a DialogCloseListener and I check the selection on the Dialog <dialog.getSelectedValue()).
I don't believe that this process will be running in your UiApplication, so you need to Context switch to your Application. The obvious way is to use a GlobalEvent. But instead, I would actually just give your DialogCloseListener access to the UiApplication. You can extend Dialog to do this, so it retains a reference to your UiApplication, or you just use the setCookie function in Dialog to keep it. To context switch back to your Application, just
<your UiApplication object>.invokeLater(new Runnable() ... );
To get the reference you need, and put it in your Dialog's cookie, you could just do
So now we are at the final hurdle, how do you display something to the user if they want you to.
You need to do two things
b) push your NotificationScreen.
Now you realize that this means the notification screen will be pushed on top of whatever was last showing. So for example, say your user was displaying a notification from a previous one that arrived, then got a new popup saying something had arrived, and said yes show it, this would pus a new screen on top of the previous one. Once the user had finished looking at this, they would just close it, and the original notification screen would be visible. If you don't want to work like this, then we will need to think about some other logic.
OK, that is it for you first question.
I think we are missing an important word in your second post:
"I want to actually place the thread code and push listener object in my because "
In your what?
I will answer a general related question in the hope that it answers yours.
If you want a Singleton Object to be accessible easily from multiple places,you need to be able to reference it. There are a number of options including these two:
a) Use a public static. This is a Singleton where you only have one Application or one UiApplication. If you start using alternate entry points, then this will not work. But I think it will work in this case and is the approach I would recommend for you
b) Use RuntimeStore as described here:
OK, ask again if this was not your question. Ask also if the above is not clear and/or doesn't answer your question anyway...
07-19-2012 06:57 AM
Thanks for your reply!
I understand what you're saying about the Dialog, but if I don't want to bring my application to the foreground directly from the Dialog, can't I just use that DialogCloseListener to grab the reply then request the foreground and push the screen in the same method that created the dialog? I have a couple of reasons for wanting to do this, mainly: I really do only want one instance of that notification screen running at any time, with the notifications persisting until the user replaces or clears them. I think it'd be better to have that code inside my application so I can use static variables to check whether there's an instance of the screen running. I also don't want to update the notification screen unless the user says they want to display the new push notification.
As for my second question: I wanted to place my PushListener object inside the main() method or constructor of my UiApplication class, instead of inside the notification screen class. That way, I don't have to check whether I need to start it whenever I push the notification screen. But I'd need to access it in my exit() method to deregister. So, you did answer my vague question. I am a bit hesistant to make the listener object static, simply because I'm superstitious about the static modifier, and I'm not sure I trust a static object with listening/processing the pushes, launching the dialog or spawning threads. I'm going to try it anyways.
07-19-2012 07:32 AM
This sort of thing can get a bit complicated and there are different ways of implementing this too, and to be honest, I don't really have time to understand the depths of your app logic. I am hoping I can provide the framework, and you determine how to implement this yourself. The sort of questions you are asking I don't think a BlackBerry specific, they are logic.
The DialogClosedListener is just an Object that implements that interface, so this could be your Notification Screen, but that means you need an instance of it to be active all the time. Or it could be another Object, that checks to see if the Notification screen is active, if so, calls some sort of update method on it, if not, starts a new one. You can do all of this in the DialogClose method, but remember you will want to swap back into your Application context to do this sort of thing.
I'm not sure I understand why the positioning of your PushListener is important. I had presumed you would start it when your app started, stop it when your app exited. After that, I would have thought it would put the data it receives in some kind of queue, you need to be aware that the listener could receive multiple bits of data before the user has a chance to review. So you need access to the queue rather than the listener in the Notification Screen. And be aware, if your application starts a Thread, it will be killed when your application exits anyway, so perhaps you are worrying about nothing. But probably nicer to try to stop it.