I'm building an app that requires a user to have logged in and obtained a user id. This id is a member variable of my extended Application class.
I'd like the application to recognize when/if this variable gets wiped out and, if so, throw up my log in screen and destroy the Activity stack behind it.
Here's what I think I'm going to do:
Extend Activity and ListActivity (currently the only two types of Activities I am using). In the onResume() handler, check to see if the user id is set. If not, throw up the log in screen and destroy the rest of the Activity stack behind it. All of my Activities will derive from these new extended Activities.
My issue here is that I don't know how to destroy the Activity stack behind a particular Activity. Any ideas?
One idea is to have a broadcast receive listening for a particular message that tells Activities to kill themselves, but I'm hoping Android already has something in place for a situation like this.
Update:
Also, is there a way to clear the entire Activity stack? I'd like to override the onBackPressed() handler on an Activity and have the Activity stack blown out so the user gets taken back to the Android home screen.
Other choice will be using the noHistory parameter in the AndroidManifest.xml to accomplish this.
so your Activity should not be placed in the history stack
<activity android:name=".MyActivity"
android:noHistory="true" />
I agree with danh32, setting the FLAG_ACTIVITY_CLEAR_TOP on the intent to bring the Login Activity on top of the stack will destroy all activities behind the new activity (hence, the Login Activity). This will leave one activity on the stack.
Intent myIntent = new Intent(view.getContext(), DisplayMenu.class);
myIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(myIntent);
finish();
I use this option to allow users to get back to a main screen from a long path through a lot of activities.
Related
What flag must I set for an intent so if the activity is visible with same extra it does not bring up a new one.
My app is somehow like google play. There are different app that are show in AppActivity by sending the app id as an Extra. User can download app and when download is finished, a complete notification is shown which on press brings up the corresponding activity page.
Currently by pressing notification it start a new activity which is correct for when AppActivity is not visible or showing another app. But it also start a new AppActivity even if the AppActivity is visible for same app.
PendingIntent.getActivity(ServiceDownload.this, id,
new Intent(ServiceDownload.this, AppActivity.class)
.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)
.putExtra(Constants.EXTRA_ID, id), 0);
Use Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP while starting your activity and define it single top at your manifest file.
If activity is somewhere in the stack, it will be brought to top(onNewIntent method will be invoked) and all activities above it, will be destroyed. If it is not in the stack it will be created (onCreate method will be invoked)
Edit: You have to handle onNewIntent to get bundle and update your current activity with new values.
Note: Also remember, system may destroy your activity and your both onCreate and onNewIntent methods can be invoked. Design your activity considering this.
Edit2: If you want to have many app details and user can navigate back with pressing back button. And also one detail for one app. Then you should use fragments. Add fragments by tag of your application id/name (something unique) and while showing an app detail search if any detail page exists with findFragmentByTag method. If it exists remove it and add it to top of the stack.
I have an Android app with multiple activities. The main activity communicates over a network and can launch or dismiss various other activities depending on commands it receives over the network. When an Activity is dismissed I don't want to finish() it, just move it down the stack so it's no longer the top activity. What I really need is a FLAG_ACTIVITY_REORDER_TO_BOTTOM but there is no such thing.
There's an intent flag called FLAG_ACTIVITY_PREVIOUS_IS_TOP and the name implies something like that but I don't understand the description:
"If set and this intent is being used to launch a new activity from an
existing one, the current activity will not be counted as the top
activity for deciding whether the new intent should be delivered to
the top instead of starting a new one. The previous activity will be
used as the top, with the assumption being that the current activity
will finish itself immediately"
Could someone please decode that for me, and if it's not what I want IS there some way to tell an activity to submerge itself below the previous one?
This isn't possible. The activities are stacked and you cant put one back under the other. It sounds like you may want to create a class that extends Android’s android.app.Application.
I found this tutorial online and it looks good. Good luck.
Extending Android's android.app.Application tutorial
You cannot move an activity below a certain activity into the android back Stack. The only way to move a activity in back stack is to open another activity on top of it. You can move an activity on top by creating a single instance of activity using FLAG 'singleTop' in this way your activity will be moved to the top of another activity and only a single instance of activity will be there in stack.
More information about activity back stack and Flags is available here.
Go through this information and all your doubts will get cleared about back stack.
I have 3 activities in my app.
Home -> List -> Detail
When I am in Detail activity, I want to have a home button that will redirect me to Home activity and close the other activities. Then, I tried this code:
Intent intent = new Intent(this, HomeActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
since the FLAG_ACTIVITY_CLEAR_TOP is:
If set, and the activity being launched is already running in the
current task, then instead of launching a new instance of that
activity, all of the other activities on top of it will be closed and
this Intent will be delivered to the (now on top) old activity as a
new Intent.
I got what I want, but then it still goes to onCreate. Is there any way to launch the home and not going to its onCreate?
Your thinking and Android's are not yet fully compatible. ;)
When you "launch the home", that means it's going to be launched, and that means it's going to be created.
You can, however, use Activity.startActivityForResult() to start List and Detail. Your "home" button then will finish your Detail Activity. In the onActivityResult callback of List, you'll just pass through using Activity.finish(), and in onActivityResult of Home you'll just catch the event and know that you're now back.
You cannot control the Activity life cycle. It's up to Android to decide which activities to keep running and which to close. This means that when an Activity loses focus, it is not necessarily destroyed or closed, but might simply lost focus and keep running, but might also not. This is up to Android; you cannot control this behavior.
If you want to recover an Activity in a given state, you have to save all needed data and restore it in onCreate().
I am trying to close a whole stack of activities using the way described here:
How to kill an application with all its activities?
Namely, each activity starts the other one with startActivityForResult, and in onActivityResult calls finish() to close itself together with the activity it opened.
The problem is that the activities in the task still seem to repaint themselves at least once before they close, and this doesn't look good. After closing the topmost activity one sees all previously opened activities like in a very fast slideshow.
How can one avoid this graphical issue?
EDIT: I need that if the user presses HOME button and then presses the app's icon in launcher, he returns to the current state of the stack, not to the very first activity again. So, from what I understand, with such a requirement I can't finish() activities before starting next ones.
That's native behaviour, intended to aid in user Experience. When an Activity is started with startActivityForResult and then finishes, it will (on devices that allow fancy animations) automatically slide away. That helps people not get surprised by the screen suddenly changing.
You could try starting the Activities without startActivityForResult and handling the passing of data to and from Activities manually, then handle how/when Activities finish() and which Activity they pass back to. You might find you implement something where Activities actually pass forward to the appropriate Activity all the time, rather than back to an Activity on the stack.
Intent intent = new Intent();
intent.setClass(getApplicationContext(),
PhoneListCheckboxAES.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
If u give like this when u are starting the next activity then the graphical problems won't occur
Is there any way to tell Android, "If the user exits this Activity by hitting the 'home' key, immediately finish() every Activity on the stack that has ever been associated with this Application?" Or, alternatively, a way for an Activity whose onPause() method has been forcibly called by a user hitting 'home' to finish() not only itself, but the Activity that started it as well?
The problem I have is workflow. My application's users basically go back and forth between a main Activity and "detail" Activity windows. They see something in the main Activity, tap it, the child detail Activity gets spawned, they use it for a while, then hit back to return to the main Activity. I can't finish() the main Activity after starting the child Activity, because then the back button would quit working. The problem is that now, if the user exits by hitting the home key in a child Activity, it leaves behind a zombie parent Activity. If the user relaunches the application, uses it for a while, then explicitly triggers a shutdown by hitting menu->quit from the main Activity (where I kill the service, then call finish()), the Activity goes away, and the user gets dumped into the zombie Activity from the previous run (which promptly crashes if the user tries to do anything, because the background service it depends on has already been shut down, and all the BroadcastReceivers that would have otherwise been listening have been removed, so its cries for help go unheard).
I'm actually kind of puzzled, because I already have android:launchMode="singleTask" sitting in the manifest tag for my launch activity, and I thought launchMode="singleTask" was explicitly supposed to prevent things like this from happening by making sure that any lingering Activities from a previous run were safely dead before it relaunched.
The easiest way of doing this is:
Intent i =new Intent(CurrentClass.this,HomeClass.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
Perhaps you can mark all the Activities in the stack with clearTaskOnLaunch (see http://developer.android.com/guide/topics/manifest/activity-element.html#clear).You can mark all the Activities that would be in the task with the attribute.