Starting an Android activity and popping all other activities except Home/Main - android

My Android app is for a hiking club and starts with a Home screen, which is the main activity.
The home screen shows the house-style and has some buttons to the core functionalities: list of upcoming hikes, history of hikes, last reactions and also a message board.
THe activity flow is pretty straightforward, you can i.e. navigate from:
Home -> Hike list -> Hike Details
And back using the Back button. Going back from the Home activity will ask for closing the app.
I already use the FLAG_ACTIVITY_CLEAR_TOP flag to prevent several instance of the same activity.
But my problem is I have also implemented a Menu to navigate to the core functionalities directly.
So for example, when in the Hike Detail screen, one can choose to go to the Message board. But I do not want to keep the Hike List -> Hike Detail activities on the stack.
So when pressing Back from the message board, I always want to return to the Home activity.
IS there a clean possibility to pop the stack and only keep the Home activity before launching a new activity? I guess that would solve my issue.

I found something similar on SO that might work.
Check out: FLAG_ACTIVITY_TASK_ON_HOME
Pre API 11:
Start all of your activities from home using startActivityForResult(). When you navigate to a parallel stack via the global menu. Call this on your current activity:
// startParallelActivity();
setResult(KILL_YOURSELF);
finish;
Where every activity on top of home implements onActivityResult() like so:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == KILL_YOURSELF) {
setResult(KILL_YOURSELF);
finish();
}
}
This will destroy all the activities in the current stack, leaving just the home activity that will be there when the user hits "back"

Related

Launching an Activity within a certain fragment, then going back to the previous Activity from where it was launched?

I've been struggling with a particular challenge which is as follows:
My app has an activity "A" which is considered the app's "main" activity. At a certain point, it launches an activity "B" which has an action available that should launch a fragment inside activity "A" (this won't always be the same fragment, it will depend on some data coming from our backend).
I can do this just fine by simply calling startActivity with the correct Intent, however, on pressing the back button, it goes back to A's "main fragment" (this is logic implemented inside of A's onBackButtonPressed()). Essentially, what should happen is as follows:
Activity A -> Activity B -> Activity A showing Fragment X -> press back -> Activity B
What happens when using startActivity to launch Activity A:
Activity A -> Activity B -> Activity A showing Fragment X -> press back -> Activity A showing the "main fragment". From here, if I press back again the app exits, which again is part of the implementation of A's onBackButtonPressed, however I've tried retrieving an extra from the intent which invoked A in order to conditionally bring back activity B but the Intent seemed to be empty of extras for reasons I can't figure out. I am sure I am correctly putting the extras in the Intent since activity A launches the correct fragment when invoked from B based on what I put there.
More things I've tried:
Launching the desired fragment directly from within B, however this way the fragment is not shown with the navigation bar that exists in A and seems to show the main contents of activity B behind the fragment's elements, which in user experience terms is undesirable.
Using the Intent.FLAG_ACTIVITY_REORDER_TO_FRONT flag, which seemed to make no difference whatsoever.
As this is part of my company's app which already has a decent degree of complexity, I'm not at liberty to provide you with useful code samples, and hopefully my description is sufficient for someone to aid me.
Additional information
targetApi="n"
Testing on Android 11
Activity A has launchMode "singleTask"
Activity B has launchMode "singleTop"
For the intended behavior:
Avoid using any launchMode, taskAffinity or activity flags, the default behavior is absolutely good for your requirements ("standard" is the default launch mode). So when you do the action in Activity B, a new instance of Activity A will be launched after putting B in backstack, which is the default behavior.
You should have a logic in Activity A's onBackPressed() such that: if the fragment X is visible, then it will exit the whole activity, otherwise it passes by calling super(). Something like the following:
In Activity A
#Override
public void onBackPressed() {
Fragment fragment = getFragmentManager().findFragmentByTag("yourTagForFragmentX");
if (fragment instanceof XFragment) {
// The fragment is available in the fragment manager
finish()
} else {
super.onBackPressed();
}
}
For more details, here
I think you're overcomplicating things.
Remove all of the launch mode flags for A and B - they should not be necessary.
Remove custom handling of onBackPressed - default handling should suffice.
Update A to initialize itself to the correct fragment based on the intent it's given:
For example:
onCreate(...) {
if (getIntent().getAction() == "START_ON_X") {
// Notice we REPLACE and DO NOT add to back stack
getFragmentManager().replace(fragID, createXFragment()).commit()
}
else {
getFragmentManager().replace(fragID, createDefaultFragment()).commit()
}
}
Thus, you will have:
Default launcher intent launches A.
A launches B.
B launches A with specific intent to show Fragment X
This will give you a stack of A -> B -> Ax
Then when you press back, DEFAULT BEHAVIOR will leave you on B.
Then pressing back again will leave you on A.
Then pressing back again will close your app.
Again this is all standard, default behavior. KISS.

