Tip:
Highlight text to annotate it
X
ANKUR KOTWAL: So, before we get started into this week's
topic, let's talk about the news.
So, really two pieces of news for Android developers.
Firstly, Google Play Services has launched.
We're really excited about this.
It now provides the OAuth identity management.
It provides you OAuth tokens so that you can use a single
nice API that abstracts the whole OAuth side of things for
you across all of our Google services.
And we also have the Google+ SDK as part of that.
So Google Play Services is quite interesting.
What it is, is it's a component that's actually
going to be there on users' devices as part of the Google
Play Store.
The Google Play Services component will be installed.
And now, as developers, you can just go ahead and start
using that new API.
This is just the start of something much bigger.
Google Play Services will grow.
And OAuth2 and Google+ are finally here.
So that's really good.
And the other thing that I'm really excited about is that
we have a new build system coming for the Android
developer tools.
Akim Zaveidurisham has put up a document that sort of
describes some of the changes that are coming up.
They're not available in a stable release yet, but you
can certainly go and have a look at that document and see
what kind of changes are coming.
Yeah, this is good stuff.
More tools for developers is always a good thing.
It's tablet week, so our focus today is to really use the
word "tablet" as much as possible.
No, that's not true.
We want to basically empower developers to build apps that
work well on phones and tablets.
We're actually going to have a series of presentations on
ADL+ over the coming weeks.
Today's the first one, and it's really about the
fundamental building blocks of these apps.
And it's really Fragments--
those are the components that you use.
So today is very much a primer on Fragments.
And so we're going to cover a few things.
But before we do, let's talk about some fundamental goals
that developers would like to have, or we
always want to have.
We want to build phone and tablet apps.
Firstly, we want to have a single app for
multiple form factors.
We don't want to have to manage a different set of code
for a phone version, for a tablet version, or even for a
Google TV version.
As much as possible we want to maximize our code reuse.
And in doing so, you kind of want to have your code be
quite decoupled so that you can build these reusable
components and have them not totally depend on the other
components being there.
Decoupling is obviously a really good thing in general
software design.
And finally, you want to build these apps such that they're
backward compatible.
Android 3.0, or Honeycomb, is where we
first introduced tablets.
And prior to that, we had Gingerbread and Froyo.
Now Gingerbread is still a very popular
version of the platform.
So when we talk about these Fragments and utilizing them,
we want to do it in a way that still allows our apps to run
on these older versions.
So we're going to touch on that, too.
How do we make sure that they're backward compatible,
whilst keeping all of these goals in mind?
So, what are Fragments?
Fragments--
they're really reusable components.
So it's about grouping bits of your UI, or other common
functionality, so that you can then use it in these
standalone classes.
So, when we think about taking an app and making it available
on tablets, what we want to do is really promote the idea of
the fact that you should really rethink your UI.
Don't just take your phone layout and stretch it because
that's not really a good experience.
And in the majority of cases, stretching out a typical list
or something like that on a phone and just stretching it
out onto a tablet doesn't really result in a good user
experience.
And users never tend to appreciate that.
So, as you can see from this diagram here, where you might
have had two activities--
one and two--
what you would do is actually take the contents of those
activities, and put them into Fragment.
And on the phone, you would be showing one Fragments at a
time, whereas on the tablet you could show both Fragments
at a time within a single Activity.
So the Activity is still that outer window, and you can see
it based on the blue border.
You still have activities when you're running
on phones and tablets.
And we're not moving away from activities.
But we are taking out all of that code that we had within
the Activity, around the user interface, and just regrouping
it into Fragments.
So what are Fragments?
Well, Fragments are basically reusable UI components.
By grouping our contents that we would have had in an
Activity, it means that we can be
flexible with these Fragments.
Being a Fragments isn't just like an
include in your layout.
There's actually more to it than that.
It actually participates as part of the life cycle.
So Fragments actually have a life cycle.
And they're attached to an Activity.
And that's really important because the Activity will
initialize them at key points.
It'll populate them.
And there are some specific overloads that you
should be aware of.
Fragments can also maintain their own backstack.
So, in a typical phone app, you might go from one Activity
to the next, to the next.
But if you now start reusing the contents of those
activities into Fragments, you might use a single Activity
and just transition from one Fragment to the next.
Now when the user hits the "Back" button, you don't want
it to go from one Activity to the previous one, you want to
make sure you navigate backwards through the Fragment
stack before you go to the previous Activity.
So, Fragments allow this.
The other thing to keep in mind is that Fragments don't
have to be UI components.
They can just be background workers that you instantiate
and that participate as part of the life cycle.
So, we have an API called findFragmentByTag.
Typically what you'd have is a Fragment that you'd put in a
layout, and you'd do a find view by ID, and grab the
layout, and so on and so forth.
But you can actually instantiate Fragments.
In using the Fragment manager, you cannot basically name
them, or tag them.
So this find Fragment by tag is a way to basically get a
hold of that Fragment at runtime without having to rely
on things like the view hierarchy.
So, let's talk a little bit about Fragments and activities
in general.
So, the user interface part is optional.
Typically, in most circumstances, you would use
them with a user interface.
You would use them for grouping UI.
But you don't have to.
Whereas with an Activity, it always has a user interface.
It's always the part that the user sees.
Both of them tend to have life cycle methods.
And in fact, the Fragment tends to have a few more life
cycle methods than the Activity in the typical UI
style Fragment.
Fragments can't be standalone.
They are attached to activities.
And we actually have an override called
onAttach and onDetach.
Now, the other thing you should be aware of is the use
of Intents.
So typically we use Intents to invoke certain pieces of
functionality in your Activity.
That still holds true, except with Fragments, Intents don't
go fire up Fragments directly.
You have to go through an Activity.
And we're going to clarify this later.
So what we're doing here is best describing
what Fragments are.
We're going to look at now the advantages of using Fragments.
And then eventually we will talk about--
before we talk about backwards support--
we're going to talk about communication, as well,
between Fragments.
So let's look at a typical layout.
On a phone, this is the people app that we've had since Ice
Cream Sandwich.
And you'll see on the left hand side
you've got a list view.
With this list view you have your list of contacts there,
and there's some tabs across the top.
You can swipe across them and so on.
It's a fairly standard list view type screen with some
actions along the bottom.
Now, if we want to click Matias there, it would take us
from the list view for that contact and go
into the detail view.
Now, a traditional phone app may have implemented these as
Activity 1 one for the list view and Activity 2 for the
detail view.
But if we then reorganize our code such that this list view
part of it becomes a Fragment, and the detailed view also
becomes a Fragment, then what happens is on the phone we
still can still present the same interface.
But when we go something like the tablet, we can show these
multiple Fragments at the same time.
We're maximizing our code reuse.
We're not having to define layouts multiple times, and
even code multiple times, or having really complex
inheritance hierarchies.
With Fragments, we can basically show multiple pieces
of UI at the same time.
There is some extra code that you need to do to distinguish
between a phone layout and a tablet layout.
We're going to look at that next.
But the differences are really phenomenal in terms of the
overhead for you and your developers.
So, when it comes to defining layouts, you might be saying,
well, how can I say that this layout is going to be for a
phone or for a tablet?
Well, in Eclipse, when you define your resource or your
layout directories, you can basically say it's a layout
directory, which will be the default layout that gets used.
Or you can have these extra qualifiers.
So, one of the qualifiers is something that we call
smallest width.
And then you can specify a number and a DP.
Now, smallest width basically says, that regardless of
whether I'm holding it in portrait or landscape view,
what is the smallest dimension on this device?
Now, what we've done is that we've got some metrics in
there that tell you that this is the range of values that
will result in a tablet UI, or phone UI.
So, if you specify smallest width 600, anything that has
600 DPs or greater is considered a tablet, okay?
We've, in fact, added an extra layer of
differentiation there.
If you specify 600 DP, it'll get picked up
by seven inch tablets.
If you specify 720 DP, it'll actually get picked up by 10
inch tablets.
So you may want to have a different layout between your
seven inch tablets, and your 10 inch tablets.
And this metric here is how you do that.
And you'd still have a normal layout folder.
And That normal layout folder is what will get picked up or
phones, the 600 DP for seven inch tablets, and the 720 DP
for 10 inch tablets.
You don't have to have all three.
Nothing is sort of forcing you to do so, but our
recommendation is at least have two.
Have the default layout folder, and then have the 600
DP for your tablet UI.
Now prior to Android 3.2--
so really only Android 3.0 and 3.1--
the only way that you could have a tablet layout was to
specify a res-large or a res.
Sorry, that should say layout-large and
layout-xlarge directory.
In fact, I'm going to just fix that live right
now, because I can.
And we're done.
So, it's a layout-large and a layout-xlarge directory
because prior to Android 3.2, we didn't have that smallest
width qualifier.
So, a large or and extra large layout would actually get
picked up by those devices.
We no longer recommend that you use large and extra large
qualifiers because it becomes a little bit of a gray area.
What defines a large, screen?
Is it a seven inch tablet, like the Nexus 7?
Or is something like a Galaxy Note
considered a large screen?
So, rather than having these generic buckets, we now use
the smallest width qualifier and you should, too.
So, at run time, how would you tell between whether you're
running in a phone layout, or tablet layout?
Well it's easy, right?
Because in your Activity you're going to have a layout
that you load.
And on the phone, you would typically only be showing one
Fragment at a time.
On a tablet, you might show more than
one tablet at a time.
So, what you can do is use a findViewById API, and see if
you can find both Fragments.
For example, if you're going to be able to find one
Fragment, then you know that you're running on a phone.
If you're able to find both Fragments, then you know that
you're running on a tablet.
And so that's that extra sort of glue code that I was
talking to.
But it really belongs in your Activity.
Because remember, Fragments themselves should be
standalone, reusable components that are fairly
decoupled from everything else.
It's the Activity that kind of binds the multiple friends, or
really your layout that binds the
multiple Fragments together.
So, you can just use a trick like that with using
findViewById and doing a null check.
And that should sort you out.
So, we talked about Intents before.
Typically what happens is when an Intents gets fired off,
your Activity gets invoked and told hey, here's an Intents.
But you can't go from Intents directly to a Fragment.
It still comes through an Activity.
So, you might be wondering, well, how do I manage that?
How do I get an Intents to end up invoking a Fragment?
And the answer is it has to go through an Activity.
But let me just show you some code that demonstrates how
that propagation may work.
So let me just highlight the relevant section.
So, here what's happened is we're in the--
it could happen in onCreate or it could happen on
onNewIntents--
what you'd do is basically do a get Intents code.
So this code is actually in your Activity, itself, right?
And so we just do a get Intents.
We get the action.
And we're just comparing whether the Intents action
matches whatever action it is that we're interested in.
So, once we do that in our Activity, we can then go, OK I
know that it is this action.
So now I'm going to go and get a hold
off my noteless Fragment.
So in this Activity there's probably a list Fragment and a
detail Fragment.
So a list of notes, and then the detail Fragment is
probably the note itself.
So, what we did is we got the Intents.
Now we managed to pull the relevant Fragment out.
And then finally we are able to pass in some extra
information.
Or, sorry, from the Intents we can get some extra information
out as to which list item we want to select, or
so on and so forth.
But this is an example of where in the Activity we
receive the Intents and then we followed that through and
passed it through the relevant Fragment.
So we are kind of starting to spread out our code a little
bit between different classes.
But that's not necessarily a bad thing, either.
OK, so we talked about Intents communication, but what about
when you've got two Fragments and you want to communicate
with one another?
You could do all sorts of sort of trickery, where you've got
Fragments talking to Fragments.
But it's generally not a good thing because then you start
to really closely couple them together.
Then one Fragment needs to know whether the other
Fragment exists, and has been loaded, and so on and so
forth, and then pass information back and forth.
Instead, what we recommend, is you still use the Activity as
kind of a proxy.
So, what you would do to achieve Fragment to Fragment
communication is go via the Activity.
So, here you'll see that what we recommended is that you
define an interface in Fragment 1--
we're calling it Interface A for now.
Then Fragment 2 would have Interface B defined.
The Activity would implement those methods.
And then when those methods are being called on those
interfaces, it would then pass it on to
the relevant Fragment.
And it may, in fact, like on a phone, actually need to
instantiate the second Fragment.
Because on a phone, both Fragments may not have been
instantiated, because that single
Fragment layout uploaded.
So, again really the Activity's that thing that's
binding it all together, right?
So what would happen is that once the interfaces are
defined and the Activity's implementing them, your
Fragments are invoking the Activity, and then the
Activity in turn is calling the Fragment.
So let's look at some code that demonstrates that.
So, onAttach is within a Fragment.
That's an overload.
Sorry, that's an override that says that your Fragment has
been attached to a particular Activity.
That's when it gets called.
So when our Fragment gets attached to an Activity, we're
just storing that Activity as a callback object within the
Fragment, itself.
And you'll notice that the type of that callback object
is this note list event callback.
That's our interface, which is at the bottom of this page.
But we'll talk about that in a minute.
But anyway, we store it as an interface.
And then on our Fragment, in this unlist item click method,
when we need to go and do something about the fact that
the user has selected something, we then can do it
one of two ways.
We can just call "get Activity", and then go call
the do something method.
Or we can use the interface, itself, which we stored as a
callback object, onAttach method.
Now, my personal preference is to use the callback.
I think it's cleaner.
We've defined clear interfaces.
So again we're kind of decoupling
our code quite nicely.
So, you'd call callback.onListClicked(id).
Now remember we talked about at the start in this onAttach
method, we stored this callback, and we said it had
to implement an interface.
Well that's what this bit at the bottom is.
It's the interface that this Fragment is defining.
To say, hey, whichever object I need to sort of inform that
a particular action is taken, that object will obviously
implement this method, itself.
And will pass a note ID, or whatever it may be.
So, communication between Fragments--
don't do it directly from Fragment to Fragment.
Have a proxy layer, and that's typically the Activity.
Because the Activity is the thing that Fragments are
attached to.
So, we talked about some nice things here, but I also
mentioned that Fragments came into Android 3.0.
The good news is that we actually introduced Fragments
in the support library.
So, the support library is a reusable library.
You may have heard me mention it before.
It's really simple to include in your project.
Within Eclipse, you just right click the project, go to
Android Tools, and say, add support library.
It will go and download the latest version.
Include the jar on your project, and set up the
[INAUDIBLE]
as well.
And the name space is then available.
So, we basically put backward compatible Fragments in the
support library.
Now, my recommendation to developers is use the support
Fragments from the start.
Any time you're building a new app, start with Fragments.
Think about tablets and phones as effectively being first
class citizens.
Try not to start with a phone app, and then migrate to a
tablet app later.
You may choose to do the tablet side of things later
on, but at least set up the infrastructure and start using
Fragments from the very beginning.
Because it's a lot easier then to manage a tablet
version of your app.
Whereas if you don't use Fragments, and then later on
you have to go and reorganize all of your activities, and so
on, into Fragments, the overhead is a lot more later
on because you've got a big chunk of code
that you need to refactor.
So, the support library has Fragments.
And one other really important piece of advice is don't mix
and match support Fragments with the native Fragments that
you'll find on Android 3.0 and upwards.
They're different implementation.
They're different classes.
So you kind of mix and match a support Fragment
and a native Fragment.
But we are able to achieve backward compatibility.
And that is how all of our internal apps work, as well.
You've noticed I showed you the people app, which is
obviously an Ice Cream Sandwich app.
Even things like Gmail.
Gmail uses multiple Fragments.
Anyways, so that's backward compatibility.
And that's a bit of a primer on Fragments.
So let's move on to Q&A. Does anyone on the thread here have
any questions on today's topic, or even otherwise?
I'm just going to look at the thread.
It doesn't look like there's been any question posted.
There's a question that says are you going to share this
presentation after the session?
And the answer is yes.
It's available on YouTube because the recording goes up
and it'll be there.
So you can go and view it at any point in time.
Alright, so there's no questions there.
My colleague Anirudh is joining us from Hyderabad.
Anriudh, should we move to Google Moderator?
ANIRUDH DEWANI: Yes, thanks for the [INAUDIBLE]
Ankur.
So, let's take a few questions in Moderator.
The first one, and I'm going to read it loud.
"My music player app (audio streaming) should work while
I'm driving in a car with 3G card.
What the API features should I consider as a developer?
The player apps work excellent with Wi-Fi, and some of the
devices with 3G." Ankur, do you wanna take that up?
ANKUR KOTWAL: Yeah, sure.
Look, in general, there is no no specific API that you want
to use to differentiate your behavior, your app's behavior.
But there's some strategy.
So, with 3G, it's not a good idea to continually
have the radio on.
As much as possible you want to prefetch and chunk it up.
If you can do that when you're on Wi-Fi, that's even better.
But streaming and asking for chunks, or buffers, of data
periodically is probably not the best way to do it.
Because it will have a significant drain on the
user's device.
So yeah, prefetching is one really good thing.
Rater Meyer, our colleague, presented at
Google I/O this year.
And the talk was making good apps great.
So check it out.
There's some great advice in there on how to
achieve some of this.
But what you can do to work out whether you are connected
to Wi-Fi, or 3G, is use the connectivity manager.
And then change your behavior accordingly.
And also keep in mind that if you are pulling down lots of
data, prefetch can be one of those sensitive things.
Just make sure the user's OK with you doing that.
It's a music player, you said, right?
So if the user has 2 GB of music, you probably don't want
to download that on their 3G connection.
Because you are going to blow through their data limit.
Wi-Fi is typically better.
Most people are OK with Wi-Fi.
But again, you need to consider their data limits on
Wi-FI and tune your behavior accordingly.
Also, the last thing is if you are sort of prefetching and
caching, just keep in mind how large your cache is becoming.
You might want to manage that.
You might want to have some maximal threshold set on the
app, itself, so that you're not using up all of the user's
storage capacity.
Is there anything else you want to add, Anirudh?
ANIRUDH DEWANI: Yeah, so, he also asked, what API features
should I consider as a developer?
So, for the music app, the two things I would recommend are
play approach from the rich notification bar.
This is where you handle your users.
And also Lock Screen Wizard if you have your controls there.
Because if somebody's driving a car with a 3G card, or
playing with Wi-Fi, you don't want him to unlock the phone
and go in and stop your music, or do whatever.
So the Lock Screen Wizard and notification bar controls bar
controls are really good.
Those are a couple of API features you should look at.
ANKUR KOTWAL: Actually, also the Bluetooth Music Controls.
ANIRUDH DEWANI: Yeah.
ANKUR KOTWAL: So, we've got APIs around that so you can
respond to buttons on people's Bluetooth headset, so when
they say "Play, Pause, Next Song".
ANIRUDH DEWANI: Alright, thanks for that update.
So, the next question is, "I'm trying to make an app using
Connectivity API.
Is it communication between devices, or is it between
applications?
What is the primary connectivity devices or
applications?
What is the security layer?
Is it on app level or device level?" So, I recently gave a
talk on Connectivity API, dealing [INAUDIBLE].
I think the question is sort of coming from there, as a
follow-up question.
So I'd like to answer this.
So when we say Connectivity API, what we really mean is
wireless API is like Wi-Fi and Google and being which it
would use to communicating between devices, and also with
the Cloud like Wi-Fi.
So is it communication between devices or between
applications?
So, it's really a combination between devices, but we've got
some app level features that you can use.
For example, with Wi-Fi direct, I talked about using
Service Discovery, which is an app level feature.
So, if your app is using Wi-Fi direct to connect with another
device, these are available as framework compliments just
like telephony manager and network connectivity manager.
You have a Wi-Fi peer-to-peer manager available in your app
when you extend [INAUDIBLE].
And you can use this Wi-Fi P2P manager to discover other
services around the [INAUDIBLE].
So the connection is really between the devices because
it's Wi-Fi, but then your application has some extra
features from the framework available on top of which you
can write your application.
And the same goes for security layers.
So if you're using Wi-Fi direct, for example, you have
options to use something for the framework which is like a
key-based authentication or you just use a pin-based
authentication, the general wireless security options
available to you.
But on top of that you build something on your app as well.
You could ask for pin codes or you could ask for user
accounts, or--
And that same goes for [INAUDIBLE] and other
Connectivity APIs.
So [INAUDIBLE], we provide core infrastructure of
security and data transfer using APIs at the device
level, at the framework level.
And on top of that, we give you some more flexibility in
terms of what input.
So, Ankur, would you like to add something to that?
ANKUR KOTWAL: No, I think that was quite comprehensive.
ANIRUDH DEWANI: Alright.
Okay, the next question is, and this is
from Melbourne Jeff.
"I'm trying to use a searchView in an action bar
and my theme is based on Theme.Holo.Light.DarkActionBar.
I have an issue in which I cannot find where to set the
color of the edit text in the search view.
Can I use a custom layout for the searchView?
So, I'm not really sure on the answer for this one.
And I think the answer is that the attributes available on
searchView are not customizable, in the sense
that they are not stylable attributes.
So if you need to change the color, you probably would want
to wrap the view from the layout during runtime.
Programmatically that is on PA you would want to find the
view with the search-View ID inside your onCreate.
And try to grab a reference for the view.
And then verify the properties on it.
By exploring the layout final view
searchView, it's not simple.
What I can do is I'll send a note to our UI team and see if
they have any suggestions on what can be done here.
But I doubt if we can customize the [INAUDIBLE]
using stylable attributes.
Alright, let's go to the next question.
"Hi, I am a beginner in Android development.
And I need some help about getting information from an
URL and displayed in a good UI." So, I think this is a
very basic question, a pretty broad question.
So, in terms of displaying it in a good UI, we have plenty
of UI conferences available and some training classes
available at Android.com.
There are also a lot of patterns and practices which
you could learn about from developers at
Android.com/design.
We have some design guidelines and how to build a good UI.
And some of those sessions we've
covered in our last show.
So you could also visit our playlist.
From Youtube go back and catch up on some of those sessions.
So really, good UI is kind of a broad question.
And there's a lot of resources available on
our developer site.
And you can choose some of these live shows.
When it comes to grabbing information from a URL, so
what you would need is internet permission on your
application, first thing.
And then you could use a standard Java URL connection
APIs, which would allow you to connect [INAUDIBLE]
and you could set the appropriate headers
authentication Steam by using URL connection.
And then download the data as an HTTP response.
So that's the way for doing it.
And one thing to note here is that if you must use
Gingerbread, we recommend that before she I'm going to
different people losing URL connection there so that was
some issues with URL connection client before
[INAUDIBLE].
So, if you are building an app that's meant to be compatible
across the entire range of devices, and it should be, you
should consider the fact.
If you look at the runtime, you could look at the
build of the OS.
And then choose do use a different
client to get the data.
So that's [INAUDIBLE]
client.
Are there any more resources you'd like to point to?
ANKUR KOTWAL: No, just our colleague David Chandler had
written a nice little library to fetch information from the
net, basically passing the URL.
And it just sort of abstracted a lot of detail for you.
Yeah, look up David Chandler on Google+.
And he's got a really nice library that you can use.
ANIRUDH DEWANI: Alright, great.
ANKUR KOTWAL: I can take this one. "Could you please
describe the best strategy for working with Fragments and
loaders is in a map Activity?
Any plans of supporting Fragments in a map Activity?"
So, the honest truth is it's pretty difficult, right?
The map Activity is something that we sort of released
fairly early on.
And it obviously provides the map component part of it.
But it's not a traditional Activity.
What you need is a Fragment Activity from a support
library if you want to use Fragments.
So in some ways, map Activity and Fragment activities are
kind of divergent from one another.
I've seen developers do it with all sorts
of tricks and hacks.
But I also know that there's been some complications in
having to do it that way.
We would love to be able to just use maps in a Fragment.
We, as in Google, haven't published anything yet.
It's actually a fairly common request that we get.
And so, we are.
We're definitely looking into it.
We don't have anything here to announce from a map Fragment
point of view.
ANIRUDH DEWANI: So, I think that was the last question.
ANKUR KOTWAL: Just checking if there's any other question on
the on-air thread, which there doesn't seem to be.
Does anyone live have any other questions before, or we
should wrap up, is the other question?
ANIRUDH DEWANI: So, I think [? Balisabu ?]
from Bangalore who asked the Connectivity API question I
thought we handled.
If you have other follow-up questions, you could
ask us right now.
ANKUR KOTWAL: Alright, well it doesn't look like it.
Maybe he's shy.
Or maybe he just doesn't have any follow-up questions.
On that note, I guess we'll head off.
Thank you for joining us again.
And we'll be back same time next week.
Thanks for joining.
ANIRUDH DEWANI: Thank you.
Bye-bye.