I want to launch a dialog from a service that hovers over whatever the user is currently looking at. The dialog gets launched like this: service gets trigger to open dialog > start transparent activity > transparent activity shows dialog.
My problem is when the user opens the app, launches into the main menu, and then presses HOME to leave. By pressing HOME, it leaves the main menu activity on pause, not destroyed, and when the service starts the dialog, the main menu gets shown underneath the transparent activity; causing the dialog to loose the affect of hovering over whatever the user is looking at.
How can make it so that the transparent activity gets opened independently of any other activities in the app? The only way to prevent this currently is to finish all the activities when they are paused; but this is impractical.
This is the last thing we want. :-)
1. Dialog boxes from Services
One of the best experiences in mobile devices, IMHO, and Android in particular, is that after decades, we got rid of system-wide, pesky alert dialogs. Finally, best practices [1, 2] for user interaction gave us a way to avoid the infamous disseminate use of MessageBox(hwnd, lpText, lpCaption, uType), competing for focus and for the attention of the poor user. See video parody above.
The reason it feels awkward to start a dialog from a Service is exactly because it is supposed to be a background task, without user interaction. By concept, you shouldn't be doing this. That's the reason why we see these tricks (transparent activities, what a silly thing) to cheat the design guidelines in the first place. They are bad, they disrupt the user experience, they steal focus and attention. They disrupt our work.
2. Use notifications instead
Whenever you want to notify a user of something from the background, when the user is somewhere else, you use a notification. It's the default pattern, and it doesn't bother the user.
Therefore, you should be sending notifications from your Service.
From there, if the user is interested, then he will touch the notification and you start your own activity, possibly resuming your activity, creating a new one, and then using a dialog requesting action to be performed, or whatever you want to do.
3. Finally, do NOT use FLAG_ACTIVITY_MULTIPLE_TASK
You should not, ever, use this flag unless you have carefully read and fully understood the documentation, and the implications of using that flag.
Do not use this flag unless you are implementing your own top-level application launcher.
(...)
Because the default system does not include graphical task management, you should not use this flag unless you provide some way for a user to return back to the tasks you have launched.
Really. In this case, just don't.
You may consider using alertDialog with TYPE_SYSTEM_ALERT instead of activity:
AlertDialog alertDialog = new AlertDialog.Builder(this)
.setTitle("Title")
.setMessage("Are you sure?")
.create();
alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
alertDialog.show();
Please note that you have to use the following permission:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
Found this out myself, just add the Intent.FLAG_ACTIVITY_MULTIPLE_TASK flag to the launch Intent; of course in conjunction with the Intent.FLAG_ACTIVITY_NEW_TASK flag.
Related
I am designing an app that is used for emergency alerts. The alerts come from a server and a connection to that server is maintained in service.
If the service receives an emergency request from the server it checks to see if a specific activity is open. If it is it lets it know an emergency has been triggered and the activity launches a dialog activity with some options. It then handles results from this new dialog activity.
However, if the service notes that the activity is NOT open I want it to launch the dialog anyway. I know that this isn't good practise but because of the importance of this emergency I don't want to rely on Notifications (which are already in use if the activity is closed to let the user know that the app is still listening for emergencies).
What currently happens is that the below code is executed in the service and the dialog launches. However, the 'main' activity (the only other activity in the app) also opens behind the dialog. What I really want to happen is that either...
1) The service launches the main activity which then opens the dialog so that I can easily capture the results.
2) The service launches only the dialog activity and I use a broadcast receiver to capture results from this activity.
1 would use the mechanics that already exist for capturing results from an activity. However I don't like the idea of chaining the activities together in this way.
2 means I can ignore the main activity all together (because I don't really need it in this instance) but seems more of a get around.
What I am really asking is two things. What is best practise given my circumstances and how do i achieve number 2? Here is the launch code in my service. Notification in this code is referring to the dialog activity that will open.
if (MainActivity.isActivityInUI) {
//Dealt with by activity
sendMessageAlert(message);
} else {
//Launch dialog directly from service
Intent notification = new Intent(this,
EmergencyNotificationActivity.class);
Bundle args = new Bundle();
args.putString(MobileMessage.EXTRA_LOCATION_NAME,
message.locationName);
args.putString(MobileMessage.EXTRA_ID,
String.valueOf(message.id));
args.putDouble(MobileMessage.EXTRA_LATITUDE,
Double.valueOf(message.latitude));
args.putDouble(MobileMessage.EXTRA_LONGITUDE,
Double.valueOf(message.longitude));
//and the flag to let the notification know this is from a service...
args.putBoolean(EXTRA_FROM_SERVICE, true);
notification.putExtras(args);
//add flag because this is being called from outside of an activity
notification.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |ActivityInfo.LAUNCH_SINGLE_INSTANCE);
startActivity(notification);
I think instead of trying to show a dialog without visibly showing an Activity, you should consider launching an Activity that is themed like a Dialog. Just apply the following theme: http://developer.android.com/reference/android/R.style.html#Theme_Dialog (or similar themes) to your EmergencyNotificationActivity. You probably would have to tweak your class to behave like a dialog instead of launching one (which I am assuming is what you're doing currently).
This method would also allow you to not have to check if an Activity already exists.
I have a multi-activity application. Say I set up a listener for some type of event in activity A, but then switch to a different activity B (within the same app) before the event has triggered the listener. What is the status of that listener? Does it always get destroyed? Or does it depend on the type of event? Or does it depend on whether the listener was set up within the main UI thread of activity A? Or some other conditions?
EDIT: The reason I ask is that I wish to interrogate the purchase states of a variety of in-app purchase items right at the start of my app's splash screen. This involves instigating some code and setting up a listener for "ok_here_is_the_answer()".. the problem is I'm worried that it may take longer to get the answer than the duration of the splash-screen activity. In that case do I have to start all over again in my application's second activity?
If your listener is created within Activity A and is tight to its context, then it would be destroyed when the activity pause i.e. go to the background.
If you want to do operation that should survive across activities, you can define it within the application context or in a dedicated service.
This might not be the answer to your question but you shouldn't use a splash activity (or even a splash) for many good reasons. I'd recommend you to use a full screen dialog instead which also would solve your problem.
But about your question it depend on what kind of listener we are talking about? Anything involving the context is over and done. Handlers, threads etc. is still running though (afaik).
I am trying to detect if my app became active from multi-tasking and display a dialog.
The use-case is something like this: User is using the app -> Hits the home button -> Does something -> User taps on the app again
As expected, the last activity the user was on is being shown.
I want to display a dialog when this happens. I used onRestart() for the same and it works. Only problem is, even when the user goes to some activity in the app and then hits back, the dialog is being displayed.
I went through the activity lifecycle several times, but couldn't figure out the solution. Any ideas?
Well, you can tell the foreground application using the technique outlined in Determining the current foreground application from a background task or service: look for getForegroundApp. You could run a timer that checks periodically to see if the app is foreground, and if its not then set a variable after a suitable delay (to make sure you don't happen to hit it in the wrong order when switching Activities). Clear the variable in onStart, and if onCreate of the rooth Activity is ever called you know that the app just became Active.
I achieved this by setting a flag in Shared Preferences in onStop() and cleared it in onDestroy().
Then I overrided the Back button to clear the flag whenever it is pressed. This solves the problem I had stated.
Now in onRestart(), if the flag is true.... I display the dialog.
I know it is not the most elegant solution but does the job! Hope this helps somebody.
Trying to understand best practice for the lifecycle of my android application, and how activities fit into it.
For example, I have a main activity, sort of the "home" of my application. But, on start-up there are several activities that I 'might' need to run, depending on several cases, one being that it is the first time the app's been run.
Is best practice to call these 'start-up'/house-keeping activities FROM my 'home' activity? Or should the application begin with a 'house-keeping' activities, do the work, then finish() and start the 'home' activity?
Thanks for advice about this,
-- J
For the best user experience (and cleaner code), you really shouldn't chain Activities.
A good best practice for the scenario you describe (needing a particular layout of options on first-launch) is to set a SharedPreference the first time that the "Home" Activity is created. In the same Activity.onCreate() call you should make a decision about what your UI will display based on that saved value (e.g., either set the appropriate View's visibility to View.GONE or choose a different layout.xml altogether).
As an added bonus: You can overload a hypothetical "has been opened" SharedPreference with the version number of the app (e.g., LastOpenedVersion) to be able to present the user with a change log the next time they open your "Home" activity after an upgrade.
I would set your LAUNCHER <intent-filter> on whatever the user will most likely want to go to from their home screen. Presumably, that would be your "home" activity.
In onCreate() of that activity, make the determination if there is some other activity that is needed (e.g., "first-run"), and call startActivity() on it. When the user presses BACK from there (or you finish() that new activity), control will return to your "home" activity.
One possibility is to start from a splash screen Activity (rather than a "home" one), which then determines what to launch next.
You should also consider if your start-up/house-keeping needs to be accomplished via an Activity. If it is not something that the user interacts with, then you can move that functionality into a Service that runs a separate thread.
When is it preferable to use a Dialog box as opposed to an Activity in Android? From my understanding, anything you can do with a Dialog box you can also accomplish with an Activity. Are there any tasks that can only be accomplished by an Activity or a Dialog?
Is what you're doing worth a new Activity? Do you need to be able to start it through an intent? Do you really need to create a new Java class for it?
If it's a straightforward dialog that displays a text and has simple hooks for positive/negative/dismissal functions, definitely use a dialog.
If you have something complex, you may want to go for a full-blown activity.
Well why exactly would you want to start a new activity just to ask the user "Are you sure? Y/N"? Dialogs generally run on top of the activity, and are usually smaller activities or notifications for the user. They also usually have something to do with the process of the app running. It helps make things simpler to open a dialog to prompt the user on top of your activity, than to start a new activity atop your current activity.
I went for Activities when I needed an user interaction that needs backstack, navigation, lifecycle and callable features.. else with dialogs. Being from the WebApp world I ask whether I would have needed a new server page or a pop window for an interaction and the decision in Andoird world becomes easier!
If newServer page then mostly Activity
elseIf popUpWindow then dialog
I created my android application in one fragment with nested alert dialog, so far my application still running well in handle those nested dialog, and I think dialog is less consuming memory than an activity