Android up button isn't working - android

I have a simple application. It consists of Activity A and Activity B.
When I start at Activity A (from the launcher icon) and then navigate to Activity B, and then hit the up button. I arrive at Activity A. Perfect.
Yet when I start activity B from the command line (simulating another app or a notification starting this activity) and I hit the up button, I just get taken to the home screen.
Here is my setup:
Activity A
public class ActivityA extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(ActivityA.this, ActivityB.class);
startActivity(intent);
}
});
}
}
Activity B
public class ActivityB extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_b);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
}
My manifest. Note that the parent activity is defined and my app min api is 16 (so the parent activity declaration is valid for 16 and up).
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".ActivityA"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".ActivityB"
android:exported="true"
android:label="#string/title_activity_b"
android:parentActivityName=".ActivityA"
android:theme="#style/AppTheme.NoActionBar" />
</application>
To start ActivityB from cmd line I use: adb shell am start com.example.demo/com.example.demo.ActivityB
EDIT 1
According to docs here: https://developer.android.com/training/appbar/up-action.html
You do not need to catch the up action in the activity's
onOptionsItemSelected() method. Instead, that method should call its
superclass, as shown in Respond to Actions. The superclass method
responds to the Up selection by navigating to the parent activity, as
specified in the app manifest.
Edit 2:
Just for kicks, I tried the two code snippets here. One at a time to see if they would do the trick. But they don't. ActivityA doesn't open. ActivityB just closes.
https://developer.android.com/training/implementing-navigation/ancestral.html
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
// Respond to the action bar's Up/Home button
case android.R.id.home:
NavUtils.navigateUpFromSameTask(this);
return true;
}
return super.onOptionsItemSelected(item);
}
and
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
// Respond to the action bar's Up/Home button
case android.R.id.home:
Intent upIntent = NavUtils.getParentActivityIntent(this);
if (NavUtils.shouldUpRecreateTask(this, upIntent)) {
// This activity is NOT part of this app's task, so create a new task
// when navigating up, with a synthesized back stack.
TaskStackBuilder.create(this)
// Add all of this activity's parents to the back stack
.addNextIntentWithParentStack(upIntent)
// Navigate up to the closest parent
.startActivities();
} else {
// This activity is part of this app's task, so simply
// navigate up to the logical parent activity.
NavUtils.navigateUpTo(this, upIntent);
}
return true;
}
return super.onOptionsItemSelected(item);
}
What's happening vs expected?
When I open ActivityB via the cmd line and hit up, I expect to go to ActivityA while ActivityB closes. What actually happens is that ActivityB just closes.

That is the default bahavior, the up navigation button works with the Activity Stack, if the ActivityA isn't in the stack, the Android will return to the previous screen , in this case the Home.

Related

Navigate up not working

I have three activities A->B->C. Sometimes I launch Activity C directly from A. Even then, when the user presses the "up" button, I want to go to activity B. So after a lot of searching, I am doing this:
AndroidManifest.xml
<activity
android:name=".B"
android:parentActivityName=".A"
android:launchMode="singleTop"/>
<activity
android:name=".C"
android:parentActivityName=".B"/>
In Activity C:
ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
....
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
Intent upIntent = NavUtils.getParentActivityIntent(this);
upIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
NavUtils.navigateUpTo(this,upIntent);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
But when I start activity C from A, the up button just goes back to A, instead of creating a new instance of B.
Even the android docs state:
When you call this method, it finishes the current activity and starts (or resumes) the appropriate parent activity. If the target parent activity is in the task's back stack, it is brought forward.
Am I missing something here?

Android App Activities Lifecycle

