Steps to create APK expansion file

user1414154 picture user1414154 · Jul 30, 2012 · Viewed 62.9k times · Source

I have developed Application and work successfully.

I have used Application Licensing feature into my application. And now I'm going to upload an application on google play.

Please let me know the steps, How to use Application licensing and how to create APK Expansion file?

Answer

Mohammed Azharuddin Shaikh picture Mohammed Azharuddin Shaikh · Jul 30, 2012

Expansion files remove the restriction of uploading more than 100MB apk size. You should attach these files when uploading the apk. Each app can provide up to 4GB (2GB - main, 2GB - patch) of additional data for each APK.

There are naming convention you have to follow while creating Expansion files

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

note:

  1. main- are those files without this your application will not going to run
  2. patch- are those files which are additional, without this your application can run
  3. expansion-version- version that you are giving to your apk, so that Expansion files of different version will not conflict
  4. package-name-This is your unique package name

.obb we are not appending, it will implicitly appended by Google while uploading

suppose you have all the content in your current directory so just select all the content and make it a zip named main.2.com.xyz.abc.zip and attach it with while uploading apk

enter image description here

This all uploading part, now downloading part

First of all you need to download Google extra package by clicking on SDK-Manager

enter image description here

Now create new project from existing source and import market_licensing, play_apk_expansion from the path sdk-path/extras/google

Remember: Free app does not require Licensing but Expansion concept required, you just need not to bother by giving reference of market_licensing to your project it will implicitly manage.

play_apk_expansion contains three projects downloader_library, zip_file, downloader_sample.

downloader_library itself having the reference of Market_licensing.

Now you just need to concentrate on downloader_sample first change the package name(for testing) to your packagename(packagename same as uploaded apk)

Very Important

In SampleDownloaderActivity navigate to...

private static final XAPKFile[] xAPKS = {
            new XAPKFile(
                    true, // true signifies a main file
                    2, // the version of the APK that the file was uploaded
                       // against
                    xxxxxxxxxxxL // the length of the zipfile in bytes right click on you expansion file and get the size in bytes, size must be same as zip size
            ),

    };

Now This activity will download the Expansion file and will store it in sdcard/Android/obb/[main|patch].<expansion-version>.<package-name>.obb ignore obb, just unzip this file anywhere you want (sdcard/Android/data recommended because it removes when your application get uninstalled).

There are latest device which download Expansion files directly from Play store and it get stored in sdcard/Android/obb/ so you have to be very careful to check all the cases

  1. Obb already downloaded
  2. Available memory
  3. downloaded but not unzipped
  4. Memory to select(see Memory Cases)

Memory Cases:

if you take any new device or for ex. micromax funbook, then it's having three memory

  • /data/data/ (phone internal memory) getFilesDirectory()
  • /mnt/sdcard/ (phone's internal sdcard) Environment.getExternalStorageDirectory()
  • /mnt/extsd/ (External sdcard) /mnt/extsd

Hope this will help you and will meet your requirements.

And one more thing use this below ZipHelper to unzipped the content.

ZipHelper.java

public class ZipHelper
{
    boolean zipError=false;

    public boolean isZipError() {
        return zipError;
    }

    public void setZipError(boolean zipError) {
        this.zipError = zipError;
    }

    public void unzip(String archive, File outputDir)
    {
        try {
            Log.d("control","ZipHelper.unzip() - File: " + archive);
            ZipFile zipfile = new ZipFile(archive);
            for (Enumeration e = zipfile.entries(); e.hasMoreElements(); ) {
                ZipEntry entry = (ZipEntry) e.nextElement();
                unzipEntry(zipfile, entry, outputDir);
                
            }
        }
        catch (Exception e) {
            Log.d("control","ZipHelper.unzip() - Error extracting file " + archive+": "+ e);
            setZipError(true);
        }
    }

    private void unzipEntry(ZipFile zipfile, ZipEntry entry, File outputDir) throws IOException
    {
        if (entry.isDirectory()) {
            createDirectory(new File(outputDir, entry.getName()));
            return;
        }

        File outputFile = new File(outputDir, entry.getName());
        if (!outputFile.getParentFile().exists()){
            createDirectory(outputFile.getParentFile());
        }

        Log.d("control","ZipHelper.unzipEntry() - Extracting: " + entry);
        BufferedInputStream inputStream = new BufferedInputStream(zipfile.getInputStream(entry));
        BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(outputFile));

        try {
            IOUtils.copy(inputStream, outputStream);
        }
        catch (Exception e) {
            Log.d("control","ZipHelper.unzipEntry() - Error: " + e);
            setZipError(true);
        }
        finally {
            outputStream.close();
            inputStream.close();
        }
    }

    private void createDirectory(File dir)
    {
        Log.d("control","ZipHelper.createDir() - Creating directory: "+dir.getName());
        if (!dir.exists()){
            if(!dir.mkdirs()) throw new RuntimeException("Can't create directory "+dir);
        }
        else Log.d("control","ZipHelper.createDir() - Exists directory: "+dir.getName());
    }
}