'FLAG_ACTIVITY_REORDER_TO_FRONT' in new flavors of Android OS(4.4 & later)

Recently, I faced a problem to re-initiate Activity that's already in back-stack. The flag FLAG_ACTIVITY_REORDER_TO_FRONT is the best solution for manage this problem. But in Android 4.4 & later it isn't work well(some times Activity view is getting freezes or Application minimizes itself, menu isn't inflated to re-initiated Activity or Keyboard isn't allow to enter something to text area) but in previous versions this flag re-initiate's the Activity, and removed from back stack. Please review this link for more details.
In Android 4.4 & later, the application misbehaves when FLAG_ACTIVITY_REORDER_TO_FRONT flag is used in Activity creation. The major issues are, some times Activity is going to freeze state, when navigate to another activity key board isn't working well(key board is shown but user can't enter anything to text area), didn't inflate menu, or Application navigates to minimize state.
I think this issue is related to back-stack and flow of activity, when launcher activity(in my application, SplashScreenActivity is a launcher) finishes, then sub-activity causes some problem when using FLAG_ACTIVITY_REORDER_TO_FRONT to re-initiate previous Activity. So in this scenario, don't kill launcher or parent activity & start next activity using startActivityForResult(childAcivityIntent, requestcode), & kill parent activity at the time of onActivityResult call. And also remember don't use singleInstance or singleTop flags in child & parent activities.
private void onStartNextActivity() {
Intent mIntent= new Intent(SplashscreenActivity.this, ChildActivity.class);
mIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivityForResult(mIntent, 1111);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode==1111)
finish();
}
I was also facing the same issue:
When I am coming back to the parent Activity by setting the Intent flag FLAG_ACTIVITY_REORDER_TO_FRONT from child activity, some times Application is minimized in Nexus5 with Android Marshmallow.
I struggled for 3 days and at last I change the Launch mode of activity to Single Task.
Now My application is working fine.

android launchMode singleTask with startActivityForResult