I have a problem that is annoying me. I have made an application that has two activitis. The first activity has a button and when you press the button it starts the second activity. I'm in the second activity and I press the home button to exit the app, and when I reopen the app the activity launched it's the first one. I want to launch the activity where the app was closed, in this case the second one. How can I do it?
public class FirstActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_first);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
View bub = findViewById(R.id.card_ub);
bub.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent1 = new Intent(FisrtActivity.this, SecondActivity.class);
startActivity(intent1);
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
// Respond to the action bar's Up/Home button
}
return super.onOptionsItemSelected(item);
}
}
Second Activity -
public class SecondActivityActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
View bub = findViewById(R.id.card_ub);
bub.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent1 = new Intent(FSecondActivity.this, FirstActivity.class);
startActivity(intent1);
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
// Respond to the action bar's Up/Home button
}
return super.onOptionsItemSelected(item);
}
}
Manifest file -
<application
android:allowBackup="true"
android:icon="#drawable/dc"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".FirstActivity"
android:label="#string/app_name"
android:screenOrientation="portrait"
android:theme="#style/AppTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".SecondActivity"
android:label="Example"
android:screenOrientation="portrait"
android:theme="#style/AppTheme">
</activity>
</application>
</manifest>
Check developer page for better understanding of backstack.
http://developer.android.com/guide/components/tasks-and-back-stack.html
just call startactivity(new Intent(FirstActivity.this, SecondActivity.class). if you shoould not call finish() when starting new activity. if you are using intent flags like CLEAR_FLAG it will destroy your activity when starting the second activity.
Check your phone setting if you setup "Don't keep background process".
In your case, seems your phone system always kill your application when entering background.
So, if your phone always does that, you can do two things:
close this setting.
Or, you can save activity status in SecondActivity, e.g, onPause / onStop, to let your application know that your current status is SecondActivity.
Next time you open the application, check your application status in FirstActivity, and restore the status to SecondActivity.

Android - back navigation from activity to previous one (no back arrow)

I have 2 activities: HomeActivity and EmailChangeActivity and some fragment inside HomeActivity. What I want to do is to set back navigation arrow in EmailChangeActivity toolbar. I have more activities and somehow I managed to make that arrow (but I made Intents straight from activities, not from fragment inside activities). What I did in order to get that arrow was:
When I go to EmailChangeActivity from HomeActivity I call this in HomeActivity fragment:
Intent intent = new Intent(getActivity().getApplicationContext(),
ChangeEmailActivity.class);
getActivity().startActivityForResult(intent, 1);
Inside EmailChangeActivity I insert standard code creating Toolbar and setting it:
// Setting Toolbar
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setTitle(getString(R.string.change_email_activity_name));
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setDefaultDisplayHomeAsUpEnabled(true);
In Manifext.xml I made:
<!-- Home Activity -->
<activity
android:name="com.example.nazwamarki.myapplication.HomeActivity"
android:label="#string/home_activity_name"
android:theme="#style/AppTheme.Normal">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- Change Email Activity -->
<activity
android:name="com.example.nazwamarki.myapplication.ChangeEmailActivity"
android:label="#string/register_activity_name"
android:theme="#style/AppTheme.Normal"
android:parentActivityName=".HomeActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.example.nazwamarki.myapplication.HomeActivity" />
</activity>
Still got no result. Any help?
Edit
I forgot to add that I also included in EmailChangeActivity:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.home) {
NavUtils.navigateUpFromSameTask(this);
return true;
}
return super.onOptionsItemSelected(item);
}
If you're not using an ActionBarActivity:
mToolbar.setNavigationIcon(getResources().getDrawable(R.drawable.ic_action_back));
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// The intent to go back to HomeActivity
}
});
If you are using an ActionBarActivity, then all you need to do is make Android use the Toolbar as an ActionBar.
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
Looks like you're missing this part:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
// Respond to the action bar's Up/Home button
case android.R.id.home:
NavUtils.navigateUpFromSameTask(this);
return true;
}
return super.onOptionsItemSelected(item);
}
You can get more details on this here Android Developers- Providing up navigation

Up Navigation is not working

So I have a very simple project. It contains two activities. The main activity has a navigation drawer and a fragment container. The second activity is merely meant to display details when the user interacts with a certain fragment.
So I have set my main activity as the parent activity to my second activity (called DetailsPage) like this:
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".DetailsPage"
android:label="#string/title_activity_details_page"
android:parentActivityName="com.collusion.serviceassistant.MainActivity" >>
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.collusion.srviceassistant.MainActivity"/>
</activity>
and in the DetailsPage activity code I have the following:
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
switch (item.getItemId()) {
case R.id.share :
share();
return true;
case R.id.home:
Log.i("BACK", "Going back!");
Intent upIntent = NavUtils.getParentActivityIntent(this);
if (NavUtils.shouldUpRecreateTask(this, upIntent)) {
// This activity is NOT part of this app's task, so create a new
// task
// when navigating up, with a synthesized back stack.
TaskStackBuilder.create(this)
// Add all of this activity's parents to the back stack
.addNextIntentWithParentStack(upIntent)
// Navigate up to the closest parent
.startActivities();
} else {
// This activity is part of this app's task, so simply
// navigate up to the logical parent activity.
NavUtils.navigateUpTo(this, upIntent);
}
return true;
}
return super.onOptionsItemSelected(item);
}
Now it seems that by my log, the code that pertains to the up action is not getting executed. Whenever I hit the up caret in the action bar or use the back hardware key, the app simply exits. Does anyone have any idea what I am doing wrong here? I am wondering if it has anything to do with the fact that the details page activity does not extend the ActionBar class:
public class DetailsPage extends Activity{
Does anyone have any ideas?
According to Google docs link on navigation using the home button you might want to use
android.R.id.home instead of R.id.home
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
// Respond to the action bar's Up/Home button
case android.R.id.home:
NavUtils.navigateUpFromSameTask(this);
return true;
}
return super.onOptionsItemSelected(item);
}
I think this might solve the home up navigation.

