If Activity A calls Activity B with .setExtra(someKey, someValue), and Activity B calls Activity C, from which the user returns to Activity B with the back button, can Activity B still access the Extras from Activity A?
A
A -> B (with Extra)
A -> B -> C
back button pressed
A -> B (with Extra?)
Is the Bundle persisted or discarded in this scenario?
I could not find this in When do intent extras become null between activities? and Android Intent Extras Sticking Around
In ActivityB when calling getIntent() you will always have access to the "extras" that were sent in the Intent that started ActivityB. Android persists the Intent (including "extras") so that even if Android kills the process (because the user put it in the background), when the user returns to the app, Android creates a new process and recreates the Activity with the original Intent.
No, they do not always persist. Most of the time, it works, but sometimes, the extra was just null, which created a NullPointerException upon accessing it. So there is no guarantee that the system keeps the Extra. Better save it somewhere.
Related
Main Activity has started activity A and A has started activity B, which is currently visible on the screen: Main Activity -> A -> B.
Now Main Activity receives a broadcast intent and it needs to pass new information from it via A to B without restarting A or B, i.e., the state of A and B should remain as is. For example, if user has written someting to EditText in B, that text should not be lost.
Question: what Intent flags should be used when MainActivity sends intent containing the new information to A and A to B in order to achieve the above described behavior?
Use the activity.startActivity(Intent) method in your Activity B to call activity A ‘s “newIntent(Intent)” method, do with what you need to then :) and maybe make sure in the manifest file the activity is set to SingleInstance
Rather than figthing with intents and launch modes, I decided to save the necessary state of A and B at their onPause() method to a companion object of MainActivity and then restore the state from there at onResume() method of A and B.
So i have AppCompatActivity A, B and C. From A, i start activity B, passing an Intent I0. In B´s onCreate i get I0 and initialize the UI based on that data. Now i open C (from B). When i press the app:navigationIcon back button of the android.support.v7.widget.Toolbar from C, B's onCreate is called again, but now the Intent I0 does not contain the data from getStringExtra("data") anymore.
I have tried to use onSaveInstanceState and onRestoreInstanceState as mentioned elsewhere, but onRestoreInstanceState is not called, and the savedInstanceState Bundle is null in onCreate.
So i'm wondering if there is a way to preserve either the UI state of Activity B (not destroy it?) or the Intent I0's extra data?
I've created an Example on Github
Thanks to #pskink for suggesting to set android:launchMode="singleTop" on Activity B. This solved the problem for me in that B is not recreated with an invalid Intent.
Im wondering how long does getIntent() in a Activity will be available (does not return null). So lets say I start Activity B from my Activity A and pass some extra data in the Intent.
In Activity B I will read the extra data from the intent in the activities onCreate() method.
So far so good. But how long is getIntent() available? I mean, if the user is displaying Activity B, but switchs to another App (i.e. by using the multitasking button) and after some hours the user clicks on the multitasking button again (the activity may have been destroyed in the meantime) and opens Activity B again. So Activity B onCreate() will be called to reinstantiate the Activity B. Does getIntent() now still returns the original Intent with the extra value or do I have to save the Intent extra value in Activities onSaveInstanceState() and use the Bundle in onCreate(Bundle state)?
Does getIntent() now still returns the original Intent with the extra value
Technically, it returns a copy of the Intent. Generally speaking, it should be identical to the original Intent, including all extras.
From Android doc, getIntent() return
Return the intent that started this activity.
But their are so many case where getIntent is null or extras are null. Check this link and this. Specially on device rotation or from pressing back keys.
But as its seems documentations says otherwise. Just to be in safe side, i will recommend you to do following
if (getIntent() != null && getIntent().getExtras() != null){
}
And, your activity code should prepared to handle the scenario where getIntent is null.
I have an activity A which starts a new activity B with startActivityForResult.
Activity B is restarted several times with FLAG_ACTIVITY_CLEAR_TOP, so when the user clicks on back, B puts on data with setResult() and comes back to Activity A. However, the data is missing. onActivityResult in A is invoked with intent to null and resultCode by default.
I know that, in fact, is the right behaviour since FLAG_ACTIVITY_CLEAR_TOP discards previous activities, but I wonder if there is some workaround to achieve this (apart from obvious options like avoiding restarting B)
Add both FLAG_ACTIVITY_CLEAR_TOP and FLAG_ACTIVITY_SINGLE_TOP to your launch intents when you restart Activity B.
activityBIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
Also relaunching Activity B will call onNewIntent(Intent), however getIntent() will still deliver the older (original) intent.
Note that getIntent() still returns the original Intent. You can
use setIntent(Intent) to update it to this new Intent.
I have an Android application that contains two Activities.
Activity A has a button that launches Activity B using Context.startActivity(Intent intent).
There is also a Notification that opens Activity in the same way.
If I start B from this notification and press back button - it just closes B and does not shows A like I go there with normal case.
Is it possible to force B to bo back to A if started from notification without history stack ?
Solution
As stefan and Paul Lammertsma mentioned, the best way is to start A from notification and in A create new intent with B - but not in onCreate() !
I dig this a bit and found that if I set in AndroidManifest a new property for A activity:
android:launchMode="singleTask"
there will be in A activity called
onNewIntent(Intent intent)
And there we should checl if Intent containst extra value passed from notification - and if so, then we call new B intent.
Thank you both and good luck with it for next devs ;-)
I would suggest having the notification call Activity A (instead of B directly) with some flag in its extras bundle. In A's onCreate(), check for the flag, and immediately launch Activity B. This will ensure that pressing back on B will return to A.
An easy way to achieve this would be to actually start Activity A from your Notification with a flag to call Activity B instantly.
So you just have to put an extra to your intent you are starting in your Notification and you have to check in Activity A if this extra exists and if it exists then you start Activity B.
Update: another way, but in my opinion not so good, would be to override the onPause() method of your Activity B and call Activity A there.
Maybe not the prettiest solution, but nevertheless a quick one;
add a boolean extra to the intent launching B, "launchedFromNotification" or something like that.
In activity Bs onCreate() you store that boolean value for later use.
In activity Bs onBackPressed() you can check the value of your boolean and if true, launch activity A before calling finish();
A prettier solution may be to launch activity A from the notification, with an extra telling it to directly launch activity B.