diff --git a/docs/html/images/training/performance/animation-frames.png b/docs/html/images/training/performance/animation-frames.png new file mode 100644 index 0000000000000..846c9fe42159f Binary files /dev/null and b/docs/html/images/training/performance/animation-frames.png differ diff --git a/docs/html/images/training/performance/animation-frames_2x.png b/docs/html/images/training/performance/animation-frames_2x.png new file mode 100644 index 0000000000000..0aba2a5793164 Binary files /dev/null and b/docs/html/images/training/performance/animation-frames_2x.png differ diff --git a/docs/html/images/training/performance/apk-structure.png b/docs/html/images/training/performance/apk-structure.png new file mode 100644 index 0000000000000..75a180cd4711a Binary files /dev/null and b/docs/html/images/training/performance/apk-structure.png differ diff --git a/docs/html/topic/performance/reduce-apk-size.jd b/docs/html/topic/performance/reduce-apk-size.jd new file mode 100644 index 0000000000000..1e73bf017c1ec --- /dev/null +++ b/docs/html/topic/performance/reduce-apk-size.jd @@ -0,0 +1,538 @@ +page.title=Reduce APK Size +trainingnavtop=true + +@jd:body + +
+ Users often avoid downloading apps that seem too large, particularly in + emerging markets where devices connect to often-spotty 2G and + 3G networks or work on pay-by-the-byte plans. This article describes how to + reduce your app's APK size, which enables more users to download your app. +
+ ++ Before discussing how to reduce the size of your app, it's helpful to + understand the structure of an app's APK. An APK file consists of a ZIP + archive that contains all the files that comprise your app. These files + include Java class files, resource files, and a file containing compiled + resources. +
+ ++An APK contains the following directories: +
+ +CERT.SF and
+ CERT.RSA signature files, as well as the {@code MANIFEST.MF}
+ manifest file.
+ resources.arsc.
+ armeabi, armeabi-v7a,
+ arm64-v8a, x86, x86_64, and
+ mips.
+
+An APK also contains the following files. Among them,
+only AndroidManifest.xml is mandatory.
+
res/values/
+ folder. The packaging tool extracts this XML content, compiles it to binary
+ form, and archives the content. This content includes language strings and
+ styles, as well as paths to content that is not included directly in the
+ resources.arsc file, such as layout files and images.
+ + The size of your APK has an impact on how fast your app loads, how much + memory it uses, and how much power it consumes. One of the simple ways to + make your APK smaller is to reduce the number and size of the + resources it contains. In particular, you can remove resources + that your app no longer uses, and you can use scalable {@link + android.graphics.drawable.Drawable} objects in place of image files. This + section discusses these methods as well as several other ways that you can + reduce the resources in your app to decrease the overall size of your APK. +
+ +
+ The {@code lint} tool, a
+ static code analyzer included in Android Studio, detects resources in your
+ res/ folder that your code doesn't reference. When the
+ lint tool discovers a potentially unused resource in your
+ project, it prints a message like the following example.
+
+res/layout/preferences.xml: Warning: The resource R.layout.preferences appears + to be unused [UnusedResources] ++
+ Note: The lint tool doesn't scan the {@code
+ assets/} folder, assets that are referenced via reflection, or library files
+ that you've linked to your app. Also, it doesn't remove resources; it only
+ alerts you to their presence.
+
+ Libraries that you add to your code may include unused resources. Gradle can
+ automatically remove resources on your behalf if you enable {@code shrinkResources} in
+ your app's build.gradle file.
+
+android {
+ // Other settings
+
+ buildTypes {
+ release {
+ minifyEnabled true
+ shrinkResources true
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+}
+
++ To use {@code shrinkResources}, you must enable code shrinking. During the + build process, first ProGuard removes unused code + but leaves unused resources. Then Gradle removes the unused resources. +
+ ++ For more information about ProGuard and other ways + Android Studio helps you reduce APK size, see Shrink Your Code and Resources. +
+ +
+ In Android Gradle Plugin 0.7 and higher, you can declare the configurations
+ that your app supports. Gradle passes this information to the build system
+ using the {@code resConfig} and {@code resConfigs} flavors and the
+ defaultConfig option. The build system then prevents resources
+ from other, unsupported configurations from appearing in the APK, reducing
+ the APK's size. For more information about this feature, see Remove unused
+ alternative resources.
+
+ When developing an Android app, you usually use external libraries to improve + your app's usability and versatility. For example, you might reference the + Android + Support Library to improve the user experience on older devices, or you + could use Google Play + Services to retrieve automatic translations for text within your app. +
+ ++ If a library was designed for a server or desktop, it can include many + objects and methods that your app doesn’t need. To include only the parts of + the library that your app needs, you can edit the library's files if the + license allows you to modify the library. You can also use an alternative, + mobile-friendly library to add specific functionality to your app. +
+ ++ Note: ProGuard can clean up some + unnecessary code imported with a library, but it can't remove a library's + large internal dependencies. +
+ +
+ Android supports a very large set of devices, encompassing a variety of
+ screen densities. In Android 4.4 (API level 19) and higher, the framework
+ supports various densities: ldpi, mdpi,
+ tvdpi, hdpi, xhdpi,
+ xxhdpi and xxxhdpi. Although Android supports all
+ these densities, you don't need to export your rasterized assets to each
+ density.
+
+ If you know that only a small percentage of your users have devices with + specific densities, consider whether you need to bundle those densities into + your app. If you don't include resources for a specific screen density, + Android automatically scales existing resources originally designed for other + screen densities. +
+ +
+ If your app needs only scaled images, you can save even more space by having
+ a single variant of an image in drawable-nodpi/. We recommend
+ that every app include at least an xxhdpi image variant.
+
+ For more information screen densities, see Screen Sizes and + Densities. +
+ ++ Frame-by-frame animations can drastically increase the size of your APK. + Figure 1 shows an example of a frame-by-frame animation separated into + multiple PNG files within a directory. Each image is one frame in the + animation. +
+ ++ For each frame that you add to the animation, you increase the number of + images stored in the APK. In Figure 1, the image animates at 30 FPS within + the app. If the image animated at only 15 FPS instead, the animation would + require only half the number of needed frames. +
+ +
+
+ Some images don't require a static image resource; the framework can
+ dynamically draw the image at runtime instead. {@link
+ android.graphics.drawable.Drawable} objects (<shape> in
+ XML) can take up a tiny amount of space in your APK. In addition, XML {@link
+ android.graphics.drawable.Drawable} objects produce monochromatic images
+ compliant with material design guidelines.
+
+ You can include a separate resource for variations of an image, such as + tinted, shaded, or rotated versions of the same image. We recommend, however, + that you reuse the same set of resources, customizing them as needed at + runtime. +
+ ++ Android provides several utilities to change the color of an asset, either + using the {@code android:tint} and {@code tintMode} attributes on Android 5.0 + (API level 21) and higher. For lower versions of the platform, use the {@link + android.graphics.ColorFilter} class. +
++ You can also omit resources that are only a rotated equivalent of another + resource. The following code snippet provides an example of turning an + "expand" arrow into a "collapse" arrow icon by simply rotating the original + image 180 degrees: +
+ ++<?xml version="1.0" encoding="utf-8"?> +<rotate xmlns:android="http://schemas.android.com/apk/res/android" + android:drawable="@drawable/ic_arrow_expand" + android:fromDegrees="180" + android:pivotX="50%" + android:pivotY="50%" + android:toDegrees="180" /> ++
+ You can also reduce your APK size by procedurally rendering your images. + Procedural rendering frees up space because you no longer store an image file + in your APK. +
+ +
+ The aapt tool can optimize the image resources placed in
+ res/drawable/ with lossless compression during the build
+ process. For example, the aapt tool can convert a true-color PNG
+ that does not require more than 256 colors to an 8-bit PNG with a color
+ palette. Doing so results in an image of equal quality but a smaller memory
+ footprint.
+
+ Keep in mind that the aapt has the following limitations:
+
aapt tool does not shrink PNG files contained in the
+ asset/ folder.
+ aapt
+ tool to optimize them.
+ aapt tool may inflate PNG files that have already been
+ compressed. To prevent this, you can use the cruncherEnabled
+ flag in Gradle to disable this process for PNG files:
+
+aaptOptions {
+ cruncherEnabled = false
+}
+
++ You can reduce PNG file sizes without losing image quality using tools like + pngcrush, pngquant, or zopflipng. All of these tools can + reduce PNG file size while preserving image quality. +
+ ++ The {@code pngcrush} tool is particularly effective: This tool iterates over + PNG filters and zlib (Deflate) parameters, using each combination of filters + and parameters to compress the image. It then chooses the configuration that + yields the smallest compressed output. +
+ ++ For JPEG files, you can use tools like packJPG that compress JPEG + files into a more compact form. +
+ ++ Instead of using PNG or JPEG files, you can also use the WebP + file format for your images. The WebP format provides lossy compression (like + JPEG) as well as transparency (like PNG) but can provide better compression + than either JPEG or PNG. +
+ ++ Using the WebP file format has a few notable drawbacks, however. First, + support for WebP is not available in versions of the platform lower than + Android 3.2 (API level 13). Second, it takes a longer amount of time for the + system to decode WebP than PNG files. +
+ ++ Note: Google Play accepts APKs only if the included icons + use the PNG format. You can't use other file formats like JPEG or WebP for + app icons if you intend to publish your app through Google Play. +
+ ++ You can use vector graphics to create resolution-independent icons and other + scalable media. Using these graphics can greatly reduce your APK footprint. + Vector images are represented in Android as {@link + android.graphics.drawable.VectorDrawable} objects. With a {@link + android.graphics.drawable.VectorDrawable } object, a 100-byte file can + generate a sharp image the size of the screen. +
+ ++ However, it takes a significant amount of time for the system to render each + {@link android.graphics.drawable.VectorDrawable} object, and larger images + take even longer to appear on the screen. Therefore, consider using these + vector graphics only when displaying small images. +
+ ++ For more information on working with {@link + android.graphics.drawable.VectorDrawable } objects, see Working + with Drawables. +
+ ++ There are several methods you can use to reduce the size of the Java and + native codebase in your app. +
+ ++ Make sure to understand the footprint of any code which is automatically + generated. For example, many protocol buffer tools generate an excessive + number of methods and classes, which can double or triple the size of your + app. +
+ +
+ A single enum can add about 1.0 to 1.4 KB of size to your app's
+ classes.dex file. These additions can quickly accumulate for
+ complex systems or shared libraries. If possible, consider using the
+ @IntDef annotation and ProGuard to strip enumerations
+ out and convert them to integers. This type conversion preserves all of the
+ type safety benefits of enums.
+
+ If your app uses native code and the Android NDK, you can also reduce the + size of your app by optimizing your code. Two useful techniques are + removing debug symbols and not extracting native libraries. +
+ +
+ Using debug symbols makes sense if your application is in development and
+ still requires debugging. Use the arm-eabi-strip tool, provided
+ in the Android NDK, to remove unnecessary debug symbols from native
+ libraries. After that, you can compile your release build.
+
+ Store {@code .so} files uncompressed in the APK, and set the {@code
+ android:extractNativeLibs} flag to false in the {@code
+
+ Your APK can contain content that users download but never use, like regional + or language information. To create a minimal download for your users, you can + segment your app into several APKs, differentiated by factors such as screen + size or GPU texture support. +
+ +
+ When a user downloads your app, their device receives the correct APK based
+ on the device's features and settings. This way, devices don't receive assets
+ for features that the devices don't have. For example, if a user has a
+ hdpi device, they don’t need xxxhdpi resources that
+ you might include for devices with higher density displays.
+
+ For more information, see Configure APK Splits + and Maintaining Multiple APKs. +