2024年最全Google Play渠道超过100M?尝试APK分包!,Golang程序设计基础教程

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 在分包之前,开发者需要明确项目中的大容量资源文件究竟是什么,大多数情况下,他们指的是assets目录下的资源以及raw下的文件,如果drawablemipmap目录下有超过1M的文件,也可以考虑将其进行分包处理,这种情况下需要开发者将该资源的引用方式从直接使用资源id:R.drawable.xxx改为从文件中解析。

  • 所有的资源文件将被压缩为obb文件,最终上传到GooglePlay供用户下载。

obb文件

  • 概念

什么是obb文件,obb全称是Opaque Binary Blob,翻译过来是不透明的二进制对象,再进一步解析就是具有访问权限的二进制文件。看到这个定义很容易联想到另外一种文件格式——zip压缩包文件。所以,从本质上来说,obb文件和zip文件是一样的,它们只是在不同领域上不同解释罢了。而在Android分包领域,obb还有自己的一些规则。

  • 命名规则

obb的命名规则如下:

[main/patch].[versionCode].[packageName].obb

  • 第一部分由可选字段组成,只能填入main或者patch,main指的是主扩展文件,而patch是对于main的补丁或扩展。第一次分包时填入main,而后续如果只是对分包进行增量修改的话,填入patch。笔者习惯每次发版都将所有资源重新打包成obb文件,所以只使用main字段。
  • 第二部分为当前app的 versionCode,当确定好这次发版的versionCode后,大胆填入即可。
  • 第三部分为 packageName,可在AndroidManifest.xml的根节点中读取package字段得到。
  • 最后记得加上obb文件后缀名。
  • 这里举个例子:

main.16.com.example.obbtest.obb

  • 生成方法
  • 方法一:

官方工具法,Google官方提供了Jobb工具用来生成obb文件,工具可以在 Android\sdk\tools\bin文件夹下找到。这是一个命令行工具,具体用法和参数如下:

$ jobb -d [所有资源的路径] -o [生成的obb名称(请遵循上述命名规则)] -k [打包密码] -pn [包名] -pv [versionCode(跟obb名称的versionCode一致)]

也可以使用该工具对obb文件进行解压:

$ jobb -d [输出路径] -o [obb文件名] -k [打包所用的密码]

  • 方法二:

压缩工具法,直接使用Windows或者Mac上的打包工具,将文件压缩成zip包后,更改文件名即可。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

需要注意的是,压缩文件格式需要选择zip,并将压缩方式改为存储。如需进行加密,可使用压缩工具自带的设置密码方法,得到的效果和官方方法设置 -k 参数是一样的。 压缩完后别忘了将文件名改为符合命名规范的obb文件名,如:

main.16.com.example.obbtest.obb

  • 方法三:

gradle打包法,即通过在build.gradle中添加压缩脚本的方式,将需要打入obb的资源集体打包的方法。该方法会在后文中进行详细介绍。

上传obb测试

  • 本地测试 本地测试的原理是模仿Google Play下载,将obb文件复制到相应的目录。通过Google Play下载的obb文件存放的路径为:

/Android/obb/App包名/

所以,通过在/Android/obb/下创建[app包名 如com.example.obbtest]文件夹,并将obb文件复制到该目录下即可模拟Google Play安装App。

  • 线上测试

  • 登录Google Play Console开发者账号,打开应用列表,选择需要测试的App:

  • 左边控制栏选择 Release managerment ,然后选择 App Release,最后选择Internal testMANAGE INTERNAL TEST发布内部测试版本。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 在内部测试里创建新的发布版本:将GooglePlay版本的Apk上传,上传完毕后,点击Apk右侧添加更多按钮,将obb文件提交上去,注意obb文件的命名版本号必须与上传的apk的版本号一致,否则会收到提交版本失败的错误。推荐大家使用不可能用在线上版本的versionCode进行测试,比如手机号码、女朋友生日等,以免后续提交正式版本时版本号被占用(不知道为什么GooglePlay的内部测试和正式发布的版本号竟然不能重复)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 填写剩下内容并发。,回到内部测试管理界面,选择管理测试者,将需要测试的Google账号提交上去,并将“Opt-in URL”的地址复制下来。

  • 在测试机上登录测试账号,在浏览器里打开刚刚的“Opt-in URL”地址,即可加入内测,并可以通过Google Play App下载测试版本的App。

  • 下载完成后,可以在/Android/obb/App包名/下看到一份崭新的obb文件。

