Steps to create APK expansion file
Solution 1
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:
main
- are those files without this your application will not going to runpatch
- are those files which are additional, without this your application can runexpansion-version
- version that you are giving to your apk, so that Expansion files of different version will not conflictpackage-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
This all uploading part, now downloading part
First of all you need to download Google extra package by clicking on SDK-Manager
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
- Obb already downloaded
- Available memory
- downloaded but not unzipped
- 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());
}
}
Solution 2
First , assume you are migrate using a helloworld.jpg from /assets/helloworld.jpg to your expansion
- create an zip file but with the following file pattern , ending the file extension .obb:
`[main|patch].{expansion-version}.{package-name}.obb`
E.g if your pkg name is "com.earth.helloworld" and version = 1
then your output extension file name should be:
patch.1.com.earth.helloworld.obb
which is a zip file containing helloworld.jpg
after the zip file is created, note the file size:
2. then create this folder on your sdcard if not exists:
/mnt/sdcard/Android/obb/{your package name}/
i.e
/mnt/sdcard/Android/obb/com.earth.helloworld/
then upload your obb file to your sdcard e.g /mnt/sdcard/Android/obb/com.earth.helloworld/patch.1.com.earth.helloworld.obb
Then create a method to get the extension file
public ZipResourceFile getExpansionFile() { String fileName = Helpers.getExpansionAPKFileName(this, false, 1); int filesize = 445461159; if (Helpers.doesFileExist(this, fileName, , false)) { try { return APKExpansionSupport.getAPKExpansionZipFile( getBaseContext(), 1, 1); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return null; }
Finally use this two lines to get the helloworld.jpg
InputStream istr = getExpansionFile().getInputStream(strName);
Bitmap bitmap = BitmapFactory.decodeStream(istr);
Solution 3
Some helfull information for people that end up here in this post since there are some things that changed in the way apk expansions work and also if you are using Android Studio to make the libraries work.
NOTE 1
You can't use draft anymore as the link to get the expansion file won't be active yet. You have to upload a version to Alpha or Beta first with expansion file. (adding an expansion file is only possible from the second apk you upload and up) So make sure you see the apk expansion file listed when you click the details in the developer publish section under APK.
NOTE 2
If you are using android studio and want to make use of the downloader library don't just copy the package name and java files into your own app src directory. Import the downloader library in eclipse and choose export => gradle build files. Afterwards you can import the library as a module in android studio.
NOTE 3
Not sure of this but I also think it's neccesary to download the app atleast once through the play store and have access to it with the account on your test device. So if you are working with alpha create a google+ test group and add yourself or other test devices to it.
BTW
With these libraries it's pretty easy to implement the apk expansion download just make sure:
your activity (the one where you want to implement the downloading of the expansion pack when the downloading has not been done automatically) implements IDownloaderClient.
you set up the service & receiver and set them up in your manifest.
The BASE64_PUBLIC_KEY in the service class is correct. Upload the first apk => look in Services and API's in the developer console under your app => License code for this app.
This code is used to see if the expansion file can be found on the device:
boolean expansionFilesDelivered() {
for (XAPKFile xf : xAPKS) {
String fileName = Helpers.getExpansionAPKFileName(this, xf.mIsMain, xf.mFileVersion);
Log.i(TAG, "Expansion filename " +fileName);
if (!Helpers.doesFileExist(this, fileName, xf.mFileSize, false))
return false;
}
return true;
}
It uses the class XAPKS wich represents an expansion file, be it either a main or patch file, having a certain filesize(bytes) and associated with a apk version (the one it was first added in).
private static class XAPKFile {
public final boolean mIsMain; // true
public final int mFileVersion; //example 4
public final long mFileSize; //example 126515695L
// example => main expansion that was first introduced in apk version 4 and is 126515695 bytes in size
XAPKFile(boolean isMain, int fileVersion, long fileSize) {
mIsMain = isMain;
mFileVersion = fileVersion;
mFileSize = fileSize;
}
}
Its also quite easy to read movie files and other stuff directly from the expansion file using the zip tools that google has provided (com.android.vending.zipfile).
First get the expansionfile using the methods provided in the library, the paremeters are integers that represent your main expansion apk version (the apk version where the expansion pack you need was first added) and the patch apk version.
ZipResourceFile expansionFile = APKExpansionSupport.getAPKExpansionZipFile(context, APKX_MAIN_APK, APKX_PATCH_APK);
Video
For playing video directly from this zipresourcefile:
AssetFileDescriptor a = expansionFile.getAssetFileDescriptor(pathToFileInsideZip);
Now from this assetFileDescriptor you can get a FileDescriptor and use this in your mediaplayer, the correct syntax to get your mediaplayer to play the video also needs the second and third parameter.. Be it the startoffset and length you can get from the AssetFileDescriptor.
player.setDataSource(a.getFileDescriptor(), a.getStartOffset(), a.getLength());
Other
For all the other stuff (like images) you can just get an inputstream of the zipresourcefile:
expansionFile.getInputStream(pathToFileInsideZip);`
ALSO make sure you don't compress the videos in the zip for this to work! for example not to compress .mp4 files:
zip -n .mp4 -r zipfile.zip . -x ".*" -x "*/.*"
Solution 4
Just want to add some things that I learned in the process of implementing this:
1) As of now, you do not need to implement the downloader library and all the XAPKFile stuff, all you need to do is copy/paste all the permissions that are listed on https://developer.android.com/google/play/expansion-files.html into your manifest file. Maybe you used to, but Google Play Store handles the downloading and installing for you. The only reason you would need to handle actual downloading in your source code is if the user manually went into Android/obb and deleted your expansion files.
2) When uploading your .zip file, you don't have to name it to the main.version.package.obb convention. Simply upload your .zip file with its original name, and it will be renamed for you regardless.
3) To access the zip file, go to File > New > Import Module, and import the zip_file library that is in the same directory as the downloader and licensing libraries. Make sure to add to your dependencies in the build.gradle file for your app: compile project(':zip_file'). This makes it so you can import those libraries in your project.
I hope that is helpful. I basically spent hours trying to implement the (complicated) downloading library code that is listed on the site, and in the end I deleted all of it and just kept the permissions in the manifest, and it works fine.
user1414154
Updated on July 09, 2022Comments
-
user1414154 almost 2 years
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?
-
user1414154 almost 12 yearsPlease let me know the steps to implement Application Licensing. I have look at the developer site. Still i require some more help on it.
-
user1414154 almost 12 yearsi follow the steps up to added code from SampleDownloadActivity to my activity.
-
LOG_TAG almost 12 yearsafter running the code there bugs like 1>crc 2>download bar may effect your code.. stackoverflow.com/questions/11723814/… please comment if got the same problem, if I found the solution let u know..
-
LOG_TAG almost 12 yearscrc bug solution by hotveryspicy: stackoverflow.com/questions/10330283/…
-
LOG_TAG almost 12 years@user1414154 google's apk extension files guide is very good,or go trough above details.In single line i can tell u just import all libs Marketlicensing,downloader_library,zip_file and sample code from C:..\androidsdk\extras\google\play_apk_expansion\downloader_sample from sdk C:...\android-sdk\extras\google folder and go to properties add the libraries to sample code, before uploading into gplay change the package name and add base64 code, apk expansion file byte size to SampleDownloaderService.java and sove the crc bug if you want! after running you may get some bugs goo.gl/2JhWg
-
LOG_TAG almost 12 yearsright click on you expansion file and get the size in bytes, size must be same as zip size but which size we have to put? there two types of file size 1>Size on Disk 2>Size which one we should use?
-
Mohammed Azharuddin Shaikh almost 12 years@Subra ignore size on disk, take another one.
-
LOG_TAG almost 12 yearsthanks! do you think XAPK File validation failed come for crc bug or files size ? stackoverflow.com/questions/11723814/…
-
LOG_TAG almost 12 yearsWhich is the right way for unzipping or unpacking the expansion APK Expansion Files obb files? (sdcard/Android/data recommended because it removes when your application get uninstalled). I can use this goo.gl/OJfLk for unzipping?
-
LOG_TAG almost 12 years@hotveryspicy thanks it's working fine! #coolverysweet problem is I have to delete downloaded obb file after unzipping to save the space!!
-
LOG_TAG over 11 years@Goofy please share where you stuck ex:LVL, download verification, unzipping/accessing the data
-
Goofy over 11 yearsi am using the sample proj provided in the sdk, now i have am testing the obb file exists or not before uploading the apk file in market, now i have added the obb file in Android/obb/com.abc.ss/main.2.com.abc.ss.obb but when i run the sample app it says downlaoding failed resource not found, but why is it downloading as i have not yet uploaded in console and also the obb file is already present
-
LOG_TAG over 11 years@Goofy maybe you have to check the size of the file you mentioned in the sampledownloader activity!
-
Goofy over 11 years@Subra can you join here chat.stackoverflow.com/rooms/25141/…
-
jeevamuthu about 11 years@hotveryspicy i have a problem while unzip the .obb file. i am getting this error Not a zip file.
-
am_ almost 11 yearsI spent some time looking for the sdk-path/extras/google path when creating new project from existing source. My sdk was located in my users/[username]/AppData/Local/Android/android-sdk/extras/google. Just hover your mouse above the package in the SDK Manager and it will show the path there.
-
Sanket Kachhela almost 11 yearsi have found that we should have to make 0% compression zip file. so we dont need to extract that obb file. see this stackoverflow.com/a/18953778/942224
-
Mohammed Azharuddin Shaikh almost 11 years@SanketKachhela Yes, but this is when you are dealing with media files i.e Audio/Video. This will not apply for regular files
-
Sanket Kachhela almost 11 years@hotveryspicy i have tried with images too. and it's working nice.
-
Jeongbebs about 10 yearsthe user asked for apk expansion files, not exporting the project to an apk.
-
Lalit Poptani almost 10 years
-
Buggy IdioT over 9 yearsthats not about the signed apk user ask about Apk expansion file.
-
anhnt almost 9 yearsCan you provide Helpers class as well?
-
Raj over 6 yearsThank you for the Explanation. 1) Any Other Alternate is there or not 2) we are able or not to access obb files directly without upload the apk in play store.
-
Raj over 6 yearsThank you for the Explanation. 1) Any Other Alternate is there or not 2) we are able or not to access obb files directly without upload the apk in play store.
-
Raj over 6 yearsThank you for the Explanation. 1) Any Other Alternate is there or not 2) we are able or not to access obb files directly without upload the apk in play store.
-
Raj over 6 yearsThank you for the Explanation. 1) Any Other Alternate is there or not 2) we are able or not to access obb files directly without upload the apk in play store.
-
Nauman Shafique almost 6 years@AzharShaikh You've write this line in try of unZipEntry method
IOUtils.copy(inputStream, outputStream);
Please guide me what is IOUtils Android Studio is showing error on it. -
Pranav about 5 yearscan i use notification sound from expansion file?
-
xSuperMu almost 4 yearsAnother Important key point, In the documents google says: "Google Play downloads your expansion files to a device, it saves them to the system's shared storage location." What would happen if the device does not have external storage? is it going to crash? @MohammedAzharuddinShaikh