Android 创建APK扩展文件的步骤
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11715855/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Steps to create APK expansion file
提问by user1414154
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.
我在我的应用程序中使用了应用程序许可功能。现在我要在 google play 上上传一个应用程序。
Please let me know the steps, How to use Application licensing and how to create APK Expansion file?
请让我知道如何使用应用程序许可以及如何创建 APK 扩展文件的步骤?
回答by Mohammed Azharuddin Shaikh
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.
扩展文件取消了上传超过 50MB 的 apk 大小的限制。您应该在上传 apk 时附加这些文件。每个应用程序可为每个 APK 提供最多 4GB(2GB - 主要,2GB - 补丁)的额外数据。
There are naming convention you have to follow while creating Expansion files
创建扩展文件时必须遵循命名约定
[main|patch].<expansion-version>.<package-name>.obb
[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
main
- 如果没有这些文件,您的应用程序将不会运行patch
- 是那些额外的文件,没有这个你的应用程序可以运行expansion-version
- 您提供给您的 apk 的版本,以便不同版本的扩展文件不会发生冲突package-name
- 这是您唯一的包名
.obb
we are not appending, it will implicitly appended by Google while uploading
.obb
我们不附加,它会在上传时由 Google 隐式附加
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
假设您在当前目录中拥有所有内容,因此只需选择所有内容并将其命名为 zipmain.2.com.xyz.abc.zip
并在上传 apk 时将其附加
This all uploading part, now downloading part
这都是上传部分,现在下载部分
First of all you need to download Google extra packageby clicking on SDK-Manager
首先,您需要通过单击 SDK-Manager下载Google 额外包
Now create new project from existing source and import market_licensing, play_apk_expansionfrom the path sdk-path/extras/google
现在从现有源创建新项目并从路径sdk-path/extras/google导入market_licensing、play_apk_expansion
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.
请记住:免费应用程序不需要许可,但需要扩展概念,您只需要将 market_licensing 引用给您的项目,它将隐式管理。
play_apk_expansion
contains three projects downloader_library
, zip_file
, downloader_sample
.
play_apk_expansion
包含三个项目downloader_library
,zip_file
,downloader_sample
。
downloader_library itself having the reference of Market_licensing.
downloader_library 本身具有 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)
现在您只需要专注于downloader_sample
首先将包名称(用于测试)更改为您的包名称(包名称与上传的apk相同)
Very Important
很重要
In SampleDownloaderActivity
navigate to...
在SampleDownloaderActivity
导航到...
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).
现在此活动将下载扩展文件并将其存储在sdcard/Android/obb/[main|patch].<expansion-version>.<package-name>.obb
忽略 obb 中,只需将此文件解压缩到您想要的任何位置(sdcard/Android/data
推荐,因为它会在您的应用程序被卸载时删除)。
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
有最新的设备可以直接从 Play 商店下载扩展文件并将其存储在其中,sdcard/Android/obb/
因此您必须非常小心地检查所有情况
- Obb already downloaded
- Available memory
- downloaded but not unzipped
- Memory to select(see Memory Cases)
- ob已经下载了
- 有效内存
- 已下载但未解压
- 要选择的内存(请参阅内存案例)
Memory Cases:
记忆案例:
if you take any new device or for ex. micromax funbook, then it's having three memory
如果您使用任何新设备或例如。micromax funbook,然后它有三个内存
- /data/data/ (phone internal memory) getFilesDirectory()
- /mnt/sdcard/ (phone's internal sdcard) Environment.getExternalStorageDirectory()
- /mnt/extsd/ (External sdcard) /mnt/extsd
- /data/data/(手机内存)getFilesDirectory()
- /mnt/sdcard/ (手机内部sdcard) Environment.getExternalStorageDirectory()
- /mnt/extsd/(外部 SD 卡)/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
来解压缩内容。
ZipHelper.java
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());
}
}
回答by RAY
First , assume you are migrate using a helloworld.jpg from /assets/helloworld.jpg to your expansion
首先,假设您使用 helloworld.jpg 从 /assets/helloworld.jpg 迁移到您的扩展
- create an zip file but with the following file pattern , ending the file extension .obb:
- 创建一个 zip 文件,但文件格式如下,文件扩展名为 .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/
例如,如果您的 pkg 名称是“com.earth.helloworld”并且版本 = 1,
那么您的输出扩展文件名应该是:
patch.1.com.earth.helloworld.obb
,这是一个在 zip 文件后包含 helloworld.jpg
的 zip 文件已创建,请注意文件大小:
2. 如果不存在,则在您的 sdcard 上创建此文件夹:
/mnt/sdcard/Android/obb/{您的包名称}/
即
/mnt/sdcard/Android/obb/com.earth。你好,世界/
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);
然后将您的 obb 文件上传到您的 SD 卡,例如 /mnt/sdcard/Android/obb/com.earth.helloworld/patch.1.com.earth.helloworld.obb
然后创建一个获取扩展文件的方法
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; }
最后用这两行得到helloworld.jpg
InputStream istr = getExpansionFile().getInputStream(strName);
Bitmap bitmap = BitmapFactory.decodeStream(istr);
回答by Jordy
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.
对于在这篇文章中结束的人们的一些有用的信息,因为 apk 扩展的工作方式发生了一些变化,如果您正在使用 Android Studio 使库工作,则也是如此。
NOTE 1
注 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.
您不能再使用草稿,因为获取扩展文件的链接尚未激活。您必须首先使用扩展文件将版本上传到 Alpha 或 Beta。(添加扩展文件只能从您上传的第二个 apk 开始)因此,当您单击 APK 下开发人员发布部分中的详细信息时,请确保您看到列出的 apk 扩展文件。
NOTE 2
笔记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.
如果您使用的是 android studio 并且想要使用下载器库,请不要只将包名和 java 文件复制到您自己的应用程序 src 目录中。在 Eclipse 中导入下载器库并选择 export => gradle build files。之后,您可以将库作为模块导入 android studio。
NOTE 3
注 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.
不确定这一点,但我也认为有必要通过 Play 商店至少下载一次应用程序,并使用测试设备上的帐户访问它。因此,如果您使用 Alpha 版,请创建一个 google+ 测试组并将您自己或其他测试设备添加到其中。
BTW
顺便提一句
With these libraries it's pretty easy to implement the apk expansion download just make sure:
使用这些库很容易实现 apk 扩展下载,只需确保:
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.
您的活动(您希望在未自动完成下载时实现扩展包下载的活动)实现了 IDownloaderClient。
您设置服务和接收器并将它们设置在您的清单中。
服务类中的 BASE64_PUBLIC_KEY 是正确的。上传第一个 apk => 在您的应用程序下的开发人员控制台中查看服务和 API => 此应用程序的许可证代码。
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).
它使用 XAPKS 类,它代表一个扩展文件,无论是主文件还是补丁文件,都具有特定的文件大小(字节)并与 apk 版本(首先添加的那个)相关联。
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).
使用谷歌提供的压缩工具(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.
首先使用库中提供的方法获取扩展文件,参数是代表您的主要扩展apk版本(首先添加您需要的扩展包的apk版本)和补丁apk版本的整数。
ZipResourceFile expansionFile = APKExpansionSupport.getAPKExpansionZipFile(context, APKX_MAIN_APK, APKX_PATCH_APK);
Video
视频
For playing video directly from this zipresourcefile:
要直接从此 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.
现在从这个 assetFileDescriptor 你可以得到一个 FileDescriptor 并在你的媒体播放器中使用它,让你的媒体播放器播放视频的正确语法还需要第二个和第三个参数..无论是你可以从 AssetFileDescriptor 获得的 startoffset 和长度。
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:
对于所有其他内容(如图像),您只需获取 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 中的视频以使其正常工作!例如不要压缩 .mp4 文件:
zip -n .mp4 -r zipfile.zip . -x ".*" -x "*/.*"
回答by eric k atwood
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.htmlinto 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.
1)截至目前,您不需要实现下载器库和所有 XAPKFile 内容,您需要做的就是复制/粘贴https://developer.android.com/google/play上列出的所有权限/expansion-files.html到您的清单文件中。也许您曾经使用过,但 Google Play 商店会为您处理下载和安装。您需要在源代码中处理实际下载的唯一原因是用户是否手动进入 Android/obb 并删除了您的扩展文件。
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.
2) 上传 .zip 文件时,您不必将其命名为 main.version.package.obb 约定。只需使用其原始名称上传您的 .zip 文件,无论如何它都会为您重命名。
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.
3) 要访问 zip 文件,请转到文件 > 新建 > 导入模块,然后导入与下载器和许可库位于同一目录中的 zip_file 库。确保在 build.gradle 文件中为您的应用添加依赖项:compile project(':zip_file')。这使得您可以在项目中导入这些库。
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.
我希望这是有帮助的。我基本上花了几个小时试图实现网站上列出的(复杂的)下载库代码,最后我删除了所有这些代码,只保留清单中的权限,它工作正常。
回答by enjoy-writing
In Eclipse your project,click right mouse key,follow the steps: Android Tools->Export Signed Application Package -> ....
在 Eclipse 你的项目中,单击鼠标右键,按照以下步骤操作:Android Tools->Export Signed Application Package -> ....