DAN GALPIN: Can you hear me? All right. I'm Dan Galpin,
and Lisa Wray and I will be giving you a tour of
the highlights of the latest platform and support
library updates. And we've got so much
to cover, so I'm just going to jump right into it. So one of the biggest
changes to know is we added adaptive
launcher icons. And this is a big
deal because if you have any of these phones
from these lovely OEMs, you saw they are using their
own custom launchers with custom icon shapes. And Android icons, shapes
and sizes are all random. And so what they would do, like
with Chrome and the Play Store here, they would
shrink the icon, and stamp on it a random color
or shape that they choose. And we thought, you know, we can
do something better for this. So what we did is we
created adaptive icons. And to enable this
kind of customization, your app provides
icons in two layers-- background and foreground. So if the OEM defines a
rounded rectangle mask shape, the user will see this. And if they define
a circular shape, it's going to look like this. And this is cool. And this goes every
single way or place your icon appears in the system
UI, such as inside the setting app list, the recents
or overview title bar, and your shared sheet dialog. So to support wider
ranges of icon sizes, because not every
launcher makes the icons the same size, as you've
also probably noticed, bigger than 48 DP,
we now recommend that apps contain an icon
asset of at least 72 DP in size with a visible area. Sort if an OEM or
third party launcher wants to render icons in 60 DP,
it will not be super sampled. Now, the actual size of this
foreground and background layer that we want to
update to is 108 DP. And we recommend that both
the foreground and background layers are actually padded
with 25% of the extra image around each side. And the reason we do
this is because we want to use it to add delightful
animations such as parallax and pulsing. And this is just an example. No, we haven't actually added
this to a shipping launcher, but someday we might. So you can now
control how your brand is going to look no
matter what icon shape your OEM chooses
while integrating well into their visual design. This is actually important. So here's what we've done. We've added this adaptive
icon drawable class to Oreo, and it supports the foreground
and a background inner tag that supports one
drawable attribute. And also as a [INAUDIBLE]
to help us out, we added this
fractional inset value. And this means your insight can
now be density invariant, which is really, really cool. So as it turns out,
18 over 8 is 16%. So if you use this value to pad
your 72 DP launcher icon there will be no APK size increase
from a non-adaptive icon that's big enough. But better yet, the
really cool thing is that because these
are only used in O, in Android N the vector drawable
became expressive enough to support most
of the SVG format. So you can actually
now make vector icons, which is really cool. So once again, O made a
bunch of critical changes to other areas, too. Not just adaptive icons,
we made critical changes to notifications. Now, in previous
releases of Android, the user could only block all
the notifications for an app for sending a
spammy notification. But in Android O, of
course, we introduced notification channels,
which are named categories of notifications that share
the same behavior so users can control them. And the user can also click
here to see all the categories. And clicking on the category
reveals per-category things like vibration and
sound, et cetera. And of course we
also added these dots in the launcher, which
are a low-stress way to see if apps
have notifications. I don't have to look how
many numbers there are. Long pressing the icon also
reveals the notification. And widgets can also
really be installed easily in this way, which is
so cool because people don't have to stress and
figure out how to install them. All right, and
all the stuff used to customize per
notifications now applies to the whole channel. This is pretty cool. You can set all this
stuff on a channel. OK, I do have a bullet
point slide here. I'm sorry. But seriously, don't overwhelm
your users with channels. Make the distinctions
between them make sense. Give them reasonable defaults. And of course, you can
use notification compact to set channel information. And remember that if
you don't use channels and you're targeting
Oreo, your notifications aren't going to show up. All right, let's talk about
shortcuts and app widgets. So way back in
Android 7.1 we added these nifty launcher shortcuts. And users can drag them and
pin them to the launcher. An app could request that
a shortcut gets pinned, but there was no
indication to the app that it actually
worked, and the user wasn't notified that it was
happening, which wasn't really great for users or developers. And it doesn't work anymore
if you're targeting O. So we now have the new
way with Shortcut Manager. And it has an API. And it takes the same shortcut
info as we used in Android 7.1, but the launcher
will now ask the user whether to add the shortcut
and where to place it. So the app can now adapt
to-- and the app also has the ability to actually
update the shortcut icon later, as well, with this. And custom shortcuts
are also in 7.1. It allowed shortcuts to be
added from the widget tray with an optional
configuration screen. And the Oreo API is an
improvement there, as well. As before, you register the
custom shortcut activity with the Create
Shortcut Intent folder. And in 7.1 it would return
the shortcut as intent extras directly to the activity
return, which is OK. But now we wrap all
of that functionality, which also allows the app
to update the shortcut. So again, just making
the launch better. And this has been a
really long time coming. But we actually
have a way for you to surface your app
widgets in your app. You no longer have
to beg the user to find it in the launcher. You can say, hey, I've
got an app widget, please install it
on your behalf. And they get prompted, and they
get added to the home screen, and it's just awesome. I can't believe it
took us this long. All right, let's
talk about Autofill. All right, so apps that use
standard views automatically work with Autofill. But you can help it do a
better job by providing hints, like postal address. You could also mark fields
that Autofill should ignore. You can integrate
it more deeply. So you can actually request
Autofill in your app. And you can use Autofill
on completely custom views such as those are drawn
with OpenGL or Vulcan by providing an Autofill
virtual structure. And no matter how
you build your apps, you should really
consider doing this. And this is kind of cool. You have a website, the
Google Autofill provider can actually share
credential information between your web and your app
if you create a digital asset link. And this is pretty
straightforward. You've got to put something on
your server, some JSON here, which allows you to define that
you want to share your login credentials between your
website and your app. And then you go and
modify your manifest with this string that points
to a similar JSON resource that contains a list of web
targets and permissions just like what you've
hosted on your website. And that's it. With these two steps you
can share credentials between your website. And this works for Autofill,
and it's also the first step in implementing Smart Lock. So you might want
to do that also, which this lets your users
automatically sign in. But if you don't want to go
all the way to Smart Lock, this is a really cool way of
leveraging that credential information between your
mobile app and your website. Some other O stuff. We added a whole bunch more
cool StrictMode behavior, which is great. We now actually-- this is great
for finding bad app behaviors. We can detect unbuffered
I/O with thread policy, and VM policy allows you
to detect untagged sockets, as well as when a content URI
is sent that doesn't grant the calling app read or write
permission, because it's not very useful to have a call-- yeah. And we've also added
seekable file descriptors from document
providers, so you can use this for large remote
sources such as big audio and video files. OK, another thing we did is we
actually added proper support for caching. So the quota here can change
depending how frequently the user actually
interacts with your app and the amount used while
the allocate actually takes deletable cache into account. So pretty slick. And there's tons
of more stuff in O, I'm not going to go
through it all here. Most of you have seen
a lot of this stuff. But we have enhancements
to accessibility, including the ability for users
to add an accessibility button on devices that have soft
navigation, something else for that bar. Paging and content providers. A bunch of great stuff
to make the runtime faster as I mentioned before,
such as a concurrent copying collector and a whole
bunch of changes in media. All right, but let's get
into the support library. So you know what I'm going to
say here, which is devices that are running SDKs less than
14 comprise less than 1% of the Play Store active users. So we've updated the support
libraries [INAUDIBLE] SDK level. And as you might have guessed,
we got rid of these two guys. We'll be focusing
on the SDK versions that most developers
are actually targeting. So the minimum
version is now 14, and Google Play services
also recently dropped that support in version 10.2. However, you can still use an
older version of the support library if you
really, really want to still target
gingerbread [INAUDIBLE].. And dropping API 14 gives
us a bunch of benefits. Removed over 1,400 methods. And remember, we still have
a 65k method, [? decs ?] limit on API is less than 21. And there's more to
go in later versions. Our public API surface reduced
by 30 classes for 100 methods. And what we need to do
now is you can still use a lot of these
things as they are, but you should start
actually getting rid of the deprecated stuff
because we're actually going to get rid of it to
even make things smaller. And of course, we're using
the Google Maven repository for this, which you can
specify in your build gradle. This is on Android Studio 2.3. And if you're using
3.0 plugins you can actually just say Google,
which is kind of sweet. All right, text and fonts, which
is one of my favorite things. I love fonts. In the old world,
how many people actually did custom fonts
on their Android app? Yeah, a lot of you. You know how much
it kind of sucked. You had to load typeface
into the constructor, and then you could go and
use this custom text view everywhere, and you know, yeah. But now we have a
new resource type which both accepts single font
files as well as families. And font files
get a resource ID. And you can also
make these families, which are groups of
fonts that are together. So you can define
them and say, like, I want normal to be this font,
and I want bold to be this font, and you know, et cetera,
very, very sweet. And this one generates
r.font, .myfont. And this is super
easy to use in XML. The text view font
family attribute is used and it can handle families,
which is even better. So you just get to
use the same thing you've been using all the time. Both textile attribute as well
as style spans are supported, which is really great. And you can also define
them in styles as usual. You can use them in code
by resources compat. And more importantly,
it's supported on API 14 above with the support library. So go out there
and use more fonts. And the only problem, of
course, is that fonts actually bloat the size of your app. So we had to think about this. The top 25 fonts in
Google Fonts actually average 500 kilobytes or more. And they're not optimized
for mobile, necessarily. So we're like, what do we do? How do we fix this? So of course we added
downloadable fonts. And the font provider fetches
and service fonts to your apps. So more importantly, you don't
have to bundle them anymore. And this is really cool too,
because this font provider's actually shared between apps. So it gives you memory,
gives you network, it gives you space savings. And with Google Play
services and Google Fonts you get over 800 fonts. So it's really nice. And in code you can
request these fonts using a font request,
which [INAUDIBLE] things like authority, and
package, inserts, or security, and callbacks for
success or failure now exist. And of course you just
use fonts contract compat, and you do control what thread
this runs on, so don't run it on the UI thread. And this you can
also throw it in XML. So it's really easy to use. The search is actually
a string array. And it actually is pretty cool. So we've also done
full integration with Android Studio. It looks like this. We have some boring
text in a layout, and we go and select More Fonts. You see where you've
got Google Fonts here, you've got this beautiful
selection of fonts. But it's so many I'm just
going to search for one. There we are. Yesteryear, we say
downloadable font, and it's going to show
up in the layout editor, and then it's going to add
this beautiful file-- actually two files-- to the project. So pretty sweet. So check out the sample
app, the Google Fonts docs, and the guide on
developer.android.com for all the info. And best of all,
downloadable fonts are all supported
in API 14 plus. All right, so
there's nothing worse than when someone
sends you a message, and you get a box that
provides no information. We call this tofu
because it's box. So it's time to
get rid of this-- and this is there because
the system is always bundled the emoji font, and
unicode keeps adding new emoji, and it's impossible
for us to keep up unless we can make it
show up in older versions. So the support library has
access to this new font. And it checks per glyph
if it can be rendered, or it replaces this with
these emoji [? stamps ?] if it can't, which is great. There are two ways for
you to use it in your app. The download
configuration just happens to integrate with
downloadable fonts. So you just add
your dependencies, you make your font request,
and you initialize it in your application on create. Very simple. It means you don't
have to actually bundle the emoji font with your app. But you can. If you're targeting a non-GMS
devices, you can do that. It'll add about 7 megabytes. And you configure
it in a similar way, again, with a just
bundled emoji pack config. So very straightforward. Again, you can just-- you have
to use these emoji text views. Instead of text
view, you can use emoji edit text, and emoji
button instead of edit text and button. And you don't have to use these,
but if you don't use them, you have to integrate it into
your own custom views yourself. So we do supply these
to help you out. And so now tacos and
unicorns both exist. Important things for
us to get across. So check out this sample
on [? DAC, ?] there's more information. Now, one caveat here. We didn't actually back port
this all the way to kit-kat. This does require API 19 plus. So that's the one
minor caveat here. But again, so get tofu
on some older devices if you try to set this
up to use it both ways. TextView autosizing. This is a feature I've wanted,
and how many people have built their own TextView autosizer? Yes, I've been wanting
this feature forever. So I'm so happy that it's
finally here in the platform. Text actually resizes to
fill in its container. I can't tell you how excited I
was when we built this thing. So you use auto size
text type uniform. And you can use an
array of preset sizes or an array of values, or
a set of min and max size with a stack. That's really easy. And once again, we've
brought this to API 14 plus. We bring improvements
to VectorDrawable. This gives it feature parity
with support for fill types. So if it looks like
this in Android Studio and you shove this
in, this might be what you get before because
you get these weird artifacts because we're using these
even-odd fill rules, and we didn't support that. There was a big TBD in
the source code of you went and looked. So a fill rule defines
how this render designs, which of the regions are
inside, and which are outside. And we added support for this,
which we actually fixed finally in SDK 24 and we've
backported it to 14 plus. So this is really cool. It means your vectors are
more likely to work, which if you've ever had to deal
with, you know how awesome this is that we finally fixed it. We also ported the stuff
from animated drawable compat for path data morphing. And this is really cool. This is an example of using
shapeshifter, Alex Lockwood's tool, to generate compatible
images with matching path formats. And let's look along at what's
going on here at the XML level. We start with our
vector, defining our starting image, a buffalo. We've extracted the path data. And for the buffalo,
hippo and elephant, they're string resources. And then we use an
object animator. Pretty sweet. So again, we're
specifying the path values to morph a buffalo to a hippo. And once again, we
tie it all together in an animated vector XML. Now we can actually do stuff
with bundled XML formats to make this even cleaner. So again, we can actually
use an attr element here, and it in-lines the XML
from the buffalo drawable. And then we can do the same
with the animation attribute. And so we have a
bundle package that actually includes the entire
vector drawable animation, which is really cool. We also have a
path interpolator. Once again, that's parity. So this one is kind
of complicated, but we can take a simple
example and show how it works. So for a UX designer, it wants
to shrink a [INAUDIBLE] square, but they want to have an
interesting acceleration curve as it shrinks, we can
use a path interpolator. And this is kind of cool. We can make a curve that
that drops off quickly, snaps back a small amount
and slowly tapers off. Here's our morph animation,
and we'll set the interpolator to be our path interpolator. So once again we can bundle
it in a single file using these attrs, and this
results in this slightly more cool animation. Still just a rectangle. OK, final thing I'm
going to talk about is transition support library. So if you've noticed
that we actually added some additional transition
type in Lollipop and above, things like path motion, and
propagation, and all of this is available in the
transition library. So when you use the transition
XML with a support library, you have to specify this
dash dash no dash version transitions as an APT option. And after that, you can use
all the same transition XMLs that you use for platform
transition API on API 14 and above. And the reason I'm
talking so fast is because I want to get my
amazing collaborator on here, who is really the
star of the show. I'm just the opening act. I'd like you to welcome
Lisa Wray, who's going to talk about some
amazing animation features. LISA WRAY: Thank you. So I only have one
thing to talk about, and that's physics-based
animations. So we've known for a
long time that motion is important in material design. Natural movement inspired
by forces in the real world. And I've tried, I really have. But it hasn't always been easy. So the support library has now
introduced two implementations of physics-based animation. Not approximations of
motion with a stock interpolator, but motion
based on natural forces. Could you have done this before? Maybe, but it wouldn't
have been easy. With dynamic
animation, these ideas are now central to the
way we can animate. So my hope is to make
this type of motion easy for you to
think about and easy for you to use in your app. Some things that are easy
now that were hard before. Responding to user interaction--
by which I just mean a touch-- chaining animations,
modifying them on the fly; getting great natural movement
with much less visual jank. So I'm going to step through
the mechanics of the two dynamic animations we have right
now and then we'll mix it up. So the first, a fling animation. It starts with an initial
velocity, it slows down, and it ends gradually. So every time that
color changes, it's starting a new fling. And here's the simplest fling
that you can possibly make. Ball is a view. Translation y is the
property we're changing. And its velocity is
pixels per second. I discovered while
making this that pixels are a lot smaller
than I thought. Everything else is defaults. And so that's what you just saw. You can customize
a fling by changing its friction, the factor
by which it slows down. So here's an
example of friction. So from left, you
have high friction to low friction on the right. So the less friction
that you have, the more distance your view will
travel for a given velocity. And here's a spring animation. And it looks just
like what we'd imagine from the motion of
a physical spring. It exerts a force back to
the endpoint of the spring, and you can even get a bounce. So every time the color changes
that is a new spring animation. And here's the simplest
spring you can possibly make. Ball is a view, translation y
is the property we're changing, and zero is where
it's going to stop, which is its final
translation at equilibrium. And its velocity is
pixels per second. And everything else is defaults. And it just goes. So to customize
this, you can call getSpring on your animation,
and that gives you its internal spring
force object. And that has a damping
ratio, a stiffness, and you can see that
the final position. Damping is the ratio by
which the size of your bounce is reduced over time. And the default
is medium bouncy. In general, the lower the
number, the more oscillation you'll see-- a.k.a. bouncing-- before the force
is going to reach equilibrium. At 1 you get critical damping,
which means no bounce, and at 0 you get no damping,
which means infinite bounce. Don't do that. In general, please do not
under-damp your views. This crazy bouncing is what made
me think at first, why on earth would you ever want
to do this to a view? So try little or
no bounce, and I think you'll be surprised how
useful this animation can be. Stiffness is like the
stiffness of a physical spring. So for a given
starting velocity, how far will it travel
from the endpoint, and how fast will
it be pulled back? This example has no
bounds so that you can see the difference
in the stiffness better. The lowest stiffness
is on the left, so it's traveling further. The highest stiffness
is on the right. And you can also create your
own external spring force in order to share it
among multiple animations. We'll see why you might
want to do that in a moment. So one thing you might want
to do with these animations is allow user input. So velocity tracker is
one option to handle this. It's an older, but a goodie. This class has been
around since API 1. It does what it says on the tin. It tracks velocity
from a user's touch. You can also use just
your detector if you only care what the end
state of the fling is because its fling
callback has velocity. So how would you use this? We're going to go with
velocity tracker for now. You'd use it in a touch
listener on the parent of the view you want to track. Parent is important. Call velocity tracker
to obtain to get an instance of the
tracker, then you can feed in the user's touch
events, starting with down and continuing with move. Then in action up you'll call
compute current velocity, and it will compute a
nice velocity for you. After you're done
make sure to clear it. That velocity is going to come
in two components, x and y. Then you're going to start
two dynamic animations at the same time-- one for the x velocity and
one for the y velocity. This would be a good reason
to share a spring force. They're going to
run simultaneously. And as you can see,
this is enough. This gives you a smoothly moving
interactive two-dimensional animation . As you can see, it
works pretty well. Just be careful when you
fling because they do not automatically stay
on the screen. And when they're gone,
they do not come back. Just like other animations
you're familiar with, dynamic animation also has
end and update listeners. So that's how I was
chaining them in my earlier demonstration and
changing the ball colors to repeat over and over again. So let's chain two
fling animations. We're going to
fling just as we did before using the velocity from
our drag listener and velocity tracker. And we're going to create two
fling animations at the same time-- one for x and one for y-- to get natural movement. Then we're going to stop the
first animation at the edge and create a new one in
a different direction, giving the impression
the ball has bounced. This time we'll add an update
listener and an end listener to each of our flings. On each update,
we'll check to see if the ball has slipped outside
the bounds of its parent. There's probably a
better way to do this, but that's an exercise
for the reader. If it did go outside we'll
cancel the animation. That means we'll get a
callback to on animation end. If we canceled it,
meaning it hit the edge, then fling it back. As you can see, I made an
extension function on view here because I got
tired of typing. We'll use the
velocity past here, which is the remaining velocity
from the canceled animation. And we'll use it in the opposite
direction, which is the minus sign you'll see there. Of course, it's not
exactly that simple. What this does is it flings
the ball straight back at you because it reverses both
of its velocities, x and y. So what we really want
is natural reflection. We want it to only reverse
its velocity on one axis but continue on the other. And that's what will give us
this 90-degree bounce angle. So it's not too hard. It looks like this. If it's hitting the
horizontal edge, reverse x. Otherwise, reverse y. And we get a nice
reflection or bounce. And it also works with
different animations. Ever seen something like this? There's an app that keeps trying
to do this on my home screen. I don't why I'm
encouraging you to do this, but it's interesting
because it's quite simple. And it's sort of a
sticky effect, where if you fling it to the edge,
it sticks there and absorbs the extra momentum
with a spring bounce. So if you do this, it's going
to look something like this. The thing to note
here is that we're using the ball's current
translation value as its end value for the spring. So we're going to fling as
before, put an end listener. And then when we
get the callback, go ahead and oscillate until you
reach equilibrium, dissipating the remaining velocity. Chaining springs. There was a really cool
demo in the Google I/O talk I went to of three balls
connected with springs. I'm not going to
explain that here because they did a great
job already in that talk. So if you want, go look
it up and then come back. So here's a real
layout from an Android app using the same effect. This is inspired by a screen in
the plaid app by Nick Butcher-- sorry, Nick-- where as part
of the screen transitions, there's several onscreen
components that translate up subtly one after another. So in that effect, the
distance translated, the delay of each element,
and the interpolation used to simulate acceleration
and deceleration are all hard coded by hand. That's a pain in the butt. Here it's all done with
the same chained spring we just saw with the balls. I'll go through how that works. So what's actually
going on here? These two springs are almost
exactly the same effect. Obviously the top ball,
the blue ball, is the lead, the yellow ball follows
it, and the green ball follows the yellow
ball, almost as if they're chained together
with bouncy springs. In the actual app
example, the lead view is the headline and icons. The next view, the
paragraphs, follow it, and finally, the FAB is
following the paragraphs. You can see here that there's no
rule that these views actually have to be in a line
in terms of position. They can be anywhere. What matters is the
propagation of effects from one animation to the next. So how do we do this? Instead of a touch listener,
I started with a fixed spring animation on the headline. The thing to notice
here is that instead of giving it a velocity,
I gave it a start value. Basically I said, pull
the spring back this far and start it there. And I gave it an
update listener, which we've seen before. Then I made a spring
animation for the paragraphs, exact same thing. In the listener getting
callbacks from the headline, I call animate to final position
on the paragraph animation. This [? isn't ?] a really
important and useful method. So it's going to do two things. One, it sets the
new final position of the paragraph spring
to the current position of the headline animation. And two, it starts the paragraph
animation if it hasn't yet. And then finally, we'll do
the same thing for the FAB. We'll set an update
listener on the paragraphs and chain a spring
animation to that. And that's how chaining works. The difference here from what
we were doing before with flings is that those animations were
subsequent one after another, and these are actually
happening simultaneously. You might also notice if you're
looking very closely that I also used a spring on
the alphas of the views and on the scale of the FAB. So what else can you animate? And you can animate a lot
of built-in properties. Certainly everything I can think
of flinging or springing off the top of my head
you can animate. Alphas, translation, rotation,
scroll, scale, and x, y, and z, which are absolute
positions, including translation. But if you want to animate
something even crazier or just make a custom property
that groups a couple of these, you just make an instance
of float property compact. You also need to set the
minimum visible change so the animation
knows when to stop and doesn't keep on animating
tiny, tiny bits forever. You can also start every dynamic
animation at a particular start value, give them a
minimum and maximum, and finally cancel
your animations. Because if your user quits the
activity while they're running, your app will crash. So cancel them. These APIs are available
from Jellybean and above. And I'm sure you
got all of that. But if you didn't, all the code
for every one of these demos is on my GitHub,
lisawray/physics-playground. So my takeaway here that I want
is physics-based animations. They're not toys, and
they're not just for games. They're way more
than bouncing balls. They're a great way to
bring natural motion and interaction your current UI. So I look forward to seeing
what you make with them. Thank you. [APPLAUSE]