I have an activity A with a "child activity" which is the activity B.
When I create an activity, like in this case in android, I choose for activity B, that his parent shall be activity A.
So, when I start my application, I have an icon in the appbar in the activity B, where I can go to the activity A.
In my case, the user for example edit-text and manipulate some variables in the activity A and call activity B with Intent.
NOW, in activity B, when I click on the "back" icon, I will go back to the parent activity in this case activity A and all manipulated data are "away", because the screen will be relaunched.
But when I dont click on the icon in the activity B but instead click "back" on my mobile phone, I will come back to activity A and all manipulated data will be still there.
SO my question is, is there a way, to come back to activity A by clicking the back icon in activity B, without that the screen will be relaunched. Because this icon was automatically added, when I say, which activity have to be the parent class. I would like, that I can go back with this icon, but not relaunch the screen, instead continue, where I was "last" time.
I show you a part of my manifest file for the activity B:
<activity
android:name=".strassenfuehrer_screen.VideoPlayerHandlungsleitfadenStrassenfuehrerActivity"
android:label="Straßenführer > Handlungsleitfaden > VideoPlayer"
android:parentActivityName=".strassenfuehrer_screen.MitHandlungsleitfadenStrassenfuehrerScreenActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="de.derdoenerdon.ressourcencockpit.strassenfuehrer_screen.MitHandlungsleitfadenStrassenfuehrerScreenActivity" />
</activity>
Here you can see the "back icon" in the activity B.
For help, I would be very thankfull, I am new in android and have difficulties with it.
Thanks a lot
In your manifest for Activity A add this attribute:
android:launchMode="singleTask"
This should solve your problem.
This makes sure that there is only one instance of Activity A in the BackStack. Therefore Activity A is only created once per Task.
Hope this helps.
for more information https://developer.android.com/guide/components/activities/tasks-and-back-stack
You can override onSaveInstanceState() into your Activity and save your data before leaving that Activity.
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putInt("KEY1", Value1);
savedInstanceState.putInt("KEY2", Value2);
// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(savedInstanceState);
}
On coming back to that Activity you can get the saved data as bundle into you onCreate() method.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // Always call the superclass first
if (savedInstanceState != null) {
// Restore value of members from saved state
int val1 = savedInstanceState.getInt("Key1");
int val2 = savedInstanceState.getInt("Key2");
} else {
// This is the case when you are openning this Activity for the for the first time
}
}
Related
So in Activity A I pass some data to activity B through an intent. Ok, everything is fine and getStringExtra returns what I expect. Then from activity B, I pass the same data to activity C. Then, when I hit the back button in the toolbar (because of getSupportActionBar().setDisplayHomeAsUpEnabled(true)), the getStringExtra in activity B is now null.
So the flow is A (passes a string)-> B(passes the same string) -> C (back button in toolbar) -> B and now the variable passes from A to B is null. How can I fix that?
Mark this a rule : Whenever you are using the toolbar back button, you should take care of specifying the launchMode of the parent activity.
In your case, what happens after you press back button in Activity C, depends on what launchMode have you specified for your activity B.
If you have't specified any launch mode, the default launch mode is standard. In this case, the parent activity (B) is popped off the stack, and a new instance of that activity is created on top of the stack to receive the intent.
If you have specified launch mode as singleTop, the parent activity is brought to the top of the stack, and receives the intent through its onNewIntent() method. That is, the previous activity is preserved.
Refer http://developer.android.com/training/implementing-navigation/ancestral.html#NavigateUp.
In your case, you want to preserve the variable, therefore you should use singleTop launchMode.
If you are extracting the data in onCreate method of Activity B then when you hit the back button in Activity C, the onCreate method of Activity B is not called again. To get more clarity on the life cycle of an Activity I really suggest you go through this developer.android.com/reference/android/app/Activity.html
Coming to your question when you start Activity B from Activity A, store the string that you sent from A to B in a global variable rather than a local one, and perform check like
public Class B extends Activity {
private String stringData;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.xml_layout);
if(getIntent().hasExtra(yourKeyName)) {
stringData = getIntent().getStringExtra(yourKeyName);
}
//Do other stuff
}
}
In your activity B, always check before getting the String -
if(getIntent().hasExtra(KEY_NAME))
String s = getIntent().getStringExtra(KEY_NAME);
Reason being that when you press the back button then Activity B is not launched with the same intent that you create in Activity A. Hence the extras are not present.
You should be string the string extra as a global variable and always use a hasExtra check.
I think it is different processes.
The first one, when you start activity B from activity A, you pass
the data from activity A to activity B. It is obvious, so the data
will be present.
The second one, then you start activity C from activity B, because of
activity B is not on the foreground, then your data will be erased.
You can persist your data on activity B by many ways.
One of them you can implement a static global variable.
Second way, you can save your variables on activity B by saving the
data onSaveInstanceState and retrieve from onRestoreInstanceState or
onCreate
Third way you can listen onActivityResult on activity B from activity
C. When you starting activity C, you must use startActivityOnResult
and passing the data that you want to pass back on activity B. After
you finish your activity C, you must return the data that originally
from activity B.
And so on...
But the better way to achieve that is the second way, use bundle onSaveInstanceState and retrieve the bundle data when onCreate.
I have 2 activities which one activity leads to the other activity.
The first activity present a listview and the items click leads to the second activity.
When I click the back button I get back to the first activity but the list reload and scroll up to the first item. I want the list to stay at its place after I get back to it.
If you call finish() in activity A when openig the new Activity B on back press you will call onCreate() of activity A to avoid this avoid calling finish() in activity A in your onItemClickListner()of activity A and record tge position of tge click in Activity A, in which case calling the back press in Activity B will cll for tge onResume() in activity A where in you could call For a direct scroll:
getListView().setSelection(<position>);
Or For a smooth scroll:
getListView().smoothScrollToPosition(<position>);
when you press back you call oncreate() on that activity so everything reload
you could use :
getListView().smoothScrollToPosition(yourpostion);
and think about using fragments for another way around it .
and recyclerview is advised .
If you don't call finish() on Activity A, even if you go to Activity B and come back, Activity A should not call the whole onCreate() again.
If you take a look at the life cycle of Activities, it will put Activity A in onPause() and probably onStop() depending on what you are doing on Activity B and how you defined launchMode in AndroidManifest.xml.
So when you are calling startActivity(..), don't call finish(). Otherwise it will load everything again to draw the Activity A.
Another possible way is using
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
..
}
OR you can use SharedPreference.
Once fetching data from Parse.com is over (like onPostExecute() of AsyncTask), you can read the data passed from Activity B to relocate the user to the list where they were.
EDIT:
Read this article about how to "come back" to the activity you were in, too.
All,
I am performing a navigation between 3 screens with dependency on each other.
Activity A is having a table with list of table rows. Each row has onclick listener event where in get the data from table row and passes to next screen Activity B.
Activity B starts with reading data from Intent and gets corresponding images & data etc and builds layout. It has a button where in reads data from edit text and passed to Activity C.
Activity C also builds layout based on data from Intent.
I acheived navigation among these activities with Parent activity configuration in Manifest file.
Now when I am doing back navigation in Activity C to Activity B, it's crashing because it could not find data from Intent as the control is coming from Child to Parent rather than Parent to Child.
I understand onCreate function of Activity B is executing again. So I kept onPause() and onResume() method in Activity B to hold the re-execution. But no luck.
Could some one advise how to handle this kind of scenario.
EDIT:
Activity B:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.edit_activity);
getActionBar().setDisplayHomeAsUpEnabled(true);
source_activity = this.getIntent().getStringExtra("source_activity");
Bundle b = this.getIntent().getExtras();
if(b!=null)
DashBoardDisplay_l = b.getParcelable("obj");
Name_ref=DashBoardDisplay_l.getName();
}
Activity C:
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
overridePendingTransition(R.anim.activity_open_translate,R.anim.activity_close_scale);
setContentView(R.layout.point_log_activity);
Intent intent = getIntent();
String YourtransferredData = intent.getExtras().getString("ref_name");
Log.d(TAG, "ref name "+YourtransferredData);
Name=YourtransferredData;
Log.d(TAG, "name value "+Name);
getActionBar().setDisplayHomeAsUpEnabled(true);
new BackEndJob().execute();
}
Activity B contains some Intent which comes from prior screen Activity A. So while coming back to Activity B from Activity C, it could not find the data from Intent due to which it is resulting to null pointer exception.
So is there any option to display what is there in back navigation stack rather than recreating it with Savedinstance advised by Dalija.
From your description it looks like back navigation to Activity B should be prevented. So when user presses back button in Activity C it would go back to Activity A. If that is the case then you should finish Activity B when it passes the control to Activity C.
...
this.startActivity(intent); // start Activity C
finish();
}
Finishing activity will remove Activity B from navigation stack and completely destroy Activity B solving your back navigation issue.
However, if you do want to navigate back to Activity B then you should use onSaveInstanceState() and onRestoreInstanceState() in Activity B to save its state.
Recreating Activity
When you launch Activity C, Activity B is stopped. At that point system may decide to destroy Activity B at any time if it needs to clean up resources. You don't have any influence on that process and you cannot prevent it.
You can find more in Activity Lifecycle
I have a master activity that is a menu (A). The activity A have 6 fragments. One of them is a gallery of pictures (Figure 1). When you touch a picture you go to the picture details activity (B) (Figure 2). I add the tag "parentName" to the activity B in the AndroidManifest.xml. So the parent of the activity B is the activity A. The problem is: when you are in activity B and you press the Up Button (Figure 2) the activity A is recreated and it shows the first fragment of the activity A (not the gallery fragment). I want the same behavior of the Instragram app when you back to a previous activity. It seems like the Instagram app don't recreate the previous activity. The expected behavior is also similar to the behavior of the back button (Figure 3). How can I achieve this behavior? Thanks
Figure 1. Picture details Activity
Figure 2. Picture details Activity
Figure 3. Back button
I've solved my problem easily. I just had to add the tag android:launchMode="singleTop" to the activity A. I also add the next code in the activity A but probably isn't necessary. I hope you find it useful.
#Override
protected void onSaveInstanceState(Bundle outState)
{
super.onSaveInstanceState(outState);
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState)
{
super.onRestoreInstanceState(savedInstanceState);
}
May be programatically you are using this :
getFragmentManager().beginTransaction().replace(R.id.content_frame, new FragmentB(),null).addToBackStack(null).commit();
Replace it with this line :
getFragmentManager().beginTransaction().add(R.id.content_frame, fragment,null).addToBackStack(null).commit();
I am trying to control my stop/restart behavior according to the Android Guidelines but it's getting a bit tricky. I want my app to restore state after being minimized and tapping the launcher icon.
The current behaviour makes so I can HOME out of the app, and when the user comes back using the long press list everything behaves as expected. Now, trying to return tapping the app icon starts the default activity, it doesn't take onRestoreInstanceState into account, and while keeping the old task affinities open on their back stack.
The activities have onCreate, onResume, onSavedInstanceState overridden, calling their super, and are of type SingleInstance.
During one of my app development, I had the similar issue where app have single activity and need to save some state values (usually string, Boolean) onpause. I will give you idea how i handle it, and I hope it will useful to you also.
protected void onPause() {
super.onPause();
saveState();
}
protected void onResume() {
super.onResume();
retrieveState();
}
donot forget focus change ...
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if(hasFocus) {
retrieveState();
}
else { saveState(); }
}
Now the save and retrieve data
public void saveState()
{
SharedPreferences settings = getSharedPreferences(WEBSTATE, 0);
SharedPreferences.Editor editor = settings.edit();
editor.putString(CURRENT_URL_STATE, "some url");
editor.putInt(FILECOUNT, 10);
/* any other content... */
editor.commit();
}
public void retrieveState()
{
SharedPreferences settings = getSharedPreferences(WEBSTATE, 0);
String current_url = settings.getString(CURRENT_URL_STATE, "");
int count = settings.getInt((FILECOUNT, 0);
/*use these value as per requier.. */
}
The current behaviour makes so I can HOME out of the app, and when the
user comes back using the long press list everything behaves as
expected. Now, trying to return tapping the app icon starts the
default activity, it doesn't take onRestoreInstanceState into account,
and while keeping the old task affinities open on their back stack.
Let's say you got 2 activities: A and B. Activity A is your entry point, so when you tap on app icon (which in fact is incorrect statement as this is activity icon, NOT the app icon) you launch activity A. Now you got to activity B and press HOME. When you now open list of recents, you will see activity B, and will be able to get back to it. But when you tap your "app icon" on launcher screen, you will enter activity A. And this is normal and correct behavior. Also note savedInstanceState is not overall state of your application as you most likely think.
Also note, that your Activity class can be instantiated multiple times, which depending on your application architecture can, also lead to incorrect navigation behaviour. You can try to control this by using android:launchMode in your Manifest file (you will find android documentation here).
Finally, if possible, consider reworking your application to use Fragments instead of multiple activities - that would simplify controling application flow.
Not sure if this is what you want to do, But i had a similar problem where i wanted a single base activity to return to, And i couldn't get the desired result from SingleInstance, I defined a new Activity which was the main launched :
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
And from that activity i launched my desired Activity with the desired FLAG clear-top, and finished the main launched activity.