In this article

APK Expansion Files

02/16/2018

6 minutes to read

Contributors

In this article

Some applications (some games, for instance) require more resources and
assets than can be provided in the maximum Android app size limit imposed by Google
Play. This limit depends on the version of Android that your APK is targeted for:

To overcome this limitation, Google Play will host and distribute two
expansion files to go along with an APK, allowing an application to
indirectly exceed this limit.

On most devices, when an application is installed, expansion files will be
downloaded along with the APK and will be saved to the shared storage location
(the SD card or the USB-mountable partition) on the device. On a few older
devices, the expansion files may not automatically install with the APK. In
these situations, it is necessary for the application to contain code that will
download the expansion files when the user first runs the applications.

Expansion files are treated as opaque binary blobs (obb) and may be up to 2GB
in size. Android does not perform any special processing on these files after
they are downloaded – the files can be in any format that is appropriate for the
application. Conceptually, the recommended approach to expansion files is as
follows:

Main expansion – This file is the primary expansion file for resources and assets that will not fit in the APK size limit. The main expansion file should contain the primary assets that an application needs and should rarely be updated.

Patch expansion – This is intended for small updates to the main expansion file. This file can be updated. It is the responsibility of the application to perform any necessary patches or updates from this file.

The expansion files must be uploaded at the same time as the APK is uploaded.
Google play does not allow an expansion file to be uploaded to an existing APK
or for existing APKs to be updated. If it is necessary to update an expansion
file, then a new APK must be uploaded with the versionCode updated.

Expansion File Storage

When the files are downloaded to a device, they will be stored in
shared-store/Android/obb/package-name:

shared-store – This is the directory specified by Android.OS.Environment.ExternalStorageDirectory .

package-name – This is the application's Java-style package name.

Once downloaded, expansion files should not be moved, altered, renamed, or
deleted from their location on the device. To do so will cause the expansion
files to be downloaded again, and the old file(s) will be deleted. Additionally,
the expansion file directory should contain only the expansion pack files.

Expansion files offer no security or protection around their content – other
applications or users may access any files saved on the shared storage.

If it is necessary to unpack an expansion file, the unpacked files should be
stored in a separate directory, such as one
in Android.OS.Environment.ExternalStorageDirectory.

An alternative to extracting files from an expansion file is to read
the assets or resources directly from the expansion file. The expansion
file is nothing more than a zip file that can be used with an
appropriate ContentProvider. The
Android.Play.ExpansionLibrary
contains an assembly,
System.IO.Compression.Zip,
which includes a ContentProvider that will allow for direct file
access to some media files. If media files are being packaged into a
zip file, media playback calls may directly use files in the zip
without having to unpack the zip file. The media files should not be
compressed when added to the zip file.

FileName Format

When the expansion files are downloaded, Google Play will use the following
scheme to name the expansion:

[main|patch].<expansion-version>.<package-name>.obb

The three components of this scheme are:

main or patch – This specifies whether this is the main or patch expansion file. There can be only one of each.

<expansion-version> – This is an integer that matches the versionCode of the APK that the file was first associated with.

<package-name> – This is the application's Java-style package name.

For example, if the APK version is 21, and the package name is mono.samples.helloworld, the
main expansion file will be named main.21.mono.samples.helloworld.

Download Process

When an application is installed from Google Play, the expansion files should
be downloaded and saved along with the APK. In certain situations this may not
happen, or expansion files may be deleted. To handle this condition, an app
needs to check to see whether the expansion files exist and then download them,
if necessary. The following flowchart displays the recommended workflow of this
process:

When an application starts up, it should check to see if the
appropriate expansion files exist on the current device. If they do
not, then the application must make a request from Google Play’s
Application Licensing.
This check is made by using the License Verification Library (LVL),
and must be made for both free and licensed applications. The LVL is
primarily used by paid applications to enforce license restrictions.
However, Google has extended the LVL so that it can be used with
expansion libraries as well. Free applications have to perform the LVL
check, but can ignore the license restrictions. The LVL request is
responsible for providing the following information about the expansion
files that the application requires:

File Size – The file sizes of the expansion files are used as part of the check that determines whether or not the correct expansion files have already been downloaded.

Filenames – This is the file name (on the current device) to which the expansion packs must be saved.

URL for Download – The URL that should be used to download the expansion packs. This is unique for every download and will expire shortly after it is provided.

After the LVL check has been performed, the application should download the
expansion files, taking into consideration the following points as part of the
download:

The device may not have enough space to store the expansion files.

If Wi-Fi is not available, then the user should be allowed to pause or cancel the download to prevent unwanted data charges.

The expansion files are downloaded in the background to avoid blocking user interactions.

While the download is occurring in the background, a progress indicator should be displayed.

Errors that occur during the download are gracefully handled and recoverable.

Architectural Overview

When the main activity starts, it checks to see if the expansion files are
downloaded. If the files are downloaded, they must be checked for validity.

If the expansion files have not been downloaded or if the current files are
invalid, then new expansion files must be downloaded. A bounded service is
created as part of the application. When the main activity of the application is
started, it uses the bounded service to perform a check against the Google
Licensing services to find out the expansion file names and the URL of the files
to download. The bounded service will then download the files on a background
thread.

To ease the effort required to integrate expansion files into an application,
Google created several libraries in Java. The libraries in question are:

Downloader Library – This is a library that reduces the effort required to integrate expansion files in an application. The library will download the expansion files in a background service, display user notifications, handle network connectivity issues, resume downloads, etc.

License Verification Library (LVL) – A library for making and processing the calls to the Application Licensing services. It can also be used to perform licensing checks, to see if the application is authorized for use on the device.

APK Expansion Zip Library (optional) – If the expansion files are in a zip file, this library will act as a content provider and allow an application to read resources and assets directly from the zip file without having to expand the zip file.

These libraries have been ported to C# and are available under the Apache 2.0
license. To quickly integrate expansion files into an existing application,
these libraries can be added to an existing Xamarin.Android application. The
code is available at the Android.Play.ExpansionLibrary on GitHub.

Feedback

We'd love to hear your thoughts. Choose the type you'd like to provide: