Shared publicly  - 
 
The Android back stack is broken

I want to discuss something that’s been bugging me for a while. The Android back stack. Most Android users love the back button, and I do too. But, the design is broken. I’ll explain with an example:

You receive a text. You tap the notification, which opens a conversation with your friend. She invites you to a party and asks you to invite some friends. You respond, “sounds good!”, and then tap the back button on your Android phone to return to your list of messaging contacts. Except instead of going to the list of contacts, you are taking back to the Android launcher.

“Huh”, you think to yourself, “I swear hitting back from a text conversation took me to my contacts list?” Moving on with life, you tap on the messaging app and proceed to fire off texts to your buddies to invite them to the party. You close the messaging app by hitting home.

Five minutes later, you receive a text from your buddy who says he can’t come because he’s playing Skyrim. You reply, “get off your ass and socialize you introverted dragon-born”, you tap the back button to return to the launcher. Except this time you end up at your buddy list.

Now you’re super confused. You swear that last time you hit back, the launcher opened, but this time it was the buddy list. How is this possible?

Unfortunately, the result of pressing the back button is non-deterministic. There is no way to know for sure where the back button will take you.

The Android Back Stack

Every Android application is a series of activities held in a stack, which is together is called a task. When the user presses the back button, the top activity in the task is popped off. If there are no more activities, the user returns to the parent task that started the task, which is often the Android launcher. Multiple tasks can be running at once, and the user can switch between them using the multi-tasking button or hitting home and choosing a new app.

Checkout this diagram from the Android developer documentation of a sample task:
http://developer.android.com/images/fundamentals/diagram_backstack.png

On paper this system is consistent and deterministic. In practice, Android phones don’t have unlimited memory, so when too many tasks are in RAM, the system will destroy old activities and tasks to make room for new ones. Other times, the system will destroy activities after a period of inactivity.


(Edit: +Dianne Hackborn of the Framework team corrects me:

"I'm sorry, but you are completely wrong to tie this with memory management. How back operates has nothing to do with memory management, activity state saving, etc. It is deterministic without knowing how activities are being killed in the background and their state being saved.

What is missing is just consistency in the behavior apps implement for the back button. And actually this is a more specific inconsistency: how apps handle their back stack when the user launches into them to a potentially different state than they were last in. That is, from a notification or a widget."

More explanation from her in the comments. I really wish G+ let you link to comments. Sigh. )


For some apps this behavior is inconsequential. However in other cases there are unintended consequences, such as with notifications. When a user clicks on a notification, a new task is started or if the task is already in memory, a new activity is added to the top of the task stack.

There is no way to know which behavior occurred. So when you open a text message notification, the behavior of the back button depends on whether the messaging app task already existed in memory or not. The ambiguity is confusing, even to seasoned Android users.

Android developers have tools at their disposable to combat this problem. App best practices suggest to lazily save activity state to disk in the event of activity destruction, and restore state when the activity is needed again. Unfortunately, many apps don’t do this. And the ones that do often build perplexing activity stacks. Even first party apps are not immune.

Take the Google+ app. It has the most confusing back-stack I’ve encountered. I often click on posts from my launcher’s G+ widget. If I hit the back button repeatedly from a post, I get led through a seemingly random series of activities. Sometimes this stack ends at the launcher, and sometimes it ends at the Google+ home activity, but I’m never sure which I’ll get or how many steps it will take to get to the end.

The Facebook messenger app doesn’t manage activity state correctly. When you receive a notification, the app opens a new instance of the conversation activity, even if that conversation was already at the top of the activity stack. So when you hit the back button, the conversation you were just reading fades out, then fades back in because the same activity appeared twice on the stack.

Even as a developer and Android power user, I’m still regularly confused by the back stack. I can only imagine the confusion for novice and casual users.

Note: I glossed over some details of the back-stack and simplified the description for the purposes of narrative. If you’re interested in understanding the precise behavior of the Android back-stack, read the documentation: http://developer.android.com/guide/topics/fundamentals/tasks-and-back-stack.html

Ice Cream Sandwich to the rescue! (not)

So what can be done? In Ice Cream Sandwich, first party apps introduced a new design language straight out of iOS: a software back button in the top left of the screen. The beauty of this “bread crumb” back button is that it takes you back to the “logical” place in the application, instead of popping the current activity. Often these are the same place, but not always.

