WOJTEK KALICINSKI: Hi, everyone. Please settle down. Nice to see a full room. I wonder if it’s because
of the heat outside, or do you care about
application sizes? Who cares about the
application sizes on Android? [CHEERING] Lots of people. Is there any one
who doesn’t care? AUDIENCE: Yeah. WOJTEK KALICINSKI: Yeah? OK, great, well I hope I’m
going to convince you that it’s really important to do that. And I also hope that you
especially will go to a session tomorrow. I encourage you to all go
and see Ankur and others talk about building for
billions, and they’re going to tell you all
about building apps that will work great
on all kinds of devices for all kinds of markets. But today we’re going to
concentrate on app sizes. And if you think, why
is it important anyway? Why should I care
about app size, and what is app size anyway? First of all, think about this. We’re here in the US, where
there’s Wi-Fi on every corner, in every coffee shop. We have all those
all-you-can-eat data plans. We can download as
much as we want. Well, I just want
you to remember there are parts of the
world where people actually pay for every megabyte
they download. And it’s not always easy
for them to install apps, to keep apps updated,
and it should matter to us developers that
people you your apps, for one, and just keep them updated. And the other important thing is
that people’s phones not always have 16 gigs, 32 gigs
of memory, so they just can’t keep all of the apps
installed that they would want. And, again, if you want
the users to actually use your apps, maybe
you will help them a little bit by keeping your
app just a little bit smaller, so they maybe will be encouraged
to leave your app alone and just not uninstall it. So when I was beginning to
create this presentation, I was talking with lots
of developers at events. And I had asked them this simple
question– how big is your app? And I wonder if I
ask you, just think in your head, how
big is your app? Can you answer that
in five seconds? And if you follow
the number, I’m pretty sure you thought
of the raw APK size. So this is the file that is
produced by Android Studio. How many people
thought about that? Yeah, lots of people,
and that’s correct. That’s a correct answer. It’s technically correct–
the best kind of correct. But application size
is not about the file on the your computer. The user doesn’t really
interact with the file on your hard drive that
Android Studio produces. So the all important
sizes we can talk about is the download size. So, again, if I’m on not a
very good network connection, if I have to pay for
the data that I use, before downloading
an app, I have to actually look and think, can
I afford downloading this app? Can I afford spending this much
money on this many megabytes to download it? And it’s not always the
same as raw APK size, which we’ll find out a moment. Then there is install size. So, like I mentioned, the
other important metric is how much space users
actually have on their devices and how much space your
app will actually take up. And, again, it’s not that easy. So it’s not always the
same as raw APK size, nor is it the download size. And I’ll tell why in a sec. And third of all, the
update size– again, you might think people
download an APK. If they want a new version,
they get a new APK, right? So it must be the same
as the download size, only with a new APK. Well, that’s also not true. Then there’s other metrics,
which are really, really important, like RAM footprint,
how much memory your app uses, how many methods
are in your app. That’s really
important for if you have to use multidecks or not
and probably lots and lots of other metrics for app size. But we’re not really
going to talk about those. We’re concentrating more on
APK size and the four metrics that I mentioned
in the beginning. So before we start,
before we start talking about how to optimize
for all those four scenarios– for APK size, download size and
so on– just a quick primer. Let’s look at the internals–
what’s actually in an APK– so that we can talk about what
we can do with it and what we cannot do. And an APK is really
just a zip archive. You probably all know that. If you unpack it
to a folder or just inspect it in an archive
viewer, first of all, you will find the
application code. So there’s byte code. There’s the DEX files. There be one class as dex. There may be more, if
you’re using MultiDex. That’s pretty much all
your code that you wrote or your libraries that you
imported and so on and so on. There’s also native
code– so native libraries compiled for a specific
CPU architecture or ABI that resides in the Libs folder. And under Libs, you have
all these architectures. So if you have an ARM
device, it needs ARM SO files and so on and so on. Then resources– a pretty big
part of your app, usually. And resources are really
divided into two categories. So in the Rest folder, we
have all kinds of resources, like drawables,
PNGs, JPEG files, layouts, and so on and so on. And there’s also another
file, a resources.arc, which contains mostly styles,
identifiers, and strings. And also this file
can get pretty big. So we’ll talk about how to
reduce that sizes as well. And then there’s all kind of
kinds of miscellaneous stuff, like other assets. You put any file that you use
as a binary stream– anything that’s not an Android resource. So if you want to have a
font bundle with your app or some game data,
some textures, you just put it in the Assets,
and you can open it later in your app. Then there is the
META-INF folder. This contains the
app’s APK signature. And I’m going to talk about
that on the next slide. And then there is
the Android manifest. So when you work
on Android Studio, when you actually
compile your app, Android Studio gets all
pieces of information from all the libraries you
use, from your own app, and it creates this combined,
merged Android manifest that it finally puts in the APK. And one important thing
is if you actually do what I said and
extract the APK and try to inspect this
file, you will find that it’s in another format. It’s actually in a
binary compressed format. So you will not be able
to inspect it easily. And I will talk about
how to do that in a sec. So APK signing,
like I said, there’s a whole folder that contains
the cryptographic signature for your APK. We all know that’s important
so that Android can verify that the app was produced
by you, it comes from you, it can install it securely. And how APK signing of v1
works– the important part to know here is that
Android actually, when verifying the
signature, it goes file by file on every
file in your archive and actually
decompresses the file, then goes over the
full file contents, checks it against the signature. And of if it matches
the signature, it verify it’s correct. So one cool thing that
we can do about this is changing compression levels
on files is actually allowed. So if you have an APK, if
it’s cryptographically signed, you can actually
change compression on a file inside the
archive, and that will not invalidate the signature. Another thing that’s useful to
know is that removing any files is not allowed. So if you remove a file, you
will have to resign your app. And after making any changes
to the archive, to the APK, remember that you have to run
Zipalign after any changes. So even if you like change
something, then sign the image, sign the APK, then you
always have to run Zipalign– so just a few rules. But we have this new APK
signing scheme with version two and Android N, which
changes things a little bit. So it makes it a
little bit difficult, or let’s say impossible,
to actually change anything inside the archive. It’s more secure. The signature is computed over
all the bytes in the APK– so all the content in the APK. And then it’s appended towards
the end of the zip archive– not exactly at the
end of the file, but just before the zip
archive central directory. And, like I said, no
changes are allowed. And what’s more, Zipalign has
to be run before the v2 signing, so that complicates
things a little bit. Fortunately Android Studio
has made some improvements, and I’m going to tell you why. But why am I talking
about all this? Why did I not go
straight to the point and tell you what you can
do to make your APK smaller? I think it’s very important
to understand those things, to understand the role of
every file in this archive. For example, I said
that resources.arc can bet get pretty big. And so lots of
developers noticed that. They noticed that
this file in their app takes even 10
megabytes, 15 megabytes. And they also notice
that it’s uncompressed. So if you create an
APK in Android Studio, and you look at the compression
level of all the files, you will see that this file
is actually uncompressed. So why does it waste
all this space? I just said that it mostly
contains strings, right? So text is compressible. So many developers, using this
knowledge of APK signing v1, they go and compress this
file and problem fixed. APK is smaller. But what I want you to
understand from this talk and bring as takeaway from
this talk is some optimizations are actually
counter-intuitive and not always actually reducing APK
size will help in the long run. So, for example, in this case,
compressing resources.arc is actually a very bad idea. You should leave it as is. It’s optimized for runtime
for running your app, so the framework could
actually memory map the file. It doesn’t have to decompress
when you launch your app. Even worse, think about that. If the launcher has
to read something from this file from your
app– and the launcher has to read your
application name– if this file we’re compressed,
then just to show your app name next to your
icon, this file will have to be
decompressed into memory. So that’s one thing
you just shouldn’t do, even though you can. And we’re going to talk
about all these stages and what magic things
happen that make it so that download size is not
always the same as raw APK size and so and so on. So, for example, Play Store
serves a compressed version of your APK. So, in case, for example,
of this resources file, even though we keep
it uncompressed, when it’s actually
sent to users’ devices, Play Store will compress
the APK beforehand. So we don’t lose any bandwidth. We don’t use any bytes
over the network. So that’s good. The only thing is when
installed on the device, the file will take up
more space on the drive. But, like I said, that’s
actually working as intended. Some cool stuff is also
happening around install time. So, first of all,
remember how I was talking about these
signatures and so on? You can’t change anything
inside the archives. And so because of that,
whenever you install an app, the first and the
most important part of what’s taking up
space on the device will be the raw APK itself. We cannot change it. Even if it contains
resources for other devices, for devices with different
screen densities, with different
CPU architectures, there’s nothing we can
do with it on the device because we have to keep
the signature intact. So a little bit of space wasted. We can remedy that later. Then there was a thing that
we introduced in Lollipop, and that was the new runtime
called ART, which introduced ahead-of-time compilation. So whenever you install an
APK, the ahead-of-time compiler will take all your DEX
byte code and actually compile it down into
native code and store that on your user partition. So, again, this takes up space. This is a derivative of
how big your code is. The bigger your code is,
the bigger the compiled code will be– so another
thing to be mindful about. One note– with M,
we’re, again, getting rid of the ahead-of-time
compilation. We’re using a JIT compiler. So this is, let’s say, not a
concern as much on N devices and going forward. Finally, one curious thing– if
you have any native libraries in your APK, they will actually
get uncompressed, again, on the user partition
and will take up space on the user partition
so that Android can actually load them and access them
with better performance. Again, we cannot touch the APK. Even though we uncompressed
the native libraries, they take up more space. Well, we cannot
remove them from APK. So that’s space wasted. Fortunately, starting with
Marshmallow and above, we can remedy that. And that will be one
of the techniques I will talk about later. And then there’s things
that happen at runtime. So you know a user looks up the
application size in Settings looks at the whole
app size, it’s not just the things
that I mentioned. It’s also everything you create
during runtime– so databases, cached images, anything
you pretty much download from the internet
or generate locally. We’re not going to
cover that as much. but remember this is
a very important part to think about too. And finally, update
size– so why is the update size different
than the download size? Well, I don’t know if you’re
aware, but for many years now, Play Store has
supported delta updates or, in other words,
downloading patches. How that works is, first of
all, when a developer uploads a new APK on the Play
Store, Play Store will compute the difference or
the delta between the old APK and the new APK. It’s just basically
a minute difference. It uses an algorithm to figure
out which bytes are similar and how it can send only
certain bytes over the network. Then the delta can be
additionally compressed. And, finally, the client only
downloads the difference, the delta file, and reconstruct
the new APK on-device. So the final result
is as if the user had the whole APK, the new
signature and everything. But it’s just reconstructed
on the devise from this patch file. And one thing we’ve been
a little bit vague about, like I said– uses
some algorithm, can be compressed and so on. And we weren’t really
telling you what kind of algorithms Play
uses for that, and there was a reason for it. So the Play Store team always
wants to improve on that. And they’ve been
experimenting a lot, and it wouldn’t make any sense
to give out this information and then it would
change the next day. But, actually, let me talk
a little bit about the most recent Play improvements
on that field. And we have a new
delta algorithm. We are using BSDiff now
for computing the deltas. And we’ve seen some
major, major improvements for reducing this delta size. So, for example, a
major update Chrome, so like a big change from
one APK to a second APK, from a certain version
to a newer one, used to take 22 megs
or almost 23 megs on the previous algorithms. With the new one, it’s down to
13 megs With a minor update, the difference is a little bit
different– again, from 15 megs to 3 megs So imagine
instead of downloading a whole tens of megabytes
whole package of Chrome, you download only 3 megs and
have a new version installed on your device. From other news,
we’ve also introduced patching and compression
for the APK expansion files. That’s mostly used for games,
but it’s super important. That’s because games
usually have lots of textures, huge level files. APK expansion files can be
like a gigabyte in size. Imagine this from
version to version. You have to download and
over and over a gig and a gig and again a gig– lots
of bandwidth wasted. We’re now saving over a petabyte
of data per day for our users, thanks to that. But I can talk to you
developers about that. You will be happy that you have
smaller update sizes and so on. But what’s really important is
to show the benefits to users. So starting now, Play Store
will show download size instead of APK size on the Play Store. And in case of an update, users
will only see the update size. So users will be more happy. They will see the benefits
of all your hard work, of all the work of the
Play Store people do. It’s great. But Play Store is just
one component, right? They can only do so
much on the server side, especially with the signing
that has to be left intact. So we also have some
cool improvements in Android Studio 2.2,
which is out in preview now. So they’ve been working on
the whole packaging subsystem and optimizing it to create
APK files that are actually better for computing
of those delta updates. So, first of all, they started
sorting files in the archive so that things don’t
move around a bit, because then the
delta algorithms get confused and can’t figure out
the most optimal solution. They zero out all
the time stamps, zero out any empty space, like
useless comments and so on. And finally, they’re
introducing the option to store uncompressed
native code– so SO files. And I already told
you about that. I will get to that later
in the presentation. So what you can do if you
want to actually measure if your efforts, if what
Android Studio is doing is doing any good for
your update size– and I’m happy to say we
finally released a tool that will help you estimate– let
me stress that– estimate the update size. Again, there may
be new algorithms. There may be experiments
that are going on. But this will give
you a good estimate on the current algorithms and
how they work for your APK. So basically you run against
an old APK, a new APK. You see the size
difference, and you can see if any changes you
make makes sense for that. So now moving on to the
second section, which is kind of like a tips, recipes
on how to actually make your APKs smaller. And let’s go through
some of those things. And first of all,
how many of you had read my articles on
“Medium” on keeping APK low? Some of you? OK, so let me first explain
one point of contention about using Zopfli
compression for APK. So in the articles,
I actually wrote you can reduce the
size of your APK just by using a better
compression method. It’s called Zopfli. It’s an algorithm that was
created by Google engineers. And, yes, it did make your APK
smaller by a couple of percent. Nothing much changed for users. They were decompressed just
as fast and so on and so on. But currently, we advise against
using Zopfli for your APK. So, first of all,
some users did write to me saying that certain
devices and certain versions of Android might have
had a kind of problem with Zopfli-compressed APK. They just threw an exception. So that’s one thing. Another thing is they
take an awful lot of time to compress on your computer. Well, you don’t make a
release every five minutes, so it’s not that of a big deal. But the next thing is
really, really important. So, like I said,
the Play Store team likes experimenting with stuff. And actually, using
Zopfli, because it’s so resource-intensive and
needs so much CPU and memory to compress, in the
future, it might actually make new kinds of differential
updates impossible. So, if you read my
articles, if you are thinking of using
Zopfli, forget about it– just don’t, especially since
the new packaging system in Android Studio actually
experiments when compressing files in your archive. And it actually figures out
the best gzip compression for the files. So that’s also something
new in Android Studio 2.2. Next, images– how many of you
have been to Colt’s session just before? Yep. So I’m just going
to do a quick recap. Remember that you can always
pre-optimize your images. The tools that we currently
have in Android Studio in our build tools, don’t always do
the best job of figuring out the best compression
for images, the best optimizations they can make. So you are free to use external
tools to preprocess images in your drawable folders. They might be a lot
smaller from that. Just remember that
you used to have to add these lines
to your build.gradle. That’s simply because, again,
the packaging system had its own optimizer, and
it wasn’t, let’s say, smart enough to figure out that
if you preprocess an image, then our build tools
process it again. They could actually make
it a little bit bigger. So this actually disables
crunching of images so that your preprocessing
is left intact. I’m happy to say I’ve talked to
the people at Android Studio. And they promised me this
will be fixed for Android 2.2. So the build tools will be
smart enough to figure that out. One easy win you can
have with your PNG images is actually Zopfli-fy them. So, again, this better
compression algorithm called Zopfli, turns
out it’s OK for images. You can use it for PNG files. There’s tools that
do that for you. It’s completely lossless. It doesn’t change anything. The images look the same. They work as fast, and it’s
an easy win for file size. WEBP– it’s an older image
format developed with Google. It gives about 30% smaller image
sizes than JPEGs, for example. And you can use WEBP
for your images. Again, just remember one
thing; support for WEBP was added in Android 4.0, but
only to replace JPEGS or PNG images with no transparency. And that’s because only
Android 4.2.1 added support for new WEBP formats, including
lossless and transparent. So then you can
replace all your PNGs, and also remember to
use it server side. This is really the biggest win,
because if your app downloads a lot of images, if you
know it’s on Android, your server can just generate
WEBPs instead of JPEGS. You will save your users
a lot of bandwidth, and you will save a lot
of space on the device if you cache those images. If you can, on Android 5.0, of
course, use VectorDrawables. It’s a great text-based format. It compresses very well. It’s just amazing for icons . If you are targeting still
previous versions of Android before 5.0, there’s two
ways you can actually use VectorDrawables. So, for some time
in Android Studio, we’ve had support for generating
PNGs from your VectorDrawables. So if you put VectorDrawables
in your Drawable folder and add these lines to Android
Studio, during compile, during building your APK, it
will actually generate those PNGs for you for those
older devices who cannot use VectorDrawables. And after that, we finally
got VectorDrawableCompat, so that’s a more
problematic way of using it from the support library,
where you can actually use VectorDrawables on your
image views, [INAUDIBLE] code. It just works. Of course, there’s a
little bit more to it. But for that, I suggest you
go to Chris Bane’s session, where he will probably
talk about that. And finally,
shapeDrawables– this has been in Android
since 1.0, and I think it’s really under-appreciated. So VectorDrawables are great. You can do lots of complex
shapes in VectorDrawables, but they’re not always
available, like I just said. ShapeDrawables, however,
have been there forever, and they’re great
for simple shapes, like button backgrounds,
borders, gradients. They’re super, super
optimized, super performant. So if you can use a
ShapeDrawable, just please do. And, like I said,
this was a quick recap of what Colt was talking about
an hour ago here on this stage. But since everything
is recorded, I encourage those
of you who haven’t been able to attend the
session or are those of you watching online to go and
check out his session on image compression. So that’s what we can
do to resources, right? But what about code? And really with your code,
with the size of your code, there’s one thing I want
to tell you– use ProGuard. You will hate it, but
use ProGuard, please do. It’s very easy. No really, it’s very easy to
add to your build.gradle file, and then things will break. So, yeah, just add this line. There’s also a new way of
using the built-in shrinker in our tools. So if you do minifyEnabled
true, that enables ProGuard. But you can then go and
actually say use ProGuard false, and this will use our
built-in shrinker. It’s a little bit faster, but
it doesn’t do all the things that ProGuard does. So it just removes classes. It doesn’t obfuscate. But it works better within
[INAUDIBLE], for example. But anyway, whichever
option you decide to use, you don’t have this notion of
ProGuard configuration files. And by default, we
have one in the SDK, which has some of the same
defaults for any Android app. So, for example, the built-in
ProGuard file already has rules that keep all
the setters and getters on your view so that
animations work and so on, because otherwise they
would be optimized the way, and your app will break. But then, if you’re not
familiar with ProGuard rules, it’s a really complex topic. I will not teach you that here. But you can go and look. In your Builds folders
in the Android Studio, there’s actually an
auto-generated file. It’s generated by AAPT,
and it looks basically at your Android. Manifest. It looks at your
layouts, and it generates rules for your
activities, for you views that you use in your layouts. And, again, by looking at those
and by looking at the default ProGuard file, you can learn a
lot and start writing your own. And there’s also
another easy way. If you know that
you’re doing something in your code that
will be optimized away because you access
it by a reflection, for example, there’s a new way. Just add an annotation keep. Use the new build tools. ProGuard will just
leave it as is. It will not be removed
from your code. If you’re writing
libraries for other users or just libraries that are
components in your app, sometimes those libraries just
need their own ProGuard rules so that when someone uses them,
they don’t break their app. And just remember,
be a good citizen. If you’re writing
a library, if it needs ProGuard, you can put
your own ProGuard configuration inside your library, and
then anyone who imports it, it will just work. But you can’t always remove
code because you don’t need it. So sometimes you
actually need the things you are adding to your
project, but it’s not easy to keep track
of all the libraries that bring in other libraries
and other libraries and so on. So we call these
transitive dependencies. And if you add
just one dependency to your build.gradle
file, it may bring in lots and lots of
those transitive dependencies. So if you weren’t aware, there’s
a cool command line command for gradle that will let
you see a tree of all those dependencies that you
bring in with your libraries. And here, the only
advice is just be aware of what you’re using
and what kind of libraries you’re pulling in and
make the right decisions by looking at this. And if you’re still
not sure if what’s inside your APK,
what kind of classes finally make it
through the ProGuard, through the optimizations,
through pulling in other libraries,
there’s a tool that we open sourced
recently called ClassyShark. And it’s basically
an APK explorer. So it will let you go
into your dex files. It will show you
all the packages. They’re great for
debugging ProGuard. And you will do that a lot if
you enable it for your app, let me tell you. And I really encourage
you to try it. So we have ProGuard
for byte code. But if you go through this
pain of enabling ProGuard, you actually get one more
very important thing, and that’s the
resource shrinker. And once you have
ProGuard enabled, you can get another option
called shrinkResources true, and that will go and figure
out which resources in your app are actually referenced
from the code– from the code that’s left
after ProGuard runs its course. And it can remove
any resource that is unused in your code,
which is pretty awesome. And, again, it has
a configuration. So you can add this really
on any resource file, on any XML resource in
your Resource folder. Just add this tools:keep or
tools:discard attributes, and you can make sure that if
there are resources that you want to have in your APK, or if
you explicitly want to remove something from your APK,
that’s where you configure it– so a little bit like ProGuard
rules, only for resources. And then sometimes it happens
that if you pull in a library, even like Google Play Services
or the support library, we offer translations for many
languages in those libraries. But what if you’re making
an app just for one market, just for one language or
just for two languages? If you know that there will
be no users of your app or that you don’t
manage translations for other languages,
then you don’t really need all those resources
from those other libraries, like the Support library,
for all those other languages that you do not support. So just use restConfigs. Just put the names of
the configurations, or the languages
in this example, that you want to
make it to your APK, and the rest will
be simply removed. And one side note here– there’s
a lot of tips on Stack Overflow and other places about using
this for stripping resources for other densities. That was supported a long
time ago in ancient versions of our gradle plugin. You can’t really specify
many densities here. So don’t use it for densities,
unless you specify only one. But that’s kind of a
very advanced usage. So we have restConfigs
for resources. We have shrinkResources,
ProGuard. But there is one very,
very advanced technique that probably not many
people are aware of, and that’s the problem of
sparse resource confligs. And so, if you notice that your
resources.arc file is bloated– it’s very big,
but you don’t know why– it’s worth
trying to figure out if maybe that is your problem. And let me try to explain that. It’s not very simple. So I’m not going to teach
you how the resources file format works. Let me tell you this is
a big oversimplification. But hopefully, it’ll
get the point across. So imagine you have an
app that has five strings. The strings are somewhere
in a string pool. They take up some memory. And then you have
your default config. You have your string–
My App, Hello, Exit, and so on– just labels
for things in your app. But then you decide, well, I’m
adding a new feature to my app. It’s going to be named New
Feature instead of Feature, so you get a new string, right? But this new feature only
works for version 21 and above. So you have a config. You create a new folder under
your resources with v21. And you’re just
switching this Feature to a New Feature in that config. Well, it should take up only
space for one string, right? But it actually has
to keep new entries on all the positions
for other strings that you’re not
using in this config. So you lose a lot of space. It still takes up
a lot of space, even though you’re
just using this to override this one string. And I know these kind of
bytes, who cares about bytes? But if you think about
that, if you have an app that has 3,000 strings, if
you have 50 translations– and there’s a lot of apps
among the top 100 apps on the Play Store. I’m sure lots of them
have even more than that. The cost of adding a single
training for v21, for example, that’s translated
for 50 languages would give you 600
kilobytes overhead, and that’s something
we can work with, especially if we can have
lots of other dimensions than just v21. You can actually
shrink your file a lot. But how do you know
that you’re doing this? It’s not very easy to guess
which string do I remove? And we just recently
open-sourced a tool called ArscBlamer. It’s on GitHub. I’m going to post
those links later. Don’t worry on the
spaces– application on our space for this talk. And basically, it’s
a command line tool. You run your APK through
it, and you get a CSV file. You upload the CSV
to Sheets or use some other program for
that, and it gives you this kind of nice overview
of where the resources are in your application. And if you sort that by
the null entries column, then you can find which configs
are the most sparse in app– so which configs
wastes the most space. So, in this example, if you
look at the right-most column, I can identify that the
string that’s called Apps List is wasting almost 200
kilobytes in my app. Well, 200 kilobytes
is not a lot, right? But the next one, if I
remove descriptive text one, I’m saving one megabyte
from this file. And you can do
this over and over, and remove a lot of
really unneeded data from your resources. And some of our
apps, I want to say, remove 2 and 1/2 megs by
removing just three strings. So that’s a pretty big savings. So that’s that. Let me just say that it really
works for only big apps. If your app is not really huge
with lots of configurations and so on, then probably you
won’t get anything from that. And finally, getting
to the native libraries that I mentioned so many times
already– so since Android 6.0 Marshmallow, we have
this attribute that you can add on the application
tag in your manifest, ExtractNativeLibs false. And basically, what it does,
it instructs just the package installer, the system,
to not copy out those SO files, the native
libraries, at installation from your APK. And the other thing
is things just work. So if you’re using
system.loadLibrary, you just don’t have
to think about it. The SO files will just
stay inside the APK. They will just work. You don’t waste the
space that’s used for decompressing them
somewhere on the user partition. But there are conditions. For this to work,
the SO files have to be uncompressed in your APK. And the other thing is
they must be correctly page aligned using Zipalign. So up until now,
there was no easy way to do that using Android
Studio and our tools. It was just not supported. You have to go and
manually decompress those files and store them and so on. I’m happy to say that Android
Studio 2.2 finally does that for you automatically. So you can enable this option
in the Android manifest and see big gains. If you’re worried that having
uncompressed SO files will just bloat your APK, will make
it really big, that’s true. Raw APK size will go up a bit. But remember that Play Store
compresses data anyway, so the download size
will not suffer, and the delta sizes will
actually be smaller. That’s because the
BSDiff algorithm will be able to
figure out smaller deltas for uncompressed SO
files, so win, win, win. Just a little bit bigger a
file, but we can live with that. And then, I mentioned
before the there’s not much we can do on the
device with resources that are not targeted at
your device’s, let’s say, screen density. And if you produce a fat APK,
if the resources are all there, there’s not really much
we can do about that. Unless you actually split your
APK into many smaller APKs, targeted at those devices. And Android Studio
supports producing two kinds of split APKs. One of them is density-based. So you can actually,
during your compilation, you get smaller files
with resources targeted at specific screen densities. Then you can then upload to
Play Store and use the multi APK feature to serve them
only to certain devices. And then there is the
ABI-based multi APK. So, again, if you
have native libraries for all kinds of
CPU architectures, that will usually be really
big– a really big portion of your APK. So, again, you can split those. You can have multiple APKs that
you can upload to Play Store. And the users with devices
with certain CPU architecture will get only this file that’s
suited for their device. The only thing you
have to remember is every APK has to have
a different version code. So there’s some
scripts that you need to add to your build
APK to make that work. I really encourage
you to go and see my articles on “Medium,” where
I have the necessary snippets. There’s really no time
today on this session to go through all the
code variants for that. And example density
split savings– I just took our Topeka sample app. It’s really image-heavy. So, again, results may vary,
but the original Fat APK was 3 and 1/2 megs. And then if I split that
for different densities, it’s almost 2 and 1/2
megs saving for everyone. And then you can do a lot more. You can do custom multi APK. You can split things
by minSdkVersion. So if you have some features
that only work for 21 and above, maybe it’s
better to start thinking about splitting those up. That’s is pretty
advanced stuff, really, so not everyone
wants to do that. Then for games, you
split by texture formats. You don’t have to ship all
textures to every device. You can recreate
density in and ABI splits using Variance
in Android Studio and customize it even more. And then, for games mostly, you
will use APK expansion files to put all the stuff that
you can fit into the APK to a separate file that’ll be
downloaded from Android Studio. And here’s an
example of this file, of a build.gradle file
that kind of recreates the splits using multi APK. Again, I encourage you to
look at my “Medium” articles. This will be explained
there better. So what’s next? Go through my articles. Go through the
tools that we have. And since we have only
three minutes left, let me just mention that some
of the tools that I mentioned during this talk, we are
actually building those into Android Studio. So you might have
heard at the keynote that there’s a new APK
analyzer in Android Studio. So I’m happy to say you will
be able to download that now and play with it. And what this actually does, it
shows you the compressed size of your APK. It shows you the compressed
sizes of every resource inside your APK. You can browse classes
in your DEX files. You can browse resources, a
little bit like ArscBlamer, and then you can also look
at the Android manifest XML, as it is in this forum that
is compressed in the APK. So I encourage you to try it. It’s still under development. It’s an early preview. If you have any
feedback, if you think you would find some feature
that’s missing useful, please contact us, and I’m
happy to hear of feedback. So thank you very much, and
I’ll be open to questions. [APPLAUSE] [MUSIC PLAYING]