I am developing an android app. I want my app to have a home button. So I decide to use a clickable ImageView for that, which I am placing in the title bar. Whenever a user clicks on the home image, the app will navigate to the home screen: which I accomplish by having the image dispatch an intent to start the HomeActivity.
My concern is that the whole approach feels like poor design (I may be wrong). Basically all activities follow the HomeActivity. And since I don't normally call finish() on my activities (so to allow back-button navigation) would I end up in a loop? As in, say a user goes from HomeActivity to FooActivity then to BarActivity then clicks on the home image hence going to HomeActivity. I know I can rely on android to reclaim memory when it needs it. But I don't want my app to tax the system so much.
So how do android designers normally design home icons/buttons so to avoid this looping problem? Or is android aware that I am returning to HomeActivity and thus may finish the previous instances of the other activities I just walked through?
Using the App Icon for Navigation for this
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// app icon in action bar clicked; go home
Intent intent = new Intent(this, HomeActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
Related
I don't know how to phrase this question.
My app has a simple ViewPager and you click on something in one of those page Fragments and it takes you to another Activity. Press the back button and it takes you back to the ViewPager. Press back again and it closes the app.
However, sometimes when I press the back key at the ViewPager, it takes me back to the other Activity again, and then I press back and it takes me to the ViewPager, and so on, until the app finally closes. In other words it's like there are spare, leftover instances of either the ViewPager or the other Activity in the backstack (I think it's called), but I have no idea how or why this is happening.
I also don't know how to reproduce the error, which is even more frustrating. Most of the time it works as expected, but sometimes the leftover instances just show up out of nowhere as I am pressing back.
How can I guarantee better that when I press the back button on the other Activity, it goes back to the ViewPager, and when I press back on the ViewPager, it closes the app?
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home: //called when I press back button on the phone or the back-arrow on the toolbar
onBackPressed();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
//and then usually that's all I have, but in one particular Activity, I do override the function:
#Override
public void onBackPressed() {
if (some conditions are met) {
finish();
super.onBackPressed();
}
else {
//display some error message
}
}
Here is how I launch my Activities:
public void launchSomeActivity() {
Intent intent = new Intent(getActivity(), ActivityName.class);
intent.putExtra( etc etc etc );
startActivityForResult(intent, REQUEST_CODE);
}
Likely you are seeing a nasty long-standing Android bug. If you launch your app for the first time from an IDE, or from the installer, when you put the app in the background and launch it again from the HOME screen, Android creates another instance of your root Activity. This would exhibit exactly the behaviour you are reporting. If you launch the app for the first time by pressing the app icon from the HOME screen (or list of available apps), the problem does not occur.
See Re-launch of Activity on Home button, but...only the first time
I am implementing up navigation in my action bar with the 'back' arrow.
I have been doing this as follows:
ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
and declaring the parentactivity in the manifest manually. The problem is, in my app for some activities there maybe many routes to the destination activity.
I have been researching this http://developer.android.com/guide/topics/ui/actionbar.html#Home
and to quote
Or, override getSupportParentActivityIntent() and
onCreateSupportNavigateUpTaskStack() in your activity. This is
appropriate when the parent activity may be different depending on how
the user arrived at the current screen. That is, if there are many
paths that the user could have taken to reach the current screen, the
Up button should navigate backward along the path the user actually
followed to get there.
The system calls getSupportParentActivityIntent() when the user
presses the Up button while navigating your app (within your app's own
task). If the activity that should open upon up navigation differs
depending on how the user arrived at the current location, then you
should override this method to return the Intent that starts the
appropriate parent activity.
The only problem is I don't know what to override it with to get the current parent activity. Has anyone used this previously? I'd appreciate advice
If anyone could help me on how to do this I'd greatly appreciate it, I'm not as suggested using it as a back button. I'm just trying to overwrite the up button.
Oh...for anyone who might need a more helpful answer than those provided...
here is what I have done
#Override
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 android.R.id.home:
finish();
overridePendingTransition(R.animator.close_slide_in, R.animator.close_slide_out);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
so in the case of android.r.id.home that's where you put your required action. In my case I just wanted to finish the current activity
I hope that's of some use to somebody out there
According to the Android guidelines, you should not make the up button behave in different ways everytime. That is the way the back button should work.
On my apps home page I have an option to add items to a ListView using adapter.add(string). I also have another Activity that my app goes to using startActivity(intent). When I am in that second Activity and I press the back button all of the data that was added to the list is still there, however when I press the icon at the top left all the data is gone. Is there a way to make it so that the button for the icon preserves the data in my list. I think I should note that I don't want the data to be preserved when the app is closed, only when navigating through the open app.
This is my current method that handles the home button action:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
NavUtils.navigateUpFromSameTask(this);
return true;
}
return super.onOptionsItemSelected(item);
}
A quick solution would be to call onBackPressed() instead of NavUtils.navigateUpFromSameTask(this). This, however, isn't recommended and you should try to implement proper navigation logic. Take a look at the answers to this question as well as these tips.
I have Activity A (Main) and Activity B.
Fact: Activity A has: android:launchMode="singleInstance"
Usual scenario is:
User launches application > Activity A.
User clicks an item > Activity B
3.A. If user clicks on back/up buttons > Back to A (without calling finish() on B)
User clicks the SAME item as before > Forth to B.
At this point he can go back and forth without new instances. It's all in the stack and it doesn't recreate activities. (All right!)
3.B. If user clicks Home, then goes to task manager and brings the app to front > Activity B (all good, so far)
If user clicks UP button, it goes to TASK MANAGER, and I want it to go to Activity A (back button is expected to work this way, so let's focus on UP button).
Here's the implementation I have in Activity B for BACK and UP buttons.
#Override
public void onBackPressed() {
moveTaskToBack(true);
// I don't want to finish() the activity, so the user can reclick the same
// item without reloading the whole activity again (webview slow when parsing html).
return;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
moveTaskToBack(true);
// I don't want to finish() the activity... idem.
// I need to implement here the bring Activity A to front
break;
}
}
So, what I want is: to "Go Back" to Activity A keeping the same idea of using the stack to reload Activity B if needed, without using Intents (unless it calls activity to front, without adding items to the stack.)
Let me know if I explained myself clearly and if you need more info.
UPDATE:
I've found this at: http://developer.android.com/training/implementing-navigation/ancestral.html
This is how I adapted it.
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
Intent upIntent = new Intent(this, Activity_A.class);
if (NavUtils.shouldUpRecreateTask(this, upIntent)) {
TaskStackBuilder.create(this).addNextIntentWithParentStack(upIntent).startActivities();
} else {
moveTaskToBack(true); // I want it this way. Don't worry.
}
break;
}
}
But the method NavUtils.shouldUpRecreateTask is ALWAYS returning false.
I did the http://developer.android.com/training/implementing-navigation/ancestral.html#SpecifyParent part, so that's not the issue.
My problem is that I want to recognize if Activity A exists in the stack, for when i.e. the app is launched from the task manager.
How can I achieve this?
Thanks.
moveTaskToBack moves the entire task to the background. it doesn't finish the activity.
in order to have full control of activities, you have some possible solutions:
create your own global manager for the activities, monitor each of them through all of their lifecycle and decide what to do on each event.
you could also finish each activity as soon as you go from it, and put "it" (just its name or something) in a stack and restore its state when you come back to it.
use fragments instead, and manage them all on a single activity. be warned of configurations changes though.
I want to implement Navigation Pattern in my app with Up button in ActionBar.
I have Details Activity, here I can come from home, favorites and search screen. Also I can open this screen from browser(handling specific url). When user press Up button, I use flush() method, to emulate back navigation. But for case, when user come from browser, I want to open home screen instead of previous browser activity. How I can recognize, that previous activity was from another app, and navigate to home screen?
Up Should always navigate to the hierarchical parent of the activity and Back should always navigate temporally.
In other words you should leave Back as it is.
As for Up, it should always go to the same place no matter where it came from. So if you normally come to the DetailsActivity from YourListActivity, Up should always go there no matter where you came from. What is the most likely place is up to your discretion, but it should always be the same.
If you come to the Details Activity from a non-normal location (such as the browser, another activity, widget, or notification) you should recreate your task stack so navigation using up results in the same path. Here is an example from the Android Developer Training:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
Intent upIntent = new Intent(this, YourListActivity.class);
if (NavUtils.shouldUpRecreateTask(this, upIntent)) {
// This activity is not part of the application's task, so
// create a new task
// with a synthesized back stack.
TaskStackBuilder
.from(this)
.addNextIntent(new Intent(this, HomeActivity.class))
.addNextIntent(upIntent).startActivities();
finish();
} else {
// This activity is part of the application's task, so simply
// navigate up to the hierarchical parent activity.
NavUtils.navigateUpTo(this, upIntent);
}
return true;
}
}
Here is the Android Training on Implementing Navigation
(http://developer.android.com/training/implementing-navigation/index.html).
You will need the support library for NavUtils and TaskStackBuilder.