How can I return to a parent activity correctly?

I have 2 activities (A and B) in my android application and I use an intent to get from activity A to activity B. The use of parent_activity is enabled:
<activity
android:name=".B"
android:label="B" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.example.app_name.A" />
</activity>
I also use a theme which provides an UP-button.
So after I called activity B I can use the UP-button to get back to the activity A. The problem is that the application seems to call the onCreate()-function of activity A again and this is not the behaviour I need. I need activity A to look the same way like it looked before I called activity B.
Is there a way to achieve this?
EDIT
I didn't write any code to start activity B from activity A. I think it is auto-generated by Eclipse.
Class B looks like:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_b);
getActionBar().setDisplayHomeAsUpEnabled(true);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_b, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
NavUtils.navigateUpFromSameTask(this);
return true;
}
return super.onOptionsItemSelected(item);
}
You declared activity A with the standard launchMode in the Android manifest. According to the documentation, that means the following:
The system always creates a new instance of the activity in the target
task and routes the intent to it.
Therefore, the system is forced to recreate activity A (i.e. calling onCreate) even if the task stack is handled correctly.
To fix this problem you need to change the manifest, adding the following attribute to the A activity declaration:
android:launchMode="singleTop"
Note: calling finish() (as suggested as solution before) works only when you are completely sure that the activity B instance you are terminating lives on top of an instance of activity A. In more complex workflows (for instance, launching activity B from a notification) this might not be the case and you have to correctly launch activity A from B.
Updated Answer: Up Navigation Design
You have to declare which activity is the appropriate parent for each activity. Doing so allows the system to facilitate navigation patterns such as Up because the system can determine the logical parent activity from the manifest file.
So for that you have to declare your parent Activity in tag Activity with attribute
android:parentActivityName
Like,
<!-- The main/home activity (it has no parent activity) -->
<activity
android:name="com.example.app_name.A" ...>
...
</activity>
<!-- A child of the main activity -->
<activity
android:name=".B"
android:label="B"
android:parentActivityName="com.example.app_name.A" >
<!-- Parent activity meta-data to support 4.0 and lower -->
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.example.app_name.A" />
</activity>
With the parent activity declared this way, you can navigate Up to the appropriate parent like below,
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
// Respond to the action bar's Up/Home button
case android.R.id.home:
NavUtils.navigateUpFromSameTask(this);
return true;
}
return super.onOptionsItemSelected(item);
}
So When you call NavUtils.navigateUpFromSameTask(this); this method, it finishes the current activity and starts (or resumes) the appropriate parent activity. If the target parent activity is in the task's back stack, it is brought forward as defined by FLAG_ACTIVITY_CLEAR_TOP.
And to display Up button you have to declare setDisplayHomeAsUpEnabled():
#Override
public void onCreate(Bundle savedInstanceState) {
...
getActionBar().setDisplayHomeAsUpEnabled(true);
}
Old Answer: (Without Up Navigation, default Back Navigation)
It happen only if you are starting Activity A again from Activity B.
Using startActivity().
Instead of this from Activity A start Activity B using startActivityForResult() and override onActivtyResult() in Activity A.
Now in Activity B just call finish() on button Up. So now you directed to Activity A's onActivityResult() without creating of Activity A again..
I had pretty much the same setup leading to the same unwanted behaviour. For me this worked:
adding the following attribute to an activity A in the Manifest.xml of my app:
android:launchMode="singleTask"
See this article for more explanation.
Although an old question, here is another (imho the cleanest and best) solution as all the previous answeres didn't work for me since I deeplinked Activity B from a Widget.
public void navigateUp() {
final Intent upIntent = NavUtils.getParentActivityIntent(this);
if (NavUtils.shouldUpRecreateTask(this, upIntent) || isTaskRoot()) {
Log.v(logTag, "Recreate back stack");
TaskStackBuilder.create(this).addNextIntentWithParentStack(upIntent).startActivities();
} else {
NavUtils.navigateUpTo(this, upIntent);
}
}
[https://stackoverflow.com/a/31350642/570168 ]
But also see: https://speakerdeck.com/jgilfelt/this-way-up-implementing-effective-navigation-on-android
A better way to achieve this is by using two things:
call:
NavUtils.navigateUpFromSameTask(this);
Now, in order for this to work, you need to have your manifest file state that activity A
has a parent activity B. The parent activity doesn't need anything. In version 4 and above you will get a nice back arrow with no additional effort (this can be done on lower versions as well with a little code, I'll put it below)
You can set this data in the manifest->application tab in the GUI (scroll down to the parent activity name, and put it by hand)
Support node:
if you wish to support version below version 4, you need to include metadata as well.
right click on the activity, add->meta data, name =android.support.PARENT_ACTIVITY and value = your.full.activity.name
to get the nice arrow in lower versions as well:
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
please note you will need support library version 7 to get this all working, but it is well worth it!
What worked for me was adding:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
onBackPressed();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
public void onBackPressed() {
finish();
}
to TheRelevantActivity.java and now it is working as expected
and yeah don't forget to add:
getSupportActionbar.setDisplayHomeAsUpEnabled(true); in onCreate() method
I tried android:launchMode="singleTask", but it didn't help.
Worked for me using android:launchMode="singleInstance"
Adding to #LorenCK's answer, change
NavUtils.navigateUpFromSameTask(this);
to the code below if your activity can be initiated from another activity and this can become part of task started by some other app
Intent upIntent = NavUtils.getParentActivityIntent(this);
if (NavUtils.shouldUpRecreateTask(this, upIntent)) {
TaskStackBuilder.create(this)
.addNextIntentWithParentStack(upIntent)
.startActivities();
} else {
NavUtils.navigateUpTo(this, upIntent);
}
This will start a new task and start your Activity's parent Activity which you can define in Manifest like below of Min SDK version <= 15
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.example.app_name.A" />
Or using parentActivityName if its > 15
I had a similar problem using android 5.0 with a bad parent activity name
<activity
android:name=".DisplayMessageActivity"
android:label="#string/title_activity_display_message"
android:parentActivityName=".MainActivity" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.example.myfirstapp.MainActivity" />
</activity>
I removed the com.example.myfirstapp from the parent activity name and it worked properly
In Java class :-
toolbar = (Toolbar) findViewById(R.id.apptool_bar);
setSupportActionBar(toolbar);
getSupportActionBar().setTitle("Snapdeal");
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
In Manifest :-
<activity
android:name=".SubActivity"
android:label="#string/title_activity_sub"
android:theme="#style/AppTheme" >
<meta-data android:name="android.support.PARENT_ACTIVITY" android:value=".MainActivity"></meta-data>
</activity>
It will help you
Add to your activity manifest information with attribute
android:launchMode="singleTask"
is working well for me
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
// Respond to the action bar's Up/Home button
case android.R.id.home:
finish();
return true;
}
return super.onOptionsItemSelected(item);
like a Back press
try this:
Intent intent;
#Override
public void onCreate(Bundle savedInstanceState) {
intent = getIntent();
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_b);
getActionBar().setDisplayHomeAsUpEnabled(true);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_b, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
NavUtils.navigateUpTo(this,intent);
return true;
}
return super.onOptionsItemSelected(item);
}
Going into my manifest and adding android:launchMode="singleTop" to the activity did the trick for me.
This specifically solved my issue because I didn't want Android to create a new instance of the previous activity after hitting the Up button in the toolbar - I instead wanted to use the existing instance of the prior activity when I went up the navigation hierarchy.
Reference: android:launchMode
Try this solution use NavUtils.navigateUpFromSameTask(this); in the child activity:
https://stackoverflow.com/a/49980835/7308789
In any context, If you want's to open parent activity on onBackPressed
protected fun navigateToParent() {
NavUtils.getParentActivityIntent(this)?.let { upIntent ->
if (NavUtils.shouldUpRecreateTask(this, upIntent) || isTaskRoot) {
Timber.d("navigateToParent: sourceActivity should recreate")
startActivity(upIntent)
} else {
Timber.d("navigateToParent: sourceActivity in stack, just finish")
}
}
super.onBackPressed()
}
Set android:parentActivityName in manifest
<activity
android:name=".feature.signup.SignUpActivity"
android:parentActivityName=".feature.welcome.WelcomeActivity"
android:windowSoftInputMode="adjustResize" />

Categories

Resources