Tip:
Highlight text to annotate it
X
>>> Ladies and gentlemen, please welcome Bruno Oliveira and Adam Powell.
[ Applause ] >>Bruno Oliveira: My name is Bruno Oliveira,
and I work in the Android Developer Relations team. I'm based in South America, and my mission
is to work with developers to get very high-quality applications on Google Play.
>>Adam Powell: And I'm Adam Powell. I work in Mountain View, California, on the Android
Framework team. >>Bruno Oliveira: All right. Thank you very
much for coming to our session. So we're going to talk about building user
interfaces that work across several platform versions.
So, by the way, if I want to mention this session on the social media, those are the
hashtags. Before I begin, just a quick show of hands.
How many of you are developing Android applications? Oh, duh.
How many of you are developing Android applications that work only on a single platform release,
say, only for Jelly Bean or only for Ice Cream Sandwich?
All right. A few of you. How many of you are targeting, let's say, two or three major platform
releases. Okay. That's more of you.
>>Adam Powell: That's great. Hmm, that's really too easy, though. Who's
developing all the way back to, say, Cupcake, maybe even earlier. Anyone? Wow, that's a
lot of hands. >>Bruno Oliveira: Very nice.
>>Adam Powell: That's great. So why is this important?
>>Bruno Oliveira: That's a great question. Why is this so important? Why can't I care
only about the latest version of Android? Adam, I don't know, what do you think?
>>Adam Powell: Maybe there are other versions out there.
>>Bruno Oliveira: Others versions? Really just show of hands, who has a device with
the latest version of Android. Oh, everybody. [ Laughter ]
>>Bruno Oliveira: Told you. >>Adam Powell: We're set to go.
>>Bruno Oliveira: Everybody has -- >>Adam Powell: Everybody can go home; right?
Yeah, I think that we might actually have a problem with our sampling.
>>Bruno Oliveira: Our sample is bad you think? >>Adam Powell: Well, I think it's biased just
a little bit. A little bit different.
Okay. So who has parents running an Ice Cream Sandwich or newer device. Anyone? Oh, wow.
That's more than I expected, actually. Gingerbread moms, anyone? Yes.
>>Bruno Oliveira: Froyo moms? All right.
>>Adam Powell: Okay. >>Bruno Oliveira: So why can't I care only
about the latest version of Android; right? So yeah, that's definitely a better sampling
method. If you've been developing for Android for more than one day, chances are you're
familiar with this particular pie chart; right. As you can see, the world is not exactly made
of ice cream out there yet. So any application that's seriously considering targeting most
users should work on at least Froyo, Gingerbread, Ice Cream Sandwich, and Jelly Bean. But there
are developers, and they are among us, who look at this chart and they are scared. And
they say that's difficult. One thing I learned in the last 48 hours is
that jumping from a moving Zeppelin and landing on top of Moscone center is difficult. That
stuff is easy. [ Laughter ]
>>Adam Powell: Right. This is actually fairly easy to do by comparison.
We're going to show you how just to make sure that your user interface adapts correctly
across several platform versions. It doesn't involve any extreme sports. Don't worry.
>>Bruno Oliveira: For those of you who don't like pie charts, don't worry. As you can see,
most of this presentation is not in fact a pie chart.
Enough philosophy for now. Let's start -- let's talk about some naive
approaches to multiversioning your Android user interface. It's worth mentioning that
most of the approaches we're going to mention here are all valid to some degree.
And the only -- our point is that they should not be taken to the extremes that we're going
to show you. So with that warning, let's move on to the
first naive approach. Some developers avoid evolution completely.
They just stick to the good old stuff, forget anything about the new stuff; right? It's
already an improvement over what we would have, say, 60 years ago. But then it looks
like their app is stuck inside. Because you open that up in Ice Cream Sandwich and then
it just looks exactly like it did on Cupcake or almost at least.
So, be sure, you can say, yeah, but that's because my app is consistent, consistency
is important. But that's only because it's consistently obsolete everywhere.
[ Laughter ] >>Bruno Oliveira: Needless to say, that's
not a great idea. Evolution is a must. Now, there are some -- moving on, there are
some developers that know evolution is a good thing. But they are somehow fascinated with
the concept of multiple APK and they think that that's a solution for everything, so
they have one for APK for Cupcake, one for Eclair, one for Froyo, and maybe one for that
odd device that your boss is going to be using. But, again, I'm not saying here that multiple
APK is a universally bad approach. All I'm saying is it should not be abused to the point
that you have one separate APK for each platform version. Right, Adam?
>>Adam Powell: That's right. This can really be a workable approach for handling the divide
between, say, Gingerbread and Ice Cream Sandwich, where we had a whole ton of changes in UX,
especially when holo came into the picture. But we really don't recommend getting too
much more granular than that outside of some serious edge cases.
You might consider, like, large versus small screen if certain business cases allow for
it. But, in general, you want to try and keep things mostly together.
>>Bruno Oliveira: Now, some developers know they should try and have one APK as much as
possible. But they still write fully separate layout and code for each version of Android.
While some degree of that is probably okay, if you have -- if you get to a point where
you have different layout and code for each major platform of Android, then you're probably
making things more complicated than you should. So we don't recommend going crazy with this.
Actually, we don't recommend going crazy at all in general.
>>Adam Powell: Right. So taken to an extreme, this really isn't much different than abusing
multi-APK. You're just cramming everything into the same package. You still have the
same level of duplication in practice that you have to maintain.
So when you split into separate resources and code paths for different versions, it's
important to be really tactical about it. So what are some ways that we can do that?
>>Bruno Oliveira: I'm glad you asked. So let's stop (indiscernible). So I think
at this point, we probably leveled up to a level 2 multiversioner. So let's go over some
basic multiversioning skills. There's a pretty common pattern called the parallel activity
pattern. It's a quick and easy way to launch a different activity depending on the platform
version. In this example here, we're detecting whether we are running ICS or above. If so,
we're launching this shiny, cool activity; right. If not, then we're launching this legacy
activity. Now, this is a good approach when your activity
really, really depends a lot on the newer platform features and you want to have a decent
fallback for the other versions. Now, this should only be used when you have to cross
a major platform boundary, like pre and post ICS. Because if you have too many branches
there, things can start getting complicated pretty fast.
Speaking about complications, sometimes when developers implement a certain feature on
multiple platform versions, they write separate classes that are mostly identical code except
for a few lines. Now, this is -- essentially, this gets you
to a situation where it's impossible to simultaneously maintain your code and your sanity. You have
to choose. So this is not a good idea.
Now, there is no shame in using an if. An if is a great thing. And there is no shame
in using it. You can do that and still be in good standing
with developer society. By the way, if you are worried that those
constants are going to break on the older platform versions because there was no such
thing as Gingerbread in Froyo; right? So great, that's exactly the sort of thing that you
should worry about. But in this case, it's okay, because they all get compiled to a pure
number. So it's not going to break in older versions.
>>Adam Powell: Specifically, these are the build dot OS SDK versions that you can refer
to. >>Bruno Oliveira: Exactly.
So our first advice is don't be afraid of if. Our second advice, that said, is be afraid
of if. If you suddenly start to see those code branches
get too big, then we probably need a better approach; right?
>>Adam Powell: Mm-hmm. >>Bruno Oliveira: This is what we're going
to see next. Let's talk about being lazy; right?
Laziness is probably one of the earliest human inventions. It probably even predates fire.
Human beings were being lazy long before they invented anything else.
All throughout history, it's been a solution to many of the world's toughest problems.
So this is one of those cases. So we're not going to use laziness itself.
We're going to use lazy loading. Adam, how can we use this kind of laziness
in our favor in this case. >>Adam Powell: A couple years ago I wrote
a post for the Android developer's blog that sort of details this idea.
So we start off by defining an abstract class or interface describing what the application
wants to do. And then we write implementations of that interface for each platform version
that layer us on the new functionality as it becomes available.
So we can use a simple factoring method or a similar mechanism to get the right implementation
for the platform version we're running on and then the calling code within the app doesn't
have to care about version differences anymore. So here's a simple example.
We've declared an abstract class that represents a few higher-level things that our app wants
to be able to do. And then we have this simple base implementation.
It can do the job even if it's not really fancy. This is our fallback for older devices.
Sometimes you might just want to drop functionality that you can't reasonably emulate or back
port. And it's okay if some of these compatibility implementations just end up being stubs or
no ops if there's really nothing more reasonable that you can do.
But on a later version of the platform, we can layer on additional -- or additional features
that enhance the user experience for those people running on newer versions of Android.
Note that we're calling back into the super class implementation over here in our contrived
example. This can be a great way to just layer extra functionality on your base behavior,
reduce extra duplication, especially if we're not just replacing it with something entirely
new. So a simple series of version checks makes
sure that we can construct the right version behind the scenes. And then the rest of our
code can remain ignorant of any and all version differences.
And for those of you wondering or anyone who's gone source-diving in the Android support
library, this is actually the same tactic that we use there. There's really nothing
magic going on in that library. This is how we've written all the compatibility shims
that we've made available so far. And you'll notice that this idea of these
really highly focused, isolated cases of layering on more advanced functionality when it's available
is present through all of these approaches to multiversioning that we're talking about
today. If you factor out all of these things into smaller, more isolated components within
your app, it stays a whole lot easier to maintain than trying to use some big overarching approach
that involves a lot of duplication. Okay. So enough about laziness for now. Let's
talk about something that's not so lazy. Well, it -- actually, it does a whole lot of work
for you. It does let you still be lazy, though. So we're, of course, talking about the Android
developer's best friend, the resource system. So a great tool for you to be aware of, if
you're not already, is the version qualifier for your resource directories. The naming
scheme looks a lot like this. So you can use this to offer alternate versions
of your layouts, your drawables, styles, and way more than that, depending on what platform
version the device is currently running. But, like everything else that we're talking about
today, it's important to use this in moderation. Again, if you take it to an extreme, you get
a lot of XML duplication, which is just as bad as other code duplication.
So what are some strategies we can use to avoid some of that?
>>Bruno Oliveira: So the first strategy is using Boolean resources. So a Boolean resource
is something as simple as the name implies. They're actually tons of fun, because they
can be true, but they can also be false. [ Laughter ]
>>Bruno Oliveira: The real point, of course, is not being true or false. It's that they
can be given -- their values can be given at run time by the resource system.
So this means that they can actually vary according to the device configuration, like
screen size, or in our case, the platform version.
So, for example, this is a file called bools.xml, and it's in the values-V14 directory. It's
defining two Boolean resources. So one of them is called post ICS, and the other one
is called pre-ICS. Now, because this is in the values-V14 directory,
these are only going to apply to devices running Ice Cream Sandwich or above. Now, likewise,
we have the bools.xml file in our unqualified values directory. This one has the opposite
value, so this is only going to apply when the device is running a version of Android
that's prior to Ice Cream Sandwich. Now, of course, you can use Boolean resources
directly like this, using get Boolean; right? There is nothing wrong with that, and that
might be useful in some cases. But the most interesting thing about Boolean resources
-- and it's not that they can be true or false -- is that you can actually enable or disable
components according to the platform version, like this.
For example, app widgets; right? So who here has written an app widget? Lots
of people have written app widgets. I did, too.
So an app widget is essentially just a broadcast receiver with some special data in it; right?
So if you have written one, you know it looks like this.
The point is, if you do it just like that, it's going to look the same and behave the
same for all the platform versions. But what if we wanted to provide a different version
for, say, devices running ICS or above? >>Adam Powell: Can we use a Boolean resource?
>>Bruno Oliveira: Yes, we can. Glad you asked. Exactly.
So we have to define two app widgets. First, let's define the pre-ICS one. So for the pre-ICS,
we just set Android enabled to bool/pre-ICS. So this means that it's true if and only if
we're running on a pre-ICS device. Likewise, we're going to do the same for post
ICS. So for my post ICS widget, I set Android enabled to bool post ICS. And that's going
to be true if and only if I'm running on a device that's running ICS or above.
Both widgets, of course, go into my applications manifest. And the magic of this is that the
correct one is going to be automatically activated depending on the platform version that you're
running on. But that's for app widgets. What if you wanted
to have a fallback like that but for an activities user interface. In this case, what you need
is a UI fallback, which is a technique that you can use when there are certain parts of
your layout that you would like to do differently depending on the platform version that you're
running on. For example, in this example where we're going
to use this technique to present the new and awesome switch widgets on ICS; right? And
then on the same application, same layout, we're going to display the good old classic
check box on the older versions; right? So how do we do that?
Well, we could do that using, like, two separate layout files. Everybody knows how to do that.
But that would be no fun; right? The whole point is to have a single main layout
file and then pull bits and pieces from the other files as appropriate.
Here's what our main layout file would look like. These comments in green are the parts
that don't depend on the platform version, for example, that text view; right. But for
the part that does depend on the platform version, we're using layout include. We're
pulling another layout by its ID, but the desserts ID. So this means that we can supply
different versions of that included layout that's going to depend on the version that
we're running. So how do we do that?
We place two different versions of our desserts.xml file. One of them is in the layout directory,
unqualified; right? And the other one is in the layout-V11 directory. So if I'm running
on ICS or above, it's the right-hand side that's going to kick in, so with the switches.
If I'm running on a device that's pre-ICS, it's the left-hand side that's going to kick
in, and it's going to run with the check boxes. So that just gets plugged in into the right
place in our main layout because of the layout include.
One thing to note on the code is that you should always be aware of whether you're dealing
with a switch or a check box. You could branch on top of the version and then cache to the
appropriate classes, but that's difficult. Instead, you can just realize that they both
derive from compound button and just do it like that, which is much easier, of course.
In all cases, remember that this trick is not just limited to widget fallbacks. So layout
includes are actually a very powerful tool, and they can always be used when you have
sections of your layout that should be different depending on device configuration. So platform
version, screen size, anything else that you can describe with a device configuration,
you can use layout includes. All right. So let's move on to another very
important topic. So we're developers, right, so we are focused
on making stuff that works. We like stuff that works. But legend has it that users also
care about looks. Go figure. So let's talk about how we can make sure that
your themes work across platform versions. So in this way, you can make your app look
great, regardless of what release you're running on.
So, Adam, how can we do that? >>Adam Powell: All right. I'm glad you asked.
On a Nexus device today, you have basically four themes that users might see on a regular
basis. And in the long run, we'd really like to get this down to two. But there will always
be a few legacy apps that users really don't want to let go of. By the way, creating any
sort of more modern replacement for those that are still floating around, great opportunity.
There's also the device default themes which, on a Nexus device, they just simply alias
to the holo themes. So we're going to mostly talk about those for now. But a theme, really,
at its core is a bundle of defaults. It's just a style that's applied at the context
level, after all. It defines the default look and feel for each type of view. But more importantly,
it provides a point of indirection that you can use in your apps.
Your layouts probably have a whole lot of hard-coded metrics here and there, like text
sizes, paddings, margins, so on and so forth. And this is fine. But the theme also has a
bunch of defaults that you can query using the syntax shown here.
(indiscernible) ops makes sure that you're using the metrics that the rest of the system
does, making your app feel more like a first-class citizen.
But between -- Whoops. Too quick. But between some elements that you query from
the theme and other elements that are unique to your app, it can get really repetitive
if you use the same value over and over. And this is where it becomes a good idea to define
some of your own custom styles that you can apply to views.
So you've always got a base to build on when you're defining a style, especially if you're
going to redefine what a default button style is on a custom theme, so on and so forth.
You always want to declare a parent for your styles so that that way you always inherit
all of the defaults that are there that you may not really care about.
But the problem, of course, is that holo and device default didn't exist before Honeycomb
and ICS, respectively. So how do we write our apps so that it looks like this, depending
on what kind of device that we're running on?
The key is in which parent you declare in your custom styles and themes. So before Honeycomb,
you'll want to base your apps theme on the legacy theme or theme.light. And after Honeycomb,
you may want to use the holo variants instead. So how can we do that? And, really, the same
goes for the widget styles. The simplest way to do this that comes to
mind for most developers is to just redeclare the styles in a resource overlay for V11;
right? Well, of course, that gets into the same problem of duplication again.
A better way is to declare a base style that varies by version and then keep your main
customizations in a style that derives from that instead.
So you get this simple declaration here to declare a parent that will be selected at
run time. And you can keep all the customizations that are unique to your app in one place rather
than duplicate them. And by doing this, we've separated out what's
unique about different Android versions, and we're targeting -- or the different Android
versions that we're targeting and separating those from how our app differs from that base.
So, if a theme is just a big ball of metadata about defaults, can we create our own attributes
that we can query from later? Maybe this will be helpful for us.
And the answer, of course, is that, yes, we can.
This is especially helpful when there are no attributes available in newer versions
of the platform, but that they didn't exist before that. So you can create a simple shim
attribute of your own in one place and get the right behavior everywhere.
So here's a quick example of adapting the selectable item background attribute that
was introduced in Honeycomb across multiple platform versions. By convention, we always
declare theme attributes in a file named attrs.xml and the res values directory, and then we
assign values to the new attribute in our apps theme declarations.
If we're using the tactic from earlier, with a base theme that varies by platform version,
then we can put declarations that bridge the version gaps like this in the base themes
rather than the theme that actually declares our app's own customizations.
So there are still going to be device-specific skins out there to consider when you build
your UI. So when is it appropriate to use each theme?
So as of Ice Cream Sandwich, holo is a stable base, you can always count on it being there
and we have designed it to be easy to work with. And we kind of like it.
So device default is a little bit less predictable, but this is how you can integrate with all
the various device skins if you're willing to query the theme for just about everything
that you do. There are very few assumptions that you can make here, but it can give you
a very native-looking experience if you're willing to work with it.
When it comes to the layout and structure of your content, on the other hand, following
the guidelines on the Android design site is still a really great place to start, regardless
of what theme you're using. With very few exceptions, you should always try and keep
structure and interaction patterns consistent across different themes and versions of the
platform. Bruno, can you give us some tips about some
of those cases? >>Bruno Oliveira: Sure. So let's talk a little
bit about the support library and beyond. So one of the great tools -- they are great
tools to help you keep a -- consistent user experience patterns across multiple platform
versions. So these will greatly simplify your work.
>>Adam Powell: That's right. And in just a few weeks, we're about to make
available some more tools that will encapsulate a lot of this stuff that we've been talking
about today for the commonly used components, things like the selectable item background
that we mentioned. So app compat is a new addition to the support
library to join the existing v4 and v13 components that you're probably already familiar with.
While the parts of the support library that we've already released provide this abstract
box of tools for you to work with for building your multiversioned apps, app compat elements
are designed to help you follow the Android design guidelines across those multiple platform
versions. >>Bruno Oliveira: One of the components that
the support library can help you with is fragments. Fragments are modular units of composition
within an activity. So multiple fragments can be combined together to form a single
layout. And they're actually a great way to manage user interfaces that work on phones
and tablets. Now, fragments are not an ICS feature; right?
They are so useful that we've made them available all the way back to Honeycomb. So -- oh, no.
Actually (indiscernible) for you. So Adam.
>>Adam Powell: Well, so what do we do? Well, I mean, everybody likes Froyo; right?
So as you already know, if you've been using the support library, you can use fragments
on previous versions as well with the back-ported version that we've provided. All you have
to do is add the support library to your project and import the correct classes. Then you proceed
as you would with a regular fragment. >>Bruno Oliveira: For example, here we're
defining our own fragment class. So this is the same as we would do if there were no support
library at all. We simply derive it from fragment; right? And then we override the appropriate
methods as we wish. Now, adding fragments to a layout is also
no different than you would do without the support library. So it's perfectly transparent
in this case. So this is an example of adding fragments to your layout using XML. So remember
that you can also do that from code using fragment transactioners if you prefer.
One thing to be careful about is that you have to derive your activity from fragment
activity and not activity; right? So this is specific to the support library.
So this is one of the few places where the transparency is not 100%.
>>Adam Powell: You've got something. >>Bruno Oliveira: Yes, by the way, I think
it's time that we talked to you about -- >>Adam Powell: Notifications.
>>Bruno Oliveira: -- notifications, yes. So, as devices get more advanced, the complexity
of things they can do with notifications increase a lot. But, fundamentally, they are just a
way to tell the user that something is happening right now or is about to happen and it's something
that they actually care about. So this last part is actually pretty important.
The user has to care about the -- yeah, about the event that you are telling him.
So before Honeycomb, notifications were somewhat limited; right?
So this is what you would probably see as far as code is concerned. So you can discreet
your notifications directly and then set parameters and happened it off to the manager. Naturally,
you can use it for simple cases but after Honeycomb, this became a lot more interesting.
So we introduced this notification builder that helps developers create them. Notification
builder is a builder that actually provides notification for you based on the settings
that you provide by calling its methods. It is definitely a lot easier than building it
by hand. So I like this notification builder thing, so it makes me really happy. But then
I realize it's only for APIs 11 and above so that makes me sad.
>>Adam Powell: What if I tell you this is also in the support library.
>>Bruno Oliveira: I'm happy again. >>Adam Powell: Import it and it works in the
most common use cases. >>Bruno Oliveira: What are the changes in
Jelly Bean? So let's be concrete about it. We are developers. According to a recent study
the notification builder in Jelly Bean is approximately 217% more awesome than the one
we had before. [ Laughter ]
>>Bruno Oliveira: Those are very reliable and serious numbers. So this is -- for instance,
it includes methods like add action, which you would be able to see if the screen shot
was in front of it. Actions on the notification. Like answer and ignore. And also, another
pretty cool feature about notifications is you can use styles. So you can set the style
using the set style method and it comes with a certain predefined styles that encapsulate
most of the commonly used types of notifications. >>Adam Powell: Unfortunately, the naming here
might imply otherwise. But the styles really do just refer to these different styles of
notifications and not actually resource styles in terms of the resource system.
>>Bruno Oliveira: So this is what the big text style looks like. We have a title and
a large amount of text under it. It can be for, say, an email snippet, right? Then this
is what the inbox style looks like, when you have a content title and snippets for several
items. This is the big picture style. Title, details, and guess what?
>>Adam Powell: Big picture. >>Bruno Oliveira: Yes, exactly. And there
are several other new features but we can't cover them all here because we don't have
time. It's definitely worth taking a look if you are at users notifications anyway.
Now, sadly, the new Jelly Bean notification features are not yet in the support library.
So if you want to take advantage of this right away and be backwards compatible, you have
to do a branch. So if you can detect whether you are running Jelly Bean or not. If you
are, just use a notification builder natively. And else, just use the notification comeback
builder in the support library. Fall back to the support library. Hopefully one day
it's going to become easier. >>Adam Powell: One day pretty soon.
>>Bruno Oliveira: One day pretty soon, yes. Another important point, be careful when creating
notifications, icon consistency. On Froyo and older devices, you would have white over
a black background. This is what a notification icon would look like. On Gingerbread, they
would be gray over a transparent background. And then on Honeycomb, they would be white
over a transparent background. And for each of those, you have to supply the versions
for all the screen densities possible, right? >>Adam Powell: That's way too many icons.
Is there a tool or something we could use for this?
>>Bruno Oliveira: Maybe. Maybe it's on the next slide. Oh, joy, it is on the next slide.
So surprise, surprise, there is actually a tool that helps you with that. It's called
the Android asset studio. It can be found on that URL up there. So it generates the
icons for you. It's pretty nice to have in your toolbox. Check it out if you haven't
used it before. Now, let's move on to another very important
topic. The action bar. So Adam, can you tell us why the action bar is such an important
topic? >>Adam Powell: The action bar provides a consistent
way for the user to navigate and perform within your application. You can make up your own
way to navigate and perform actions. Anyone who has used an modern Android application
is probably familiar with a bar already. So in the interest of making your app easy to
learn, there's a good chance your app should use it too. Most times when someone calls
an app intuitive, what they are really say is it works like something else that I'm already
familiar with. So you really want to make use of that wherever you can. Action bar has
two parts. Navigation, which is usually tab spinners, the up button and such, and actions.
Actions are divided between the action buttons that are visible that are surfaced on the
bar itself and the action overflow that's behind that little three dot button right
there. And remember the FIT rule from the Android design guide. Anytime that an action
is frequent, important, or typical it should be on screen whether that's in the action
bar or not. Anytime that it's not, then you should think about tucking it away someplace
that's maybe not taking up that valuable screen real estate all the time. The overflow is
one way to do that. >>Bruno Oliveira: Wait, I've heard some rumors,
they may be rumors, but the action bar seems to not be available before Honeycomb?
>>Adam Powell: Really? >>Bruno Oliveira: Yes. If that's true, what
can we do? >>Adam Powell: If you are running on a pre-Honeycomb
device, you can implement your own version of it. Good starting point is the action bar
compat sample. You can use a third-party library, like action bar Sherlock. Wait, there's also
some good news, soon you will be able to make the app-compat library to make action bars
that work all the way to Eclair. It will be as simple to use as support library's fragments
as well. [ Applause ]
>>Adam Powell: Oh, would you -- >>> Yeah baby.
>>Adam Powell: Bruno, we made some friends. Many of you familiar with backward compatible
fragments. Action bars work the same way. Action bar activity extends fragment activity
so you don't have to worry about any sort of conflicts between those. You will have
fragments available as well. And just like fetching the support fragment manager, you
can grab the support action bar in the same way. So the best part about this is the action
bar is really just the beginning of the kinds of things that we are planning on making available
as part of the app-compat library. Knowing all of these techniques we are talking about
today is always going to be useful but really nobody likes code duplication. We want to
bring the common fruits of all of this together in a form that you can just simply include
and use in your apps. Bruno, actually it looks like we have time left. It's just enough time
to talk about some miscellaneous tips. Now that we covered the most important topics.
Resource system themes, support app and app-compat libraries. So last we will finish up with
some miscellaneous tips that may be useful when writing multi-version Android user interfaces.
Our first tip is to, by all means, resist the temptation to style the options panel.
The options panel is one of those things that the user sees as a familiar anchoring element.
If you make it look a lot different than what the system looks like, that can be confusing
to users. It's not difficult to confuse users. Pay attention to the fact that each platform
version has different style. Look at the options manual in options panel in general. So you
should always provide assets to match that style. And try not to change it. It's also
worth noting that menu key is going away. Most new devices don't have a menu key. Actually,
most of the devices don't have hardware keys at all.
>>Adam Powell: Some of them still do. >>Bruno Oliveira: Some still do. The menu
key is definitely going away. It's function has been replaced by action overflow. It's
the same use case, when the user doesn't find something on screen, they will look for it
in the menu key or in the action overflow, depending on the system. So remember, any
action that follows the FIT rule, or on your layout. And then anything else should go either
in the options panel or in the action overflow depending on the platform version.
Speaking about familiar anchoring elements. That slide didn't come out too well. Dialogues
are also one of them. The indicate system level interactions, like critical yes or no
prompts, they should be used sparingly. Because, as you can see, popups are very annoying.
Dialogues should never be a central part of your user experience. Leave them alone and
don't change the default style that they will take according to platform.
If for some reason you cannot resist the temptation to style a dialogue, then this might be an
indication that whatever you're trying to accomplish with that dialogue should not be
a dialogue at all. It should be, in fact, part of your activity or be a separate activity
on its own. By all means, never style dialogues. So this next tip something that always drives
me crazy when I switch between devices maybe. So on a pre-ICS device, the default button
order was positive, neutral, negative. This is what we would typically see. The button
that does stuff is on the left. And then the button that doesn't do anything, that cancels,
is on the right. On Ice Cream Sandwich, we actually switched them around. So the button
that does something is on the right. And the button that doesn't do anything is on the
left. So it is better this way. It is better -- the Ice Cream Sandwich way is better because
it reduces backtrack because the option that the user is likely to choose is closer to
what the user is looking at when he finishes reading the sentence. You should always keep
in mind that this is different between platform releases. If you want to go that extra mile
in making sure that your app is consistent with the platform, you should always make
sure that your button order is consistent with whatever platform you are running on
so that you don't surprise the user in a bad way.
>>Adam Powell: That's right. This sort of button layout order issue is the exactly the
kind of thing we want to provide in the app-compat library as well. So we will go ahead and have
some versioned layouts that do the button bars. And just as ad add note, some of you
realized that writing app that is use different themes here, you might have noticed even on
an Ice Cream Sandwich device, an app that uses the old style dialogue is still using
the old button order. As it turns out, this is mostly because if user become that familiar
with that particular application, not only do they have muscle memory for it, but it's
also fairly common for applications to sort of mix and mingle system-generated dialogues
like an alert dialogue with dialogues that they have a custom layout for. We didn't want
to make individual apps internally inconsistent with themselves for that.
So it is also important to keep in mind that your app is not the only app that an user
is going to interact with on a daily basis. So as you switch between different apps, you
do want to try to keep a level of consistency with this sort of thing.
>>Bruno Oliveira: All right, our last hint. Always set the minimum SDK version and target
SKD version in your manifest. That's important because the minimum SDK should be what it
says, it's the minimum platform version required to run your application. Hopefully that's
going to be as low as possible and we hope that after this session it is going to be
even lower than before. Now, the target SDK version is something that many of us forget
to set or they just set to very old version. So target SDK does not affect the minimum
SDK level needed to run your application. So it should always be the latest platform
version that you are aware of and that you have tested your application against. So for
everybody in Google I/O from this date, this should be Jelly Bean. This is important because
depending on the target SDK version, the platform is going to enable or disable lots of compatibility
tricks, and that's going to affect things like the default theme. For instance, if you
set your target SDK version to 11 or above, you will have a default theme that has an
action bar. If you don't, you will not get an action bar, right? And certain other features
are also key to that. So if you want to make sure that you have the latest features enabled
for your application, always set target SDK version as high as you can. Another example
of that is if you set it to a level 14 or above, you will get hard acceleration by default
on every activity. If you don't, you will enable it individually per activity. So it's
very important to set those two attributes in your Android manifest.
>>Adam Powell: This is for safety in terms of making sure that applications still run
even if we start making a little bit more risky changes. Hardware acceleration in UIs
was definitely one of these. Not everything has the same performance profile in hardware
render, and there were certain operations that weren't supported at all in the beginning.
>>Bruno Oliveira: Remember, we don't want to break anybody's application. Backwards
compatibility is one of the core Android values. This is why we have target SDK version. Because
this is how the platform knows what your application expects to work with so we can actually provide
backwards compatibility depending on the case. >>Adam Powell: That's right.
>>Bruno Oliveira: So if anybody has any questions, we would like to answer them now. We also
remind you that we have an office hours space so anytime you want to ask a question, you
can drop by there. We will go there right after this session. If you have a more complex
question or something that requires us to see something, you can -- we will be glad
to talk to you there. But so does anybody have any questions? I think there are two
microphones, right? [ Applause ]
>>Bruno Oliveira: By the way, don't forget we have plus one boxes at the corners of the
room. so if you like the session -- if you like our session, please put the plus one
card in. We do not have minus cards. If you don't like the session, you will have to be
old-fashioned and throw tomatoes, instead. Just kidding. Please don't throws vegetables
whatsoever. >>> I have a question about styles. Like with
the style buttons, like spinners, so I tend to style everything to make the app look same
on Ice Cream Sandwich and Gingerbread. Is that a good practice or not?
>>Adam Powell: If your app has a really distinctive still of its own, yes, that can be a good
way to go. I would also say that it's kind of a matter of taste. We're definitely sort
of leaning toward more holo styling in the Google apps. The closer we get to that, the
better. >>> I found some Google apps running on the
Gingerbread, it looks like Ice Cream Sandwich. With the spinner, on Google translate it looks
like Ice Cream Sandwich but spinner on Google, I don't know.
>>Adam Powell: We definitely have a lot of the Google apps that have taken some various
approaches to dealing with this. And you'll find some different approaches on each one.
It really does come down to how you want to treat those older versions in the platform.
I would say it's a judgment call. >>Bruno Oliveira: One thing for the action
bar, the action bar was not available before Honeycomb. Now it's a pretty apparent to have
action bars even though you are running on a device running something prior to Honeycomb.
The action bar is one of those examples where we sort of like back ported a pattern to previous
versions. >>> Quick question. Any recommendation how
to integrate Google Maps with fragment. >>Adam Powell: That's a fun one. Do you want
to take this one? >>Bruno Oliveira: The problem with is that
when you are using support library you have to arrive from fragment activity. When you
are arriving from Google Maps, you have to derive from map activity. One of the problems
with languages that don't have multiple inheritances, you can't do that in an obvious way. We don't
currently have a way that you can do that. So you are just going to have to branch and
if you are running -- if you need the support library, you can just use that in some different
way and just have a regular activity, not a fragment activity. And then derive from
map activity. If not, you derive from map activity. There is no -- currently no way
to do that except branching. >>Adam Powell: That is and isn't true. There's
actually a couple of really dirty tricks that you can pull that technically work and if
you'd like to talk more about those, see me in office hours after we are done here.
>>> Hi, does the new action bar activity support some of the additional action bar functionality
found in Honeycomb and Ice Cream Sandwich similar to, like, the alternate action bar.
I forget the name after it. >>Adam Powell: Split bar.
>>> To replace the top action bar or Gmail the action bar at the bottom?
>>Adam Powell: To replace? I'm not sure which you are talking about. The split bar that
you see in Gmail or talking about the one that replaces the current bar for the action
modes? >>> Both.
>>Adam Powell: Both. The split bar, yes, that will be there. The action modes, no, they
won't. The action mode API is set up that it's series of calls at the view level that
basically bubble up the hierarchy and get dealt with as you go up. We really don't have
a good way of expressing that there. It's always not a pattern that was -- it really
wasn't supported pattern prior to that either, so I would say that the way to adapt across
that boundary when you have a case where you want to use multiple selection action mode
on newer platforms, but you kind of wonder what to do on an old one, I would say use
a context menu. >>> Thank you.
>>> (inaudible) >>Adam Powell: Cool, we will take a look at
it >>> Action bar Sherlock, using that on a Google
TV, it nicely puts the action bar on top. Will compatibility library do the same? Or
will it be on the side? >>Adam Powell: For Google TV? The plan is
on the top. >>> Thank you.
>>Adam Powell: By the way, regarding action bar Sherlock, is Jake here by any chance?
Oh, nuts, okay. >>> Where is the best place to learn about
at compat and what's going on with it. >>Adam Powell: Stay tuned, there will be an
Android developer post on it. >>> I have a similar question on fragment
in the support library. >>Adam Powell: This is going to be another
fun one. Go ahead. >>> Is it going to be integrated?
>>Adam Powell: Preference -- oh, I see, so preference fragments in the support library?
We will take a look at it. There haven't been direct plans as far as I know, but we will
see what we can do. >>> Before we had -- there was somebody talking
about the fact that we are implementing right to left text as -- inversed, too.
>>Adam Powell: Has which been inversed? >>> Inversed, right to left, right to left
text. >>Bruno Oliveira: I'm pretty sure that they
are. I'm pretty sure they follow the language setting.
>>Adam Powell: The stuff that's been going in so far bidirectional support has been fairly
deep. It's also something that we tried to do more or less automatically. I would say
you could probably expect anything that's in app-compat around button bar styles like
that will be pretty much automatic, but I don't think that -- I'm trying to think if
that's something that's -- backporting makes a whole lot of sense for. At the point where
you start backporting all of the bidirectional layout type stuff, you are essentially replacing
half the UI tool kit. >>> Any plans to provide more adapters besides
SDK adapter regarding fragments? >>Adam Powell: I don't think I understand
the question. The listed app? >>> For instance, there is a fragment listed
app but there is no for gridview or for any other views?
>>Adam Powell: Fragment list adapter. A list fragment?
>>> Yes. >>Adam Powell: I see. I suppose we could add
them. But I think the list fragment was more meant to be there as little bit of parity
with the list activity that we had before. That is something extraordinary simple. It
has been farther down the priority list. We have wanted to handle the more complex cases
out of the box first. We can certainly take a look at it.
>>> Fragments in fragments. There's a common case where you have an action bar with a navigation
list. Depending what you choose, you put it in fragments in and out. But the problem is
what if you are using something like a view pager and you have a view pager fragment?
How do you deal with that? I know there are work-around. Is there any way we can get it
done normally? >>Adam Powell: Most of the times when I have
taken a look deeper into some of these cases, it generally means there's something kind
of weird about the layout to begin with. We generally don't really want to support fragments
in fragments right now. It's come up over and over and it sounds like a good idea; sounds
like a bad idea. Sounds like a good idea; sounds like a bad idea. We go back and forth.
A lot of times when it comes to the view pager specifically, what we usually end up doing
is -- this is a case where I wish I had a white board. If you want to come down to the
office hours later to do more, that's great. But I will try to wrap it up. Generally what
we will try and do, if you have something like a two-pane layout where you have a list
and view pager off to the side, then at some point you have like a top level skeleton that
is sort of where all the fragments go, right? So it's essentially your top level layout.
In a case like that, conceptually the view pager is part of that skeleton. You can kind
of thing of the fragments that the view pager brings in and out as being on the same level
as that side bar list itself. So in those cases, the view pager would actually be part
of the top level lay out and not in a fragment on its own. It would manage the internal fragments
itself and that avoids the need for nesting. >>> Okay. But you are aware of, though, the
work-arounds where people have to load -- set the adapters for the view pager in a separate
handler just to avoid the exception that comes up?
>>Bruno Oliveira: I have never seen that. >>Adam Powell: Which exception? I think this
might be something a little bit different. >>> Maybe I will talk about it --
>>Adam Powell: Come see me in the office hours afterwards. I'm interested. Is that all?
>>Bruno Oliveira: Any more questions? >>Adam Powell: One more.
>>> There used to be an expandable list activity. Is there any plans to, like, pull the expandable
list fragment into the app compatibility as well. There are open source implementations
out there. Is there anything you are going to look at that?
>>Adam Powell: If there are contributions to AOSP. If there are implementations that
are Apache 2 that someone would like to submit. >>> It is on (indiscernible) android.com with
the snippet. >>Adam Powell: Is there? Great. We will take
a look at that time. In terms of taking code snippets pasted into the bug tracker, that
ends up being problematic for us. It needs to be loaded into AOSP for that sort of thing.
>>> Sure, we can take a look at that. >>Adam Powell: Is that it?
>>Bruno Oliveira: Thank you very much. >>Adam Powell: Thank you all.