Codementor Events

A better way to package your app

Published Mar 15, 2019
A better way to package your app

Thanks to its openness, Android has seen remarkable growth over its first ten years. There are a huge range of devices to choose from and many apps and games offered by a thriving ecosystem of developers that bring those devices to life. As a developer, you want to ensure that your users have the best experience possible and that your apps run as well as they can on all these devices. You also want to encourage as many users as possible to install your app; you want them to keep using it; and you don’t want them to uninstall for reasons beyond your control. The way Android apps have been published and distributed to date leaves room for improvement in all these areas. I’d like to take a look at some of the challenges developers face and tell you what Google is doing to help.

The problem

Here’s the problem: apps keep getting bigger and bigger. In fact, since 2012, the average app has grown 5x. This is understandable; you want to add cool features and new content to your app to keep your users coming back and to keep your business growing. Devices keep getting better, and you want to take advantage of the shiny new functions. The device ecosystem has also become more diverse, so you end up duplicating code and resources in your app to make it run just as well on a small screen as it does on a large screen, just as well on one CPU as on another, and so on.

Apps getting bigger wouldn’t matter much if every user had unlimited storage, unlimited data, and ever-present fast connections. Sadly, this isn’t the case (maybe one day!). Looking at the graph below, you can see the size of an app on Google Play is negatively correlated to its install conversion rate. That means that as apps get bigger, their install success rate goes down. This happens for many reasons. Many users don’t have enough free space on their device. This impacts users with entry level devices with modest device storage and users with high end devices who fill their devices with photos, videos, and other media — which all keep getting higher in quality, taking up more space on each device. Users also don’t want to use up expensive data plans and wait on slow connections for larger apps, especially in emerging markets.

install rate graph

So we know the install rate goes down for larger apps. Our user research also shows that app size is also a leading motivator in driving uninstalls, which makes app size an increasingly important factor for apps that are focused on retention. Think about your own experience. When you’ve tried to install an app, have you ever seen a warning from Google Play prompting you to uninstall apps you don’t use to free up space? Millions of people see these warnings every day and they’ll often uninstall the biggest apps and games when presented with this choice. Google Photos ran an amusing advertisement showing how widespread this problem is. In a user research survey conducted by Google Play last year, the leading reason why people uninstalled apps and games that they had for at least a month was to free up space.

I should mention that there is a less than adequate solution to the problem I’ve outlined. Today, you can build and version multiple APKs for each device configuration in a single release. This quickly gets out of hand when you want to optimize for screen sizes, CPU architectures, target both 32-bit and 64-bit, and so on. You can end up building hundreds of APKs for each release. It’s a pain, and most developers don’t do it. Many just put everything in a single, ‘fat’ APK, and users end up with unused, duplicated content on their device. And, even if you use multi-APK, you can’t optimize for languages. You have to include all the translated strings for every device in every APK, even if the user only needs one or two languages, which wastes more space.

So your existing options aren’t great: increase the size of your app but risk lower conversion rates and higher uninstalls, make your releases less efficient and more painful with multi-APK, or spend all of your time weighing up this feature versus that feature in an effort to avoid increasing the size of your app.

The Small Solution

The solution

Google doesn’t want developers to have to make these compromises, so they’ve been working on a better way. Here’s the big idea: if you upload everything needed to Google Play, then Play can take care of delivering just what’s needed for each user and device. It’s pretty simple, isn’t it? This process can decrease the work and effort you need to do to support Android’s diverse ecosystem and make your app much smaller for users. As you’ll discover later in the post, this new model also helps improve the user acquisition journey: from discovery and install, to engaging and retaining users with features and updates.

Less installs

To realize the vision, Google introduced a new app publishing format, the Android App Bundle, last year. Here’s how it works in detail:

Step 1: You write all your code for your app in an IDE such as Android Studio or a games engine such as Unity as you normally would.

Step 2: Now, when you’re ready to test or release the app, you build it as an Android App Bundle, Android’s new app publishing format. You still sign the app so that Google Play can verify it’s from you.

Step 3: If you haven’t already, you opt in to app signing by Google Play. If you’re releasing a new app, you can do this in a one-click process when you upload your app. When you opt in, Play designates the first key you used to sign your app bundle as the upload key. This is just for security identification purposes and, if you ever lose it, you can contact Google to verify your identity and reset it. For existing apps, you need to visit the app signing page in the Play Console and securely transfer your app signing key to Google Play. Why do you need to do this? Continue to step 4 to find out.

Step 4: When you upload your app bundle to Google Play, Play processes it and generates split APKs signed with the app signing key for every possible device configuration and language that you support. Split APKs are an Android platform feature introduced in Android L. As long as each split APK is signed with the same key, the Android platform will treat them as one app. You can think of a split APK as ‘part’ of an APK: to run the app, the device treats all the parts as a single app.