解压和下载

  • 解压

第一次安装完app后,需要将obb文件进行解压并将解压后的文件存储到我们定义的文件夹里(可以是data/data/包名/files/也可以是内置存储下自定义的项目文件夹)。要想解压obb文件,第一步是获取obb文件的本地路径,具体代码如下:

public static String getObbFilePath(Context context) {
try {
return Environment.getExternalStorageDirectory().getAbsolutePath()

  • “/Android/obb/”
  • context.getPackageName()
  • File.separator
  • “main.”
  • context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionCode
  • “.”
  • context.getPackageName()
  • “.obb”;
    } catch (PackageManager.NameNotFoundException e) {
    e.printStackTrace();
    return null;
    }
    }

拿到obb文件路径后,可以开始进行解压了:

public static void unZipObb(Context context) {
String obbFilePath = getObbFilePath(context);
if (obbFilePath == null) {
return;
} else {
File obbFile = new File(obbFilePath);
if (!obbFile.exists()) {
//下载obb文件
} else {
File outputFolder = new File(“yourOutputFilePath”);
if (!outputFolder.exists()) {
//目录未创建 没有解压过
outputFolder.mkdirs();
unZip(obbFile, outputFolder.getAbsolutePath());
} else {
//目录已创建 判断是否解压过
if (outputFolder.listFiles() == null) {
//解压过的文件被删除
unZip(obbFile, outputFolder.getAbsolutePath());
}else {
//此处可添加文件对比逻辑
}
}
}
}
}

谷歌官方有提供解压obb文件的库供开发者使用,叫做APK Expansion Zip Library,感兴趣的小伙伴可以在一下路径下查看。

/extras/google/google_market_apk_expansion/zip_file/

笔者不推荐使用该库,原因是这个库已经编写了有一些年头了,当时编译的sdk版本比较低,有一些兼容性的bug需要开发者修改代码后才能使用。所以这里使用的upzip方法是用最普通的ZipInputStream和FileOutputStream解压zip包的方式来实现的:

//这里没有添加解压密码逻辑,小伙伴们可以自己修改添加以下
public static void unzip(File zipFile, String outPathString) throws IOException {
FileUtils.createDirectoryIfNeeded(outPathString);
ZipInputStream inZip = new ZipInputStream(new FileInputStream(zipFile));
ZipEntry zipEntry;
String szName;
while ((zipEntry = inZip.getNextEntry()) != null) {
szName = zipEntry.getName();
if (zipEntry.isDirectory()) {
szName = szName.substring(0, szName.length() - 1);
File folder = new File(outPathString + File.separator + szName);
folder.mkdirs();
} else {
File file = new File(outPathString + File.separator + szName);
FileUtils.createDirectoryIfNeeded(file.getParent());
file.createNewFile();
FileOutputStream out = new FileOutputStream(file);
int len;
byte[] buffer = new byte[1024];
while ((len = inZip.read(buffer)) != -1) {
out.write(buffer, 0, len);
out.flush();
}
out.close();
}
}
inZip.close();
}

public static String createDirectoryIfNeeded(String folderPath) {
File folder = new File(folderPath);
if (!folder.exists() || !folder.isDirectory()) {
folder.mkdirs();
}
return folderPath;
}

解压完成后,就可以通过输出文件的路径来访问到我们需要访问的大容量资源了,文件的读取在这里就不展开了。

  • 下载obb

从Google Play下载和安装App有一定概率会下载到不包含obb文件的apk,或者obb文件被人为删除了。这种情况下,需要开发者到谷歌提供的下载地址处下载相应的obb文件。可是要怎么获取到下载地址呢,这里使用了官方的Downloader Library

这个库可以通过Android Sdk Manager下载到,打开manager后勾上Google Play Licensing Library packageGoogle Play APK Expansion Library package点下载即可。可是在我兴高采烈准备大干一场的时候,发现它竟然编译不过[捂脸]。这个库和上面说的APK Expansion Zip Library一样,由于年代久远又年久失修,基本不能使用了。折腾了一些时间后,魔改了一个版本,才终于可以使用。 这里提供一个编译好的jar包google_apk_expand_helper。具体代码如下:

//随机byte数组,随便填就好
private static final byte[] salt = new byte[]{18, 22, -31, -11, -54, 18, -101, -32, 43, 2, -8, -4, 9, 5, -106, -17, 33, 44, 3, 1};

private static final String TAG = “Obb”;

public static void getObbUrl(Context context, String publicKey) {
final APKExpansionPolicy aep = new APKExpansionPolicy(
context,
new AESObfuscator(salt,
context.getPackageName(),
Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID)
));
aep.resetPolicy();

final LicenseChecker checker = new LicenseChecker(context, aep, publicKey);

checker.checkAccess(new LicenseCheckerCallback() {
@Override
public void allow(int reason) {
Log.i(TAG, “allow:” + reason);
if (aep.getExpansionURLCount() > 0) {
//这里就是获取到的地址
String url = aep.getExpansionURL(0);
}
}

@Override
public void dontAllow(int reason) {
Log.i(TAG, “dontAllow:” + reason);
}

@Override
public void applicationError(int errorCode) {
Log.i(TAG, “applicationError:” + errorCode);
}
});
}

上述方法中需要提供参数publicKey,这个publicKey可以在GooglePlayConsole中找到。

  • 小结

掌握了上述的方法我们就已经完成了Apk分包的主要流程了,以下内容将举例说明如果通过配置gradle文件进行多渠道打包,如何在每次打包的时候自动将大容量资源文件压缩成obb等。

多渠道与自动化

  • 例子

假设我们现在需要发布一个超过100M的安装包到GooglePlay以及应用宝,对于GooglePlay来说,我们需要生成小于100M的apk文件和obb文件,而对于应用宝来说,只需要生成一个完整的apk即可。

那么问题来了,我们不可能说在打包GooglePlay的时候将资源文件手动移除并修改资源引用的相关逻辑,然后再在打包应用宝的时候将他们放回来,这样做会大大增加开发者的工作量并且增大出错的可能性。那有没有办法在单个工程项目下既能打包GooglePlay的包又可以打包应用宝的包呢?答案是有的,build.gradle中的sourceSets就可以解决这样的问题。

  • 利用sourceSets隔离渠道资源和资源引用代码

假设我们有一个splash.mp4文件,在应用宝中渠道包中,它被放在了res/raw/目录下。而在googlePlay渠道包中,它被放置在obb文件里,我们可以这么处理。

首先,在src目录下创建两个新的目录googlePlay和tencent,并在他们的目录下新建java,res和assest文件夹。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在app级别的build.gradle文件中添加GooglePlay和应用宝的渠道信息:

android {
flavorDimensions “default”
productFlavors {

GooglePlay { dimension “default” }
Tencent { dimension “default” }

/** 在AndroidManifest.xml中加入

**/

productFlavors.all { flavor ->
flavor.manifestPlaceholders = [CHANNEL_NAME: name]
}

}
}

紧接其后添加sourceSets配置,指定不同渠道的资源和代码地址,其中main为共有资源和代码,其余的为对应渠道包的资源和代码:

sourceSets {
main {
java.srcDirs = [‘src/main/java’]
assets.srcDirs = [‘src/main/assets’]

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

(img-9BbQPSQP-1715401043133)]
[外链图片转存中…(img-y3Lqm0GW-1715401043133)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值