For example, in the text messaging app, hitting the bread crumb back button takes you to your conversion list every single time. Ah, finally some consistency! Unfortunately, this is a small victory. Each Google app implements the bread crumb back button differently. Some, such as Google+, seem to use it as a redundant back button. Others such as the Android Market, use it in a way that occasionally are counter-intuitive.

If anything, the new breadcrumb back buttons have made things more confusing because I often wonder if I should hit the hardware back button or the breadcrumb back button. Despite this, breadcrumb back buttons are put to good use in a few apps, notably Messaging, Gtalk, Gmail, and Gallery.

A (better) Solution

The back button is powerful. When it works (and it works most of the time), apps have more flexibility than on iOS to integrate activities from other apps. The intent system in Android is brilliant, but would be useless without the back button. We’re stuck with the back button for the long haul.

Thankfully, with the introduction of the soft back button with the Galaxy Nexus, the Android team has increased flexibility in how they represent the back stack. For example, the back button could be annotated with the icon of the task it leads to. This way the user knows if they are about to accidentally leave an app. The breadcrumb back button could indicate where it leads. Checkout example mock I’ve created with user experience designer +Fravic Fernando attached to this post.

With this design, it’s clear to users where they are going, so they know whether to hit the back button or the breadcrumb back button. The confusion is gone. This is a simple and relatively easy to implement solution. There are more visually exciting solutions, such as representing the task stack as an actual visual stack and using swiping gestures for navigation.

Even with my suggested improvements, apps will still have poorly designed activity stacks. Ultimately it's up to app developers to build consistent and easy to navigate app. Perhaps the best solution is to raise awareness amongst developers of the perils of the Android back stack.

What it comes down to it, Is the back stack problem a show stopper for Android? No. Android wouldn’t be the most popular smart phone OS if it was. But, it’s a real issue that effects Android users every single day.

I’d love to hear your thoughts. Does the Android back button bother you? If so, how should it be fixed?

PS: This is the last smart phone related update I’ll be posting for the time being. I begin work at Microsoft next Monday and it would be inappropriate for me to comment on the industry while I know any confidential information.
29
14
Jonathan Baker's profile photoMartin Müller's profile photo余振鹏's profile photoDaniel Hoeggi's profile photo
20 comments
 
Aww, no more Munn posts about Android. Those are always fun.
 
Windows Phone handles the back-stack pretty well: it produces deterministic "back" behavior irrespective of the memory manager. If the app has died, it gets restarted. This is far superior to having an "informed" back button that tells you which magical result your press of the button will produce. Why can Android not do this?

I don't buy it. Determinism over informed non-determinism any day.

Edit: note that in Mango (Windows Phone 7.5), you can see the "live" back-stack by holding the back button, indicating all the apps that haven't yet been killed. This stack is not deterministic. However, a single press of the back button will always yield the same result in the same situation.
 
All applications should just implement back as emacs-style undo. It's the most awesome feature in the world once you're used to it.
 
+Tadej Rudec yes, but sometimes when you come to the message from the notification, it does take you back to the sms list. No way to be sure which will happen.
 
Nearly everything you described is not a problem with Android's Back button: it's a problem with poorly written applications. When a notification arrives, the new activity it would jump to does NOT have to pull in the stack from its potentially already-running app. Android's Notification system already adds the FLAG_ACTIVITY_NEW_TASK option to activities that it starts. Properly written apps will take advantage of this in one of two ways. First, it could have a unique activity that can only be launched from a notification (like Calendar's reminder view). If that isn't possible (and it commonly isn't in apps with conversations, like Talk, Messaging, or Gmail), then when you create the notification you can pass in your own flag: FLAG_ACTIVITY_CLEAR_TOP. In combination with the _NEW_TASK flag, this will ensure that the Back button isn't "hijacked" when a user touches a notification. Note that depending on your requirements, FLAG_ACTIVITY_MULTIPLE_TASK might also be helpful, despite the ridiculous warning in the documentation about using it.

The problem that you're seeing is that a default app (Messaging) does not properly do this. Shame on Google for not following their own UI guidelines. But still it's not the fault of the Back button's behavior. For reference here is Google's own documentation to developers about how to properly handle Notifications and the Back button:

http://developer.android.com/guide/practices/ui_guidelines/activity_task_design.html#notifications_get_back_tip
 
+Marco Chomut yes there are a lot of tools available to mitigate the problem, but it's a shame many apps don't use them.
 