We have a requirement to force the user to set up a password the first time he/she starts the app. So we have our main activity with launchMode=singleTask which start a password setting activity using startActivityForResult.
We also want the user to go back to their home if he/she taps back from the password setting page so we put the code to finish the main activity in its onActivityResult if it receives RESULT_CANCELLED. However, if the user taps home and re-enter our app, we want to show the password setting page again. But in this case, it will be destroyed (because main activity's launchMode is singleTask) and also returns RESULT_CANCELLED to our main activity causing it to be finished.
So the problem is from main activity, we cannot distinguish between tapping back and tapping home then re-enter the app.
Is there anyway to fulfill this requirement while still keeping the launchMode as singleTask ?
onBackPressed() for tapping back
Called when the activity has detected the user's press of the back
key. The default implementation simply finishes the current activity,
but you can override this to do whatever you want.
http://developer.android.com/reference/android/app/Activity.html#onBackPressed%28%29
&&
onPause() for home screen
(though it can be due to other things also like your next activity or switching to another application)
http://developer.android.com/reference/android/app/Activity.html#onPause%28%29
Update :
Why Don't you use Sharedpreferences and check if the app is run for the first time and password/rest fields are set rather than using the approach you are using right now .
I had a very similar issue recently.
What I would suggest is that you don't actually finish the app when you get the RESULT_CANCELLED.
Instead do something like:
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (resultCode == Activity.RESULT_CANCELED) {
if (/*TEST IF A USER IS SIGNED IN*/) {
//IF SIGNED IN PROCEED TO MAIN ACTIVITY
}
// OTHERWISE FORCE THEM TO SIGNIN/REGISTER/WHATEVER AGAIN
// WITH ANOTHER CALL TO startActivityForResult
...
This is a back of an envelope approach to your problem, but this pattern has worked for me.
For me, my Authentication/Registration is all done in an Abstarct Class that extends Activity. Each of my activities then extends this class. I Place the Auth/Reg method calls in the onResume() of this Abstarct Class.
When a startActivityForResult is launched in the onResume() method and fails I don't finish() the activity but just let the app proceed and let the class handle which Reg/Auth form to present. Which it will do by checking various flags to determine what action it is meant to be performing.
The added benefit of this approach is that each and every Activity that might extend this abstract class gets the added benefit of a security check each time it is used.

How to switch to an Activity that is running through an already running Activity

I know there are much discussions about this but i cannot get this to work properly.
Activity (A) = singleTop and can receive android.intent.action.SEND
Activity (B) = singleTask
When i from the Android Gallery select a picture and open it with (A)
The (A) is redirecting the intent to (B).
This is working ok and if i press HOME and select (A) from the luncher
the (B) is brought to front. That is what i want and user can continue with picture,
Now, if i press HOME and open the Android Gallery again the (A) is
onRestart(), OnStart() and onResume(). and i see (A).
This is the problem i like to switch to (B) because user need to finish what he was doing.
I cannot see a good way to do that and why does the Android Gallery resume (A)?
Maybe i do something wrong since opening the Android Gallery bring me (A)
Any help would be appreciated
This is possible reasoning based on limited info in the question, assuming A is redirecting the intent to B in its onCreate().
1) Open Gallery, select a picture, open with A, redirect it to B
Task1 has stack has Gallery, A, B (B on top of the stack)
2) Press home, select A from launcher
Launcher app creates a new task, new task2's stack has a new instance of activity A, its onCreate() is invoked and intent is redirected to B. B being a singleTask is moved from Task1 to Task2 and its onNewIntent() would be invoked.
3) Press home, and open gallery
Task1 is resumed and the top of the stack is now A. Its onRestart(), onStart() and onResume() is invoked.
This being the scenario, you can try redirecting the intent from A's onStart() or do not have B as singleTask.
UPDATE
I know this is an intricate scenario. I have made a working solution by simply killing (A)/finish() after the launch of (B). Now,
if i press HOME and open the Android Gallery again i see Android Gallery.
if i press HOME and open A i see B.
if i press back from B I see the gallery

Android App not closing when killing main activity

I have an App that has a Main (root) activity which is a splash screen and launches a menu activity through an intent. The problem is when I am in the menu and press the back button it goes back to my splash screen as it should, but when I press the back button again to exit the app it closes my splash screen activity and goes back to the menu activity. At this point I can press the back button a third time which then appears to fully close the app. I believe the solution may to to use some launch mode configuration. Any ideas?
Does the splash screen automatically start the Menu Actvity? If it does you may want to start the MenuActivity by using startActivityForResult(Intent, int). Then in the Menu activity override onBackPressed and pass back a code letting the Main Activity know to finish(); and handle it using onActivityResult(int requestCode, int resultCode, Intent data)
This link on the Android Docs should help.

Categories

Resources