Step 5: When a user installs the app, Play delivers the base split APK (all the code that’s common for every device), the language split APKs (for the languages the user speaks), and the device configuration split APKs (for the device’s screen size and the CPU architecture). This means the device gets just what it needs without wasted space. For updates to be accepted by the device, every release’s split APKs must be signed with the same app signing key as the original app install.

Step 6: Once your app is installed on a device, Play will deliver additional split APKs on demand when, for example, a user changes their device language or when a user wants to use a dynamic feature, I’ll talk about these later in the post.

New model

Thousands of developers of popular apps are using app bundles in production. Developers who are using the Android App Bundle have APK sizes that are on average 35% smaller than releasing a ‘universal APK’ (an APK packed with everything needed to support all device configurations and languages that the Android App Bundle supports). More importantly, for those of you who have to manage each release, the new format means you no longer have to use multi-APK for device configurations. Google Play takes care of this for you and makes your life a little easier. > The Play Console will soon start allowing you to upload large app bundles with installed APK sizes of up to 500MB so that, in most cases, you don’t need to use expansion files either.

A benefit of the new model and the new publishing format is that Google Play can introduce optimizations into the APK generation process saving you time and effort. An example is something that has just been announced: support for uncompressed native libraries, a little-used platform feature introduced in Android Marshmallow. Developers using the app bundle get this with no extra work.

Prior to Android M, any native libraries included in your app had to be unzipped from the APK. This meant that there were two copies of the library installed on every device: the compressed copy in the APK and the uncompressed copy. That’s wasted space. From Android M onwards, the library can be read directly from the APK in an uncompressed state, thus saving a copy on the device. Play’s compression of the APK during the download is generally more efficient than compressing the native libraries in the APK, so the overall download size is smaller too. So that you can benefit from this without worrying about the upload size, the Play Console’s size limits are changing so that they’re based on the compressed APK size that users download, not the size of the app you upload to the Play Console. On average, this optimization alone is reducing the download size of apps using native libraries by 8% and the installed size on a device by 16%. That’s an amazing size reduction in addition to what you get when switching to the app bundle!

Including assets for 20+ languages was increasing our app size and noticeably reducing our visit-to-install conversion rate before we started using the Android App Bundle.
Riafy ~37% size saving

As I mentioned, apps must opt in to app signing by Google Play to be able to use the app bundle. App signing keys are a mechanism to ensure updates always come from the same developer after an app is installed. Google doesn’t gain additional access or identifying information about a developer by holding this key. It is used only to sign a split APK for installs and updates. Security is something Google takes very seriously, and Google has a team of engineers and advanced infrastructure protecting developers’ keys using the same secure key storage that Google uses to protect the keys for its apps. In fact, for most developers, opting in to app signing and then using an upload key to sign each release (different to the app signing key held by Google) is more secure than holding the key, which can become lost or compromised. If you’re not opted in and you lose your app signing key, you won’t be able to update your app, and there is unfortunately nothing we can do to help.

Dynamic features

The next important innovation in the Android App Bundle is that it’s modular by design. This means you can add modules to your app containing additional app functionality that can be loaded on demand. This helps with the other big reason for apps getting bigger that I mentioned earlier: feature growth. Now you can add more features and functionality, without increasing the size of your app at the point of install. Dynamic features are a safe way to dynamically load code on Android because dynamic feature modules are scanned and checked in the same way Google Play Protect scans and checks apps themselves.

Dynamic features

Any app functionality can be contained in a dynamic feature module and delivered on demand. You code dynamic features in the same way you code your app. The kinds of features that work well include:

1. Less used features not needed at install: You can load these on demand or tell Google Play to defer installing them, which means installing them in the background. You can load features up to 100MB this way. Advanced features or add-ons that aren’t core to your app experience at launch are good candidates here such as premium features for paying users, personalization options, AR functionality, and so on.

2. Specific features for specific audiences: Instead of including features for every audience using your app, you can carve them out as dynamic features. For example, commerce apps could isolate selling functionality in a dynamic feature module so only the buying functionality gets delivered to every user at the point of install. The small percentage of the audience who need selling functionality can download and access it when they need it. Some developers are also exploring dynamic features as a way to avoid having many variants of an app targeting slightly different audiences. Instead, they can consolidate and offer one app while moving the tailored functionality for each audience into dynamic feature modules.

3. Less used features: Another good use of dynamic feature modules is for functionality that’s rarely used or used once. For example, if your app has a one-time ID verification or credit card scan, then loading this on demand and uninstalling it immediately after its use is an efficient way to avoid adding to the size of your app at install. It also avoids taking up space for something that’s not being used for the lifetime of your app (remember larger apps are more likely to get uninstalled).

Smaller & better

Small & better

These efforts are about helping you drive more installs and fewer uninstalls with a smaller, more efficient app and a faster, more streamlined release. The Android App Bundle also enables highly configurable apps with dynamic features and instant experiences that can increase conversions. Finally, it’s becoming easier to keep your users’ apps up to date.

If you have questions or comments on anything I’ve talked about in the post, Leave a comment

Discover and read more posts from Ali Ahsan
get started