Tip:
Highlight text to annotate it
X
RICHARD FULCHER: So good morning.
Welcome to a session entirely devoted to
navigation in Android.
My name's Rich Fulcher.
I'm one of the interaction designers on the Android user
experience team.
ADAM POWELL: And I'm Adam Powell.
I'm a framework engineer in Mountain View.
RICHARD FULCHER: And we both care passionately about
navigation.
In fact, when I first applied to work at Google three years
ago, resolving questions with Back was part of my first
interview to become an interaction designer here.
So we're going to take you through a
lot of content today.
So to get started, to really understand tasks in Android,
first, you have to have a good understanding
of how tasks behave.
And then Adam will help set the stage for that.
ADAM POWELL: So a lot of early Android apps talked about
being task managers.
But generally, they were actually talking about
managing processes.
In Android, a process can be a container for multiple
components.
And a task can contain activities hosted by many
different processes.
They really aren't the same thing.
RICHARD FULCHER: So let's just do a couple
of examples of this.
This is a really simple task that we'll build out.
We're going to open Gmail.
And we're going to dive in and view a conversation.
And the way I'm going to show a bunch of examples during
this talk is with this format.
The left-hand side of the screen will show the state of
the task stack as activities are added to it.
And the right-hand side will show the screen progression
that the user experiences as they navigate.
So starting here, we start at the Home screen.
We have the Launcher activity at the base of the
task stack for us.
Clicking on the Gmail icon from Home opens up the
activity for the Gmail Conversation List.
I'm just going to use wire frames throughout this talk,
just to keep the focus on the navigation itself.
So that has added the Conversation List activity
onto the task stack.
If I navigate deeper, I go down into a particular
conversation to view the messages inside of that.
Then the Conversation View was added as well.
And that's just building up a very simple task.
Another slightly more complicated example involves
activities that are coming from multiple applications.
Adam mentioned that we can do this within a single task.
That's one of the strengths of Android.
So I'm going to start at Home again.
I'm going to build into--
enter into Talk, where I see the Friend List, the list of
everybody I can have a conversation with.
I'll pick a particular friend from that list.
Go into the Chat View.
That activity gets added on.
Let's say that friend had sent me a link to a YouTube video.
I can continue into a different application.
In this case, I can go to YouTube.
And that activity is added to the task stack as well--
the same system.
We're just adding and adding and adding on
top to the task stack.
And I can go further.
If I wanted to watch this video and then share it with a
friend, I could hit the Share button.
And that'll take me to Gmail's Compose Screen, yet another
activity that we just drop onto the task stack.
So now we finish this example.
We've got Launcher at the root of the stack.
We've got activities from three different applications,
all part of this one continuous task.
And this is the way that tasks have always worked inside of
Android, all the way back to Android 1.0.
And one particular control, the Back button, has been
along for the whole ride.
Although over time, it's changed its appearance a
little bit.
It's now trimmer than it used to be.
So Back works by unwinding that task stack
that we build up.
It actually unwinds the global history stack.
We'll get into that in a little bit more detail.
It finishes off the current activity.
So when I hit Back, the activity has the opportunity
to do things, save out any local state
that it wants to preserve.
And then clears itself away off the task stack.
And the ActivityManager brings forward the next lower down
activity and presents that to the user.
Now, of course, there are a couple of exceptions.
Most of these just relate to when Back handles a local bit
of state within the activity.
So things like if the virtual keyboard is displayed, Back
will recede that.
If there are dialogues or spinners that have popped
open, Back will dismiss those.
If you have a selection mode, Back will get rid of that.
And then a subsequent press of Back in all of those cases
will actually act as the navigation.
There are also a few instances where Back is completely taken
over by the application.
The browser is the most obvious and notable example of
that, where Back becomes back through your browsing history,
kind of historical browsing context within browser.
So going back to the two examples we covered at the
start, what does Back do?
Well, it's actually really simple in both cases.
Back from Gmail just pops that activity off the stack.
And the Conversation List comes to the front.
Hitting Back again finishes that activity,
returns me to Home.
Same is true for the slightly more complex case.
Again, we built up these different activities from
different apps.
But Back just walks through them just as comfortably.
Back, Back, Back, Back to Home.
And once we're at Home, there's no place
further back to go.
So Back loses meaning once it lands in that context.
You've got a safe root point to do all of
your exploration from.
So now Adam's going to talk a little bit about how multiple
tasks work.
ADAM POWELL: Right.
We've been focused on single tasks so far, but how do
multiple tasks behave?
So you might have noticed that the Recents list here is a
whole lot like something else that you might be used to
using day to day.
So it's very similar to your browser tab list.
But so how do tasks really work in the context of
Android with this?
What are all those intent flags that you see in the
developer documentation?
There's a lot about how tasks work internally that isn't
immediately obvious.
But it really helps make things feel right to the user
when they're all put together.
And it's useful for you as a developer to know how a bunch
of this stuff is going on under the hood, even if your
users don't have to.
So ActivityManager, which is the component that ties all of
this navigation together, sees the world as one big global
activity stack sorted by task.
So this might explain some of the behavior that you've seen
here and there that might have made you scratch your head.
So if I hit Back a few times, I'll pop from the top of the
stack until I hit Home.
Home then prevents me from popping further.
The rest of the stack still exists, though.
This is part of my global navigation
history across the system.
So we said before that your list of tasks in Android is
very similar to your tabs in a browser.
So how do you open a new tab?
How do you create a new task?
So in an example here, from Home, we open Talk.
A new task is created.
And further navigation within Talk just adds
to that same task.
So how many of you use tabbed browsing out there?
Show of hands?
OK, pretty much everybody.
So keep your hand up if you end up with way too many tabs
open at the end of the day.
Oh, look at that.
Just as many people.
So we really didn't want to have the same problem happen
in Android.
Because manually curating your browser tabs really stinks.
You have to do this manual garbage collection pass every
now and then, just to make sure that things stay cleaned
up and that you can still understand what the heck
you're doing on your desktop.
So we have this idea called Task Affinity in Android.
Task Affinity lets us keep a single context associated with
a task instead of multiple tasks that
are very, very similar.
And this avoids having multiple tabs open for doing
the same thing.
So how does this work?
When we launch an activity into a new task here and a
task with the same affinity already exists, then the
existing task gets brought to the front.
Now, if the intent that we just launched matches the root
intent of that existing task, the one that's at the very
bottom of the task stack, then we're done.
We have nothing else to do.
So what it means for an intent to match is a little
unintuitive if you're not familiar with this particular
little detail here, is that intent extras don't count.
They're always app specific.
And the system really doesn't even pretend to know how to
unparcel them and compare them for any sort of equivalence.
So that means that intents can match even if they have very
different extras.
But all of this put together means that this is why
Launcher is able to act as a task switcher on its own.
Shortcuts always launch a new task.
And it's always the root activity of that task if it
was already existing.
So before Honeycomb, this is how a lot of users got around
the system.
You would just hit Home.
And then you would reopen the app that you wanted.
But it would reopen to exactly the same state that it was in
the previous time that you were using it.
RICHARD FULCHER: So now we've got a handle
on how tasks work.
We've talked a little bit about affinity, how Back
behaves, but navigation has evolved
during Android's history.
And in particular, we'll talk about Up and Recents, and how
they've been added.
So let's bring the timeline back up.
By the start of 2010, we knew we kind of had a problem.
Or more exactly, we knew that our users were having several
problems when it came to navigation within Android.
We had system-level controls for navigation.
We had Back, which we've talked about.
And we had Home.
Home was kind of a task switcher, but it was a little
bit awkward for that.
I'd have to hit the Home key.
I'd come back to the Home screen.
Maybe the task I'm trying to switch to isn't on that Home
screen, so I might have to locate it.
Or maybe it is on any of the Home screens, and I have to
bring up the All Apps drawer to find it.
We had a more elegant way of doing that, which was our
Recents control, which you'd invoke by kind of long
pressing on Home.
And it would bring up not a lot of
details about the tasks.
You'd get five application icons and five labels.
But we knew from listening to the users that people just
didn't know this function existed.
It was really a very hidden, power-user feature.
And users were craving something that was a lot more
obvious than that.
What about for the
application-level navigation controls?
These are switching between tasks--
or moving within the task.
What about inside an app?
We didn't have any story really there.
Now, that didn't stop charming, clever developers
such as yourselves from coming up with ways
to work around this.
One popular one was to take the Menu button and to add
additional actions into that that would target specific
activities within your application.
So it might be that you added an action to go to the
Home of your app.
Or to go to a common screen like an Account list or an
inbox, those types of things.
Another approach that a lot of apps took was to take the Back
button and try to turn it into something like a structural
navigation element by overriding its behavior.
A lot of apps did this.
I've worked on apps that did this--
[COUGH]
Gmail.
But it made the Back button very inconsistent for users.
They couldn't really predict what was going to happen when
in certain contexts we'd get overridden and
do something different.
So we wanted to address those.
I think a problem that happened with a lot of early
Android applications is that it was easy to build them in a
way that it was just kind of like a bag of activities that
you would throw your activities into.
And you could shake it up.
And the user could move to different activities through
whatever affordances you wanted to give them.
And there might be a top doorway in.
But once you started diving in a little bit, you could get
these paths that were a little bit formless, a little bit
unpredictable, and could even have circuits in the path
where I start from one screen and follow a
forward-navigating path that takes me back
to that same screen.
In which case Back gets quite interesting.
We definitely heard from coworkers, from users, a lot
of frustration.
And when people are frustrated, they come talk to
their designers.
So we didn't want to be associated with this.
We wanted to take this problem head on and really try to do
something about it.
So we did.
We started at I/O two years ago.
Myself and a few other members of the user experience team
were on a stage about this size, talking about five
interface patterns that we thought were helpful for app
developers.
And one of the ones we introduced in that session,
talked about, was the Action Bar.
So the Action Bar was trying to solve two problems.
The first was to make the most common actions more visible.
And you've heard about that in the sessions earlier today, so
I won't go there.
But the other thing it tried to do is give a sense of
structure and place to the app.
The Action Bar was intended to replace the
old Title Bar element.
Internally, we called it the Interactive Title Bar for
quite a while.
So the area at the left would give you the app icon and the
name of the activity that you were currently viewing.
But it would also be a touch target for jumping back up to
the top of the application.
In the same way that a user might expect to touch at the
logo at the upper left corner of a website, it's going to
come back to the home of that site.
So we're trying to play off those conventions.
Now that said, what we gave you at I/O two years ago was
far from perfect.
It was an interface pattern.
It wasn't supported by the framework.
It wasn't a code pattern yet.
We were just kind of offering, this would be a good thing for
you to go and do.
And it also only supported one target, which was navigating
directly to the top of the application.
And for some apps that's fine, and that's suitable.
For apps with deeper hierarchy, you want to have a
little bit more subtlety than that.
At the time, we were demonstrating the Facebook app
and the Twitter app during that session.
And those have a much richer set of activities.
They have entire subsections to those apps.
And a little bit more navigation control would have
been appropriate.
So in 2010, we did Gingerbread.
It didn't really change the story there.
But in 2011 and 2012, we really started
tackling this problem.
We wanted to take the direction we'd laid out with
that alpha version of the Action Bar and really
reinforce the story that was there.
And even as we were chatting at I/O two years ago, we were
already hard at work on our tablet UI.
So we started rolling that thought right into Honeycomb,
what would become the full Action Bar.
And then in ICS, we brought it to phone with even more
capabilities.
And navigation was a critical part of that.
So a lot of what we tried to do in those two releases was
motivated by what we saw from user research.
We did very frequent testing for Honeycomb.
Literally, we would have two or three sessions a week with
four or five different participants in a given
session for four months when we were testing Honeycomb.
And during all of those tests, we were testing navigation to
some extent.
We were testing a lot of different applications.
But that kind of glue that let the user get to the
applications, switch between them, was always something
that we were looking at.
When I think about evaluating what research can do for you,
I think the wrong question that people ask too often is
if they do an experiment.
And then they say, well, did the product test well?
I think a more valuable question to ask is, did we
glean some new insights to the problems that
we're trying to solve?
And when it comes to navigation and the work we did
in Honeycomb, we learned a lot.
Our four big takeaways were this notion of the navigation
being in the upper left corner of the screen calling back to
their experience with the web and with other devices was
really powerful for users and felt very natural.
Users wanted to make a clear distinction between navigation
that kept you inside an application and navigation
controls that were outside of it.
So users definitely had a distinction between things
that we would render in the applications content area and
things that would be rendered in the System bar.
Or more typically at the time, that would be physical
hardware controls that were on the device.
It was sometimes a mapping problem moving between those
two sets for users.
And users also want to have a safe form of the navigation.
They wanted to know that the affordances or the controls
that they would use would be able to keep them within the
app that they were currently viewing.
Users were incredibly frustrated when they would
press a Back button and unexpectedly be jettisoned
from an app.
That's back to our bag of activities from before.
And then finally-- quick, obvious--
task switching was super important to them.
So we wanted to address that.
So we added two controls in Honeycomb and ICS to cover
those issues.
Up was looking at those first three issues.
The upper left corner, the inside-outside problem, and
the predictability of remaining within the
application, that safety guarantee.
And Recents was our way of taking that question of task
switching and making it dead obvious for the user.
So I'll goes into detail on both of these, first Up.
Up is structural navigation.
We've hit that point a couple of times today,
but I'll hit it again.
It's going to keep you in the app.
When you're at the top of the app, you don't even see it
because it's all about navigating in the app.
You're at the top.
There's no further to go.
It's completely independent of the task state.
So all those examples that I showed before of how the task
stack builds, your behavior of Up isn't affected by what's on
that task stack.
It's based entirely upon the relationships between the
different activities that you've constructed in your
app, the right parent/child
relationships that exist there.
It can alter the task stack as a side effect, but it's not
dependent upon it.
And then as a result, Up is not Back.
They sometimes will have the same effect for the user.
But they behave differently.
And there are a couple of critical cases where they're
actually quite different.
So let's dive into those.
So the first is when you're doing a browsing session.
And you're going to Related Views.
So an example here that we'll use is, I've gone into the
Play store.
I'm looking at a list of books.
Maybe it's the featured books.
And I pick a book that I want to view more details about.
And I go and I see that Book Details screen.
Now, part of a lot of store experiences is that part of
the item's display will give you a list of
related content items--
you know, users also liked--
that might show other books.
And when you browse to that and you click on that, we give
you another Book Details activity.
And now, we've got two Book Details activity.
The same type of activity, but two different instances of it
get built onto the task stack.
And now obviously, this can extend from there.
So the question becomes, Back will do one thing.
Back will unwind you through that browsing history.
I was looking at this book.
I went and looked at a related book.
Now I'd like to come back to that first book.
Up is structural navigation.
Up gives you the ability to bypass that intermediate state
and return up to that original list.
Now, that may not seem like that big a deal
for this short example.
But imagine browser sessions that could get quite lengthy.
I might go from book to book to book to
book to book to book.
And then in the old school, I could go Back to Back to Back
to Back to Back, to Back to Back.
Up lets you skip all that and just jump
right up to the list.
The second instance where Back and Up differ critically is
when you have a task that's being built up from multiple
applications.
And so I'll go through one here.
I'll start at Home.
I'll go into YouTube.
I'm browsing a list of YouTube videos.
I'll pick one out, and I'll watch it.
And then I'll elect to share it over Gmail.
So the Gmail Compose activity comes to the
front of the task stack.
So from here, Back is going to do the natural thing.
If I decide I don't really want to share that cat video
with my friend, Back gets me out of that context, takes me
back to the lovely cat video.
But if instead I wanted to remain within Gmail--
maybe the fact of firing up that Compose reminded me of
something else I needed to do--
the Up lets me stay inside.
And, in fact, it'll take me to a higher level activity that
wasn't in the task stack at any point.
This is going to graduate me up to the Conversation List
and the inbox that's associated with it.
And a couple of critical things happen here.
We add that activity.
We finish the Compose activity.
That one's gone.
And we split the task.
So we have one task, our old YouTube task, now sans that
useless Gmail Compose activity.
And we have a new task, the Gmail task focused on the
Conversation List.
And we've also carried along Home's Launcher
activity for the ride.
So that if I'm at the Conversation List and now I
hit Back, I'll actually wind up back at Home.
Recents is actually pretty straightforward.
It behaves the same as it did for that hidden function way
back in [? Android .1 ?].
But what we've significantly changed in Honeycomb was to
just give the user a much cleaner interaction with it.
We introduced a dedicated button in the system or in the
navigation area.
It brings the entire task stack forward.
And we just added a lot of detail that helps the user
make that decision.
Instead of just getting the name and the app icon, we're
now giving the user those plus a screen shot of the topmost
activity in that task stack.
Which is helpful for both identifying--
where's that task I'm trying to get back to?
Oh, it's this map.
Yeah, it's that map.
As well as orienting the user for the switch.
The user's already remembering the context that they're going
to be going into even before that animation completes.
So it's a much less jarring transition for the user, which
made it much better.
Finally, we're delivering on that great multitasking story
that we always knew Android was capable of supporting.
ADAM POWELL: So coming back to our diagram from before, when
I choose Task B from Recents here, what actually happens?
So when you bring Task B to the top using the Recents UI,
Recents is starting the root activity of Task
B with these flags.
Remember, when we start the root activity of a task, it
brings it forward.
So we've already covered what New Task does but what about
this Task on Home thing?
So this was a new flag that we added in Honeycomb.
And this is the flag that allows us to bring Launcher
along for the ride, like Rich mentioned.
To keep this more consistent state that is more predictable
for users when they switch around.
So after that switch, Task B is now on top with Home
immediately beneath it.
And if I back through Gmail, I'll end up on Home no matter
how I got into Gmail, just as I expect.
RICHARD FULCHER: So one last visit to the timeline.
So we talked about Honeycomb.
We talked about ICS.
And today, we are proud to announce--
nothing else new.
We haven't changed it.
[APPLAUSE]
RICHARD FULCHER: You're welcome.
ADAM POWELL: So now you know a little bit more of the history
of how we got where we are here.
And it's important to remember that it's really easy to find
these local maxima for your app's experiences and sort of
implement special functionality
to make that happen.
But following system conventions makes your app
more intuitive to people that already know how other apps
behave in the system, when those apps follow those
conventions too.
But as you've already seen, the Android framework has a
lot of intricate options and opportunities to do things
differently.
So how do we actually implement all these guidelines
that we're talking about here?
Well, Back is really easy.
We just leave it alone.
Let it go ahead and unwind fragment transactions or
finish activities just as it does by default.
And let it move to the previous activity in the task,
so on and so forth.
But what about this Up thing?
So we talked before about how Up can switch tasks.
When you deliberately task switch, here's how you bring
Launcher along for the ride the way that Recents does.
And we talked about this a little bit.
But this really helps reinforce this hub and spoke
model of tasks for the users with Launcher as this hub.
Each one of the tasks kind of splits
out, forming the spokes.
When a task is fully replaced, then traversing back through a
synthetic stack and returning to the previous task instead
feels really, really weird.
So landing at Home reinforces structure.
So when we implement Up, we need to fully replace the task
that's there.
Again, because of this new tabs problem that we talked
about before.
By replacing the task, we're effectively sort of faking
history, though.
And some of you may be wondering, why would you
really want to do that?
Why not just have Back be Back?
Why are you lying to the users?
RICHARD FULCHER: Yeah, there are actually a few different
cases where the activity that's the logical parent may
or may not be something that's already on that task stack.
So we'll see this in more detail when we talk about
widgets and notifications in just a little bit.
And they actually behave very similarly
to Up in that regard.
ADAM POWELL: So that means that another ability that
we'll need is being able to replace an existing task.
So for example, imagine that the user's at Home with tasks
they've already built up for Gmail, Talk, and YouTube.
That's A, B, and C as listed on the slide here.
So from Home, the user navigates into
Gmail from its widget.
So this needs to be sort of a deep link in there.
Then it's the same story for Up when you're composing from
a different task, like in our previous example.
So using that widget will make the old task
state of Gmail invalid.
So we use this Clear Task flag, since we don't want
leftover state or duplicate Gmail tasks anywhere in the
global activities stack.
So as much as systems programmers really enjoy
packing arrays full of values and getting exact flag
combinations right through all of that, we really wanted to
provide a little bit of a nicer interface on top of that
to help get the details right.
So in both the Jellybean framework and in the support
library, TaskStackBuilder is that nicer interface.
So it can determine the full synthetic task stack that
you'll need based on the structural hierarchy from the
declared parent activities in your manifest, as well as
generate some pending intents for notifications and launcher
widgets when you need those.
We've got some code examples in the SDK that you can take a
look at for more details.
So how do we pull all these little pieces together to
implement Up?
Well, the good news is that in Jellybean, you don't have to.
It's all completely done for you.
Just give us the metadata in your manifest about the parent
activities.
And we'll take care of everything else.
So sometimes you need to specify some other intent
extras to those activities along the way.
For example, if one of your parent activities is a
category view and you need to know what category you're
viewing, you may express that as some sort
of an intent extra.
So in that case, you can override an activity method
and edit the intents in the TaskStackBuilder that's being
used under the hoods whenever it's needed.
So we'll also be bringing this to the AppCompat component of
the support library that we talked about yesterday in the
multi-versioning Android UI session, if
any of you were there.
RICHARD FULCHER: So the last major topic we need to cover
as far as navigation goes is widgets and notifications.
And these are both examples of a pattern we internally call
deep links.
These are things that let you bypass certain intro screens
in an app and target an activity that's deeper within
its hierarchy.
Widgets are pretty straightforward in the sense
that we know that those are always going to be new tasks.
You're always firing them from Home.
They're effectively acting as a Launcher activity.
They can apply task affinity as Adam talked about before.
But they're not that complex.
Notifications are a little trickier, so
we'll cover those last.
So here's just a quick example showing widgets.
So back to the old format, we've got the task stack and
the screens building up.
So from Home, I have a Gmail widget on my Home screen.
And I see a conversation within my inbox,
and I touch on that.
That lets you bypass the Conversation List screen, and
you navigate directly to the Conversation View.
But actually representing that screen in the
task stack is valuable.
Keeping that Conversation List around matters a lot.
It doesn't matter so much right now, like
right at this instant.
But where it matters a lot to the user is when they've been
inside Gmail for awhile.
They come in.
They read that message.
They read several other conversations past that.
And they've been in the app for a little while,
and they hit Back.
They're not aware that instant that, oh, the doorway I used
to enter was the widget.
So of course, it's going to kick me out to Home.
It's a surprising change if we were to just do that.
So we don't.
When the widget calls into the Conversation View, you can add
the Conversation List activity to the task stack.
That way when the user hits Up or Back, they're being kept
within the application.
If they really wanted to go Home, well, they could have
hit Home to begin with.
Or they could just hit Back again.
Notifications--
so a common flow for notifications
is I'm in one app.
So I start Home.
I launch again into Gmail.
I'm reading a conversation.
And in comes a notification.
I pull down the shade.
No activity.
No task stack change there.
That's just purely local.
And I've got a new notification from Talk.
A new message has come in, and I want to read that.
So I tap that notification.
And now we have the Talk activity to deal with.
And we're going to go straight to the Chat View.
Again, we're bypassing that Friends chat or the Friends
List that we'd seen in the earlier examples.
The question here is, what should the relationship
between that new activity and the prior task be?
Is this going to be a new task?
Is this just something that we put on top of
the previous task?
ADAM POWELL: So knowing what you now know about how all of
this fits together and what we found our users' expectations
were, not just right immediately but several hours
later, this really doesn't work.
We can't just hop back to the previous task.
This is something that became muscle memory for a lot of
users over time in previous versions of Android.
You answer a notification.
You do whatever you need to do there.
And then you hit Back.
And then you continue doing what you're doing.
So this actually caused us a lot of problems.
It was trivially easy to create this super confusing
state that users wouldn't discover
until much, much later.
So something really needed to change.
So the problem that it created was that the task stack was no
longer predictable.
If you last opened Gmail through a notification, hours
or days later your Gmail task state would be very different
than if you had opened it through the front door.
So as you go switching back and forth between tasks just
as you use your device, then this gets
really massively confusing.
And users just started attributing this to Android
being dumb or confusing, one thing or another.
So the idea of Back staying within the current task is
something that we weren't willing to give up.
There's a ton of psychology behind maintaining that
expectation in each task.
Context switches are very, very powerful.
People remember a lot about an old context
when they switch back.
And then they forget about the context that
they switched from.
So have you ever walk through a doorway into another room
and suddenly forgotten what you were doing?
You're not alone in this.
RICHARD FULCHER: Yeah, there was actually a pretty
well-known psych study that covered this exact topic that
got some play in the popular press, so you may
have heard about it.
And it looked at what happens when participants were asked
to engage in memory tests while they were walking
through doorways.
And they did it in both physical and in virtual
environments.
Spoiler alert, people forgot stuff when they walked through
the doorway.
So we didn't want our users to suffer the same fate when they
did the task switch.
I have to just call out in this quote.
I love this little bit that talks
about episodes of activity.
I read this quote--
I swear I didn't doctor it.
And that just screams task stack to me when I look at it.
ADAM POWELL: OK, so we have all of
these crazy flags available.
Can we cheat a little bit?
Can we really keep that flow of just hitting Back and going
right back to where we wanted to be?
So here's one possible trick.
We could start a new task but don't set the
Task on Home flag.
Well, this trick will make the Back button work
for this use case.
But the rest of the existing task still ends up being there
to mash back through.
And that's really not very great.
And if we add the Clear Task flag, then it really leaves us
with a bogus state.
Back becomes unpredictable either way.
If you clear the task, then returning to that task later
from Recents means you Back right back into Home again.
If you don't, then you have to Back through the rest of the
task before you get back to the previous task.
And you still lost the quick Back.
So that's not going to work.
So, OK, what if we really, really cheat?
You can try a really dirty trick here.
But this will leave this orphaned activity hanging
around that you won't actually be able to get back to in any
sort of a discoverable way.
If you answered a notification and then wrote half of a
message in Talk, then you're basically hosed if you leave
and want to come back.
And then you get into this matter of, OK, well, we could
go ahead and make everyone try and save drafts for everything
that you're doing one thing or another.
But we really didn't think it was a good idea to expect
developers or even want them to take on this much
duplication in special casing.
So notifications are supposed to be this first-class thing
in Android.
But just as a note, this trick actually is useful in some
other cases.
So if you have a deliberately orphaned summary dialogue or a
screen that shows more than a notification can on its own
but it's really just an extension of that notification
before you jump into the content, then this can be
really useful.
Calendar reminders are one place where we do this in the
base Android system.
When you get a pop up that shows multiple reminders that
have been collapsed.
So the solution that we finally settled on was that we
treat notifications just like we treat widgets in Up.
So that means that navigating into an app from a
notification replaces the target task entirely with that
same sort of deep link synthetic task stack that we
use for Up and for widgets.
So conceptually that means notifications have become a
shortcut for going Home, clearing out the current task
state by swiping away in Recents, opening the app, and
then just following the shortest path down the UI to
get to the content that you actually cared about.
But you're doing it all in one step.
So TaskStackBuilder gives you an easy way
to accomplish this.
So the implications of this are that, yeah, we really did
just lose that case.
You can't just use Back from answering a notification to
switch to the previous task anymore.
And that is kind of unfortunate.
But the good news is that since we've elevated Recents
to this first-class element that's right there on the
navigation bar all the time, then getting back to the last
thing that you were doing is very simple.
So the most recent task is always sorted
closest to the button.
So it's a very quick two taps to get back to the previous
thing that you were doing.
But more importantly, we realized from all the user
testing that it was less important to keep this quick
Back than it was not to surprise people with a bogus
task state much, much later down the road.
And to reinforce this idea of the task switch as we go back
and forth, we really try and tell the story with animation
in Jellybean.
RICHARD FULCHER: OK, so wrapping up.
Three things that I'd love you to take
away from this session.
The first is, think about the structure of your app early on
in your planning process.
The first talk this morning did a really good job of
illustrating how you think about what you want your app
to achieve.
What is the app in and of itself?
Don't be the bag of activities.
You don't have to be like this exact hierarchy.
There are a lot of different hierarchies
that are out there.
And there are a lot of apps you can look at as
exemplars of that.
You can be broad or narrow.
You could be shallow or deep.
You could be balanced or imbalanced in your hierarchy.
Let the activities and their relationships drive the
structure that you try to implement.
ADAM POWELL: So another thing that we'd like you to do is
don't just test your app navigation in isolation.
It's very, very easy when you're in an intense debugging
session to just make some quick changes, push the new
APK to your device, test it out really quick just within
your app that just launched from your debugger,
and say, OK, great.
It works.
We're done.
The thing is is that as soon as you have any sort of
sophisticated navigation in your application, this doesn't
actually exercise all of the different cases that users are
going to run into.
Make sure that you test all of the navigation in
and out of your app.
That's the notifications, widgets, and any sort of
intent fulfillment that happens from other
applications.
If your application can act as a viewer for
certain types of content.
If other applications can share to your app.
Make sure that you test all of those things too.
And most importantly, go ahead and dogfood your own
application, too.
Test it over a number of days.
See how it interacts with other
applications on the system.
And make sure that it's behaving consistently with the
other applications that people are going to be
using day to day.
RICHARD FULCHER: And then finally, why
are we doing this?
Why do I care about this so much?
Users always win.
Your users are always win when apps behave consistently.
You've heard the consistency point a number of times today.
It's important.
There's no need for a user to learn how to navigate your
application if you're doing the standard, doing the
consistent thing.
They can take the knowledge they've learned in one app and
apply it to yours directly.
You also don't have to spend time introducing a tutorial,
teaching the users how to use your navigation.
It gives the users a sense of mastery.
That ability to take the knowledge learned in one place
and apply it into a different context is what
contributes to that.
And your app is the beneficiary of that.
The user gets all these positive associations with it.
Adam often talks about this being--
kind of one way that users express this is they say, oh
that app's intuitive.
It's just doing the things they would expect to do
without having had to learn what the app is
asking them to do.
And it lets the users concentrate on the key things
your app is trying to deliver.
And then finally, it makes the whole experience feel better
to the users.
Your app, all the apps, all the devices.
We're working really hard to try to bring consistency to
all of the Google applications.
And hopefully, you'll notice in Jellybean, we've made a
tremendous number of improvements when it comes to
using navigation consistently.
I'm sure there's a couple that we've missed.
We're working on it.
ADAM POWELL: We couldn't have missed any, Rich.
I don't think that's possible.
RICHARD FULCHER: Yeah.
That's why they pay us the medium buck.
We've covered a lot today.
If you want to go back and review any of this material--
I've tried to concentrate on the why's.
You know, why did we come to these
decisions that we've made?
But if you just need the guidelines, they're in the
design guide.
If you go to the navigation pattern there,
you can review it.
It's got a lot of this content or other related examples that
you can go through again.
And with that, thank you very much.
[APPLAUSE]
RICHARD FULCHER: And we have time for questions.
AUDIENCE: Hi.
Do you have some advice for tools to draw diagrams or some
tools like UML to create the navigation diagrams?
RICHARD FULCHER: Yeah, that's a good question.
So we use a lot of different tools within the team.
I happen to use Illustrator just because I do navigation
and wire framing at the same time.
We have a number of designers who use OmniGraffle to do
quick connections.
I've worked at places where we've used
PowerPoint or Visio.
I'm dating myself.
Pen and paper is usually good enough, too, oftentimes if the
app just isn't that large.
I don't know if you have anything to add.
No.
ADAM POWELL: No, I think that, that pretty well covers.
RICHARD FULCHER: Great.
AUDIENCE: Thank you.
RICHARD FULCHER: Thanks.
AUDIENCE: Hi.
I have a question related to how the Back navigation is
supposed to be working when you're having a
list view on a tablet.
So on a tablet, for example, you have a list view.
And then you're showing it beside it in a separate
fragment the icon, like the item of the list.
And then on the list, you select the next one and then
the next one and the display shows.
What's the expected behavior?
Is there an expected behavior of the Back button to go and
go back and show me those other list
items that showed before?
RICHARD FULCHER: No.
The expectation is more that Back will operate at the level
of the entire screen.
So any internal--
AUDIENCE: So then the Back button basically behaves the
same as the app button.
RICHARD FULCHER: Again, but it depends on how
you entered it, yes.
AUDIENCE: Yeah, but, if I enter into the list here and
then go through the list, the Back button doesn't actually
do the expected back operation in terms of I went back to
that list item I saw before.
And that's expected?
RICHARD FULCHER: That's expected.
Another example of this would be tabs.
Back doesn't operate across tab views.
So if I come in and I'm browsing even on the I/O app--
I'm browsing through the top level--
Back isn't going to take me to the prior tab.
It's just going to treat that all as state--
ADAM POWELL: Yeah, that's right.
There's a few of these constructs that we have.
And just like you mentioned, tabs are one of them, where we
really distinguish between what types of actions do or
don't create navigation history.
And tabs are definitely one that we decided do not create
navigation history.
And choosing different list items to focus on in a
two-pane UI is another one of those very analogous sort of
actions that doesn't itself create navigation history.
AUDIENCE: Can you update that in the design guide?
Because it's not explicit from there.
And I was thinking that it actually should be doing the
actual Back thing.
And therefore implemented that in my app and
that's how it works.
I find that, for example, the Gmail app and all these apps,
they don't do that.
So I'm kind of contemplating to ripping it out again.
So you're saying that that is the expected behavior?
Maybe update the design guide.
That would be great.
RICHARD FULCHER: Yep, I think we can add that.
We're actually trying to add more and more depth to our
tablet support in the design guide.
So that's a good call-out.
Thank you.
ADAM POWELL: Yeah, so I guess we should add that same note
that we have about tabs to the left pane list.
AUDIENCE: So with the move from Gingerbread to Honeycomb
and ICS, you guys did away with the option menu, which
had a visual interface and a nice grid layout, to the
overflow menu, which is a big giant list of text.
RICHARD FULCHER: That's right.
AUDIENCE: Now, some of us prefer to have a visual
interface for people rather than just a
bunch of text to read.
And so before I and others start getting into coming up
with our own ideas of how that menu should work, I'm curious
if you guys have had any discussion and ideas on how to
integrate visual pieces into the overflow menu.
RICHARD FULCHER: Yeah, I guess my initial response to that
would be that the old menu would give you visibility for
five options and then like a More button, which would then
fall through to a text-only display at that point.
So when we designed the Action Bar, and particularly in ICS
when we brought it to phone, we gave you the
split Action Bar.
So you could still have five visible targets within your
application, if you wanted to.
And then kick over to the text overflow.
So we tried to, in the Action Bar, give you a similar amount
of graphical targets that you can give it.
We don't have any plans right now to introduce graphics into
the action overflow itself, though.
ADAM POWELL: Yeah, the idea was really to reduce the
navigation depth that the user had to traverse by one.
So everything that would have appeared in that menu panel,
we're now trying to bring on screen just by default.
So that anything that really needs visual navigation should
be there present, that is a little bit more discoverable
than something that's hidden behind the Menu button.
So in that case we're positioning the overflow menu
as something that really is for some of those hidden
options that are not frequent, important, or typical.
RICHARD FULCHER: Thank you.
AUDIENCE: So this is regarding the Back button.
If I had to navigate a page to an activity from a dialogue.
And I hit the Back button.
I go through the stack of dialogues that
I didn't want to.
As a user, I would expect Back to go to the previous
activity, without hitting all the dialogues that I had to go
to the next activity.
So is this behavior remaining, or--
ADAM POWELL: So which?
I'm sorry.
I guess I don't quite understand.
So you had a case where you had multiple nested dialogues
that were created?
AUDIENCE: Yeah, I had two dialogues.
Which was important to make some decisions before we go to
the next activity.
ADAM POWELL: Oh, I see.
AUDIENCE: When I hit the Back button I would actually expect
to go to the previous activity rather than [? fall on ?] all
the dialogues.
ADAM POWELL: Right.
So what the system alert dialogues do by default is
whenever you choose one of those options in the bottom
bar from the dialogue, we actually dismiss the dialogue
as part of navigating to the next thing.
So that way, there's no extra states still left over.
If you're ending up with a lot of stacked dialogues one on
top of another, then that's probably a situation that you
want to avoid getting into upfront, rather than worrying
about how to clean it up after the fact.
So when you've already made a decision from a dialogue, that
should be about it for the dialogue.
So go ahead and dismiss it and let the next thing take over.
RICHARD FULCHER: And the behavior you're describing
would be kind of strange and jarring, I agree.
We would want to not take you back to the dialogue and take
you back to the root activity underneath it.
ADAM POWELL: Yeah, absolutely.
RICHARD FULCHER: Yes.
AUDIENCE: Thank you.
RICHARD FULCHER: Sure.
AUDIENCE: Hi, I'm constantly having to explain to my
parents that there aren't actually two Back buttons on
the screen.
RICHARD FULCHER: That's not true.
There's two.
There's a Back and an Up.
AUDIENCE: Are there any plans to make the Up button face up?
ADAM POWELL: So that's kind of interesting.
We actually started--
oh.
Lots of people like this.
[APPLAUSE]
ADAM POWELL: So believe it or not, this is actually what it
looks like in the first release of Honeycomb.
We actually had a little glyph that pointed
up and to the left.
And as it turned out, because of just the way that the
spacing all works out, nobody saw it.
It was effectively invisible.
It almost looked like a little shaded corner.
We played around with a lot of different
glyphs to try it out.
And in our user testing, we just found that something a
lot more in your face that we ended up using as that sort of
left-facing chevron was way more effective in terms of
just how it read to the majority of the people that we
user-tested with.
RICHARD FULCHER: Yeah, the other thing
I'll add is like Up--
we think about Up all the time.
Hierarchy isn't an odd concept for most of our consumers.
They don't view apps that way.
And even though we're kind of expressing it as the Up
button-- that's what we call it--
they think of it as Back in some sense.
Back in the app versus this other Back.
AUDIENCE: Thanks, guys.
RICHARD FULCHER: Sure, thank you.
AUDIENCE: So the Up button in the new Google+ app opens up
that little slide app menu on the side.
RICHARD FULCHER: Ah, we knew this was coming.
Have you used YouTube?
AUDIENCE: I haven't checked at YouTube.
RICHARD FULCHER: Same thing.
AUDIENCE: All right.
So is that going to be a standard or--
ADAM POWELL: Yeah, so this is basically the next problem
that Rich and I are going to tackle after everything from
I/O settles down here.
This idea of the [? nab ?] drawer is something that has
become really popular in the community.
And we want to make sure that we have some really strong
guidelines and support around it.
And I think that out of some of the different ones that are
around, I think that YouTube probably meets most of the
direction that we're moving toward for that.
And part of that is just because of the way that it
implements the direct manipulation is you can
actually grab hold of the content and slide it over,
rather than only relying on the Up button.
But in the case of something like Google+, the Up button
actually is semantically correct as well.
Because it's something where you're saying, I want to
perform some navigation one level up in the hierarchy from
where I currently am.
RICHARD FULCHER: As far as if you're thinking about doing
for your apps, the things I would keep in mind-- because I
think this will track the guidance
we'll give most closely--
think of it as almost an alternate visualization of the
drop-down that you can get as a view changer as well.
It's part of the local state of that topmost activity.
It means that where we would never have an Up button before
on that top-most screen, we gave you an affordance that
still looks like Up that pulls this drawer out.
And that's in addition to any kind of gestural affordance.
You know, an edge swipe that you'd like to introduce that
panel with.
AUDIENCE: Sorry, are there are plans to make this native?
ADAM POWELL: I think that we've talked about doing
something in the support library for it.
Of course, the problem with adding some core navigation
pattern like this natively is that how many people are going
to use it for the next to 6 to 18 months.
So I think that we're probably targeting something closer to
the support library for it.
RICHARD FULCHER: So we don't have
anything to announce today.
But it's definitely something we're looking at.
And just one last point I'll throw in on that--
if that drawer is open, then the behavior of Back should
just clearly be to cancel that drawer and not take the
navigation.
So it's a state [? within ?] the activity.
AUDIENCE: [INAUDIBLE]
go Back to [INAUDIBLE].
Why is it not [? back at the ?]
Menu icon or something?
RICHARD FULCHER: It could be decorated differently at some
point, but for now, the affordance we have
available is Up.
So that's what we're using.
AUDIENCE: [INAUDIBLE] don't go Up just [INAUDIBLE].
RICHARD FULCHER: I think you don't physically move up in
terms of the options you're presenting to the user.
They are upward.
This is a magic hierarchy.
ADAM POWELL: Right, right.
And in terms of the idea of Back closing the drawer, I
would think of that as any of the other sort of modal states
that you can get into.
It's the same as the IME.
It's the same as any of the action modes that you can pull
down for editing and so on and so forth.
AUDIENCE: Thank you.
RICHARD FULCHER: Thanks.
AUDIENCE: Hi.
A couple times in your presentation, you talked about
tasks being in a bogus state--
one being you're in Gmail.
You get a notification for a text message.
The text message shows up.
And apparently, a text message without a corresponding
Conversation View underneath it is somehow a bogus state.
Could you elaborate what's bogus about that?
ADAM POWELL: Yeah.
So the idea there is that if you have the detail view of a
particular text message, then if you don't have the
Conversation List above it, then the problem isn't right
there when you're working with it.
The problem is, OK, you get another notification.
You answer it.
You press Home.
You leave.
One thing or another.
And then you actually come back into the SMS app or the
Talk app sometime later through Recents.
And at that point, you've crossed through the doorway.
And that's where you want the Back button's behavior to be
somewhat consistent with your expectations.
And if you start that activity without having a Conversation
List below it, then what that means is that the Back button
is going to finish that activity.
And then you're going to land back at Home.
And then that ends up being inconsistent with expectations
that the user would have, depending on if they got into
it from a different way, again hours or even days earlier.
AUDIENCE: So switching back to it from Recents
after you left it.
ADAM POWELL: Yeah.
RICHARD FULCHER: Or from another notification.
Like any mechanism at that point, it's going to have I
guess what I'd describe as an incomplete state above it.
It's not invalid.
It just means that once I try to exit it, I'm going to wind
up somewhere unexpected.
ADAM POWELL: This is one of the things that we found
really contributed to a lot of users feeling like Back was
unpredictable in Android as a whole.
It wasn't a matter of what it did right away.
It was a matter of state that got created a really long time
ago that wasn't really intentional.
But as soon as you come back to it, then suddenly
everything's kind of goofed up.
And it's right after you did another task switch.
You're trying to do something where your
expectations were one way.
Suddenly, you get flustered.
And it's like, oh, this stupid phone.
I hate it.
AUDIENCE: Don't they feel frustrated after responding to
a notification, hitting Back, and it doesn't go back to
where they were?
RICHARD FULCHER: If they're really familiar with that old
behavior, yes, there's some kind of muscle learning they
have to do to shift that behavior to Recents.
But we still think we're supporting it.
ADAM POWELL: We've found that in practice in our own
dogfooding with Googlers, who, by the way, are probably the
most critical audience for issues like this.
We had a lot of initial frustration in
the first few days.
And then it really trailed off after that, once you started
training yourself.
I know that I was the same way.
Matias isn't around here, but I actually locked him in a
conference room for the better part of an afternoon trying to
convince him that, no, we had to find some way
to keep this behavior.
And in the end, I was not only convinced that this was the
right way to go.
But that once I actually started using it this way,
once it's in action, you start switching over to Recents.
And it becomes extremely natural to the point where you
pick up an older device and you're like,
this is entirely wrong.
So a lot of it really is just a matter of habituation.
AUDIENCE: Thanks.
AUDIENCE: I have a couple of questions.
You mentioned going up through the stack and then basically
hitting the Up and going all the way,
bypassing the middle ones.
And you were showing the task stack as basically having
those vanish.
But how do you make that happen?
Since conceptually, you could also be getting back to that
Home screen just by following other navigation which would
put it on the top with all those back in there.
ADAM POWELL: Yes, there's a few ways to do this.
The first is that, well, in Jellybean and forward, there's
actually a specific method that does this.
Or, wait, no, that's--
never mind.
That's a different case.
So as you're jumping up for that type of navigation,
essentially you have this other flag that's called Flag
Activity Clear Top.
And it means that I'm launching into this task, but
clear everything else off the top if this same target
activity already exists in my task stack.
So we've used this in the past to really try and prevent
cycles in navigation.
And that's exactly what it does in this case, as well.
AUDIENCE: OK, and somewhat similar.
We respond to a number of deep links we capture.
You've probably formatted URLs, etc.
And so if we come in for item A, and then we stay in the app
for a little bit, and then we go back out.
And we come in again following another link for item B. And
we go off a ways.
So our stack for our task currently has
items A and B on it.
And so those are handled by the same activity, just
different data.
Now we get a deep link again for item A, but it just brings
our activity to the front showing item B.
ADAM POWELL: Yes.
That's that task switching behavior that we described
when it matches the root intent.
So I'm guessing that your data URI is an exact match for what
A was in that particular case.
So that's definitely why you're seeing that behavior.
AUDIENCE: Actually, it's not.
ADAM POWELL: It's not?
AUDIENCE: Or sorry, it's an exact match for item A, yes.
ADAM POWELL: Yeah, yeah.
So if it's an exact match for item A, that's why it's
bringing that task forward, even though you've got other
tasks still on top of it.
So generally, it sounds like this means that your activity
is acting as a viewer, sort of as a helper for another app.
Is that correct?
AUDIENCE: Actually-- well, I'm with IMDb.
So basically, if somebody follows a link that has been
shared to them, or whatever, or a title or a
celebrity or whatever.
ADAM POWELL: So it's basically a web link that you've
registered an HTTP URI Intent Filter for?
AUDIENCE: Right.
ADAM POWELL: Excellent.
So generally, the way that we do this is that that doesn't
actually launch a new task.
So that shouldn't be launching a new task to begin with.
Because it's conceptually part of exactly what the user was
doing in whatever task linked them to it.
So that's our case before, where we were doing the share
YouTube video off to Gmail.
Where in that case, the detail view from the IMDb app would
be launching as an activity on the current task already.
So in that case, you wouldn't be creating this other state
that you've still got left here.
Now, there's another flag which is kind of important to
be aware of for this that is useful when
linking out to this.
But sometimes when you're just handling an HTTP URI, it's not
really feasible to be able to set it.
But that's Flag Activity Clear When Task Reset.
So it's kind of a mouthful.
But what that does is that makes a distinction on whether
or not the user comes back.
So say they were in the browser.
So they're in the browser.
They hit a link to an IMDb page, and it
brings up the app instead.
So it's launched that on the browser's activities stack.
Now ideally, if you're linking them from something else and
using this as sort of a viewer, you could
also set this flag.
And then that means that if the user later comes in
through Recents, then, OK, it's exactly
the same as it was.
The IMDb activity is still on top.
But in the case where the user relaunches from the Launcher
itself, they press Browser.
They want to get browser.
They don't want to get the IMDb app.
So that actually acts as that task reset at that point.
And any cut points where that flag was specified, all those
tasks get finished and are cleared off.
But that aside, the general idea is that you really want
to be trying to launch within the current task of whatever
is linking into your activity.
So that that way you don't end up creating your own task
stack of a whole ton of extra history there.
AUDIENCE: OK.
On certain links, then, we used the clear top.
But I'm not sure that the activity that actually
responds to that intent actually gets dismissed and
this other fragment activity gets loaded on top.
ADAM POWELL: Oh, I see.
So this is when you're navigating Up from that other
detail view from before, or--
AUDIENCE: No, it's actually in order to cover some of the
other cases, we had to have basically an activity chooser
activity that handles the intent coming in.
And then goes off to fragment activities that actually load
everything else.
So it's a little complicated.
ADAM POWELL: I see.
So you've essentially got a detail activity that holds a
bunch of other pieces then?
RICHARD FULCHER: We're over our time.
So let's just cut the questions on the mic off.
Please feel free to come up.
And then everybody else can go.
ADAM POWELL: Yeah, definitely.
If we get kicked out of this room, then let's talk more
outside, too.
RICHARD FULCHER: Thanks.