问题
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?
回答1:
Expansion files remove the restriction of uploading more than 50MB 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());
}
}
回答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:
/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);
回答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 "*/.*"
回答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.
回答5:
In Eclipse your project,click right mouse key,follow the steps: Android Tools->Export Signed Application Package -> ....
来源:https://stackoverflow.com/questions/11715855/steps-to-create-apk-expansion-file