I'm sorry, but you are completely wrong to tie this with memory management. How back operates has nothing to do with memory management, activity state saving, etc. It is deterministic without knowing how activities are being killed in the background and their state being saved.

What is missing is just consistency in the behavior apps implement for the back button. And actually this is a more specific inconsistency: how apps handle their back stack when the user launches into them to a potentially different state than they were last in. That is, from a notification or a widget.

These days applications should either switch to a dedicated activity for handling the notification/widget UI (see for example the list of events that you go to for Calendar) or into a state where pressing back will bring the user back through a stack that is the same as they would have had if they had navigated to that state (see for example Gmail when you tap on a notification for a single new e-mail). It is obvious how to implement the former; for the latter newer APIs like http://developer.android.com/reference/android/content/Context.html#startActivities(android.content.Intent[]) make this fairly easy or if you are using fragments this is straight-forward to implement as well.

It is unfortunately true that there are still many apps that don't follow these conventions, even in the base platform. This does not represent an intrinsic flaw with the platforms definition of the back button (and certainly nothing to do with how that relates to memory management), but just inconsistency in the implementation of those apps.

Finally, knowing what will happen when you press the back button is not nearly as easy to determine as you think. The back button is a regular button that can be handled by the application. It needs to be this way so that for example the browser can use it to go back through its history, it can be used to dismiss the pop-up of a spinner, it can change the state of fragments to move to a previous state in an activity, etc. We had wanted to hide the back button in situations when it wouldn't do anything (such as being in home) and show a different icon when it would close a dialog, but even that is complicated because of the app being involved -- it would require adding a new API for apps to report how the back button will be handled and know when things change in the application such that this state needs to be re-queried. And since this would be a new API, the behavior would be pretty inconsistent since no old applications would be able to report the correct state.
 
+Andrew Munn Agreed. Especially the default apps that ship with Android, developed by Google. They really should know better!
 
+Dianne Hackborn thank you for the clarifications. My confusion around the memory limitations comes from some of the language on the documentation page, specifically:

However, if the user is running many background tasks at the same time, the system might begin destroying background activities in order to recover memory, causing the activity states to be lost.

I gather that most apps correctly respond to this behavior. I've quoted your comment in an edit to the original post so as not to mislead people.
 
That part you quoted references the section on activity state that clarifies this. This is just for the state inside of an activity such as text user may have entered etc. That is, onSaveInstanceState(), that is, the per-activity state, that is nothing to do with back stack except for apps that may handle back internally for special cases, which is not what you are talking about in your post.
 
Is this an Android 4.0 related change? As far as I can recall, the back button wasn't doing anything "funny" on my Android 2.3 Droid X.

I have noticed the back button behavior you specifically reference in your original post related to txt messaging on my Galaxy Nexus though. It is kind of frustrating sometimes.
 
I've always thought the back button should take you one level higher in the hierarchy of whatever app you're in with two exceptions: the browser, and if you switched apps using the notification bar.
The worst offender is Google Voice. Even on Ice Cream Sandwich it is unpredictable.
 
Google Voice and Google Plus are the worst imo. Maybe I am just use to the weirdness that happens in the other apps.
 
The broken back button with text messages annoys me the most since it's so blatantly obvious that the behavior is incorrect. For some reason, I thought this was Samsung's fault since I've been using Samsung android for a long time.
 
Good post. This has always annoyed me as both an Android power-user and as an app developer. My solution was just to handle the back button in my apps so that I could control the behavior myself. I'm slowly adjusting to the new "breadcrumb" back buttons of ICS as you call them, and this helps but it only adds to the issue of inconsistency. That has always been the double-edged sword of Android. The lack of strict app development guidelines fosters innovation but leaves the door wide open for inconsistency.
 
I have over time learned my way around the back button but it still has some amazingly bad coding in certain apps like the FB messenger as you said.

But if say I open a link from an app, by going back it takes me back to that app. Same as when I open a Whatsapp notification. But occsionally, some apps won't work that way. As you and Dianne mentioned, consistency is the key.
 
I totally agree that it's broken. And that hints for what the back button will do would change everything. The examples in android docs of how to implement "correct" stack manipulation are so unwieldy that to most users, even power users (me at least), it feels unpredictable, and as a developer, I leave manipulating the back stack only to situations where it is obvious that it is required for acceptable behaviour.
Add a comment...