C#版Unity-APK打包工具
最近应大佬的要求,给渠道做了一个打包工具。
这里说的打包工具,不是在unity里直接调用打包,而是更改已打包好的APK,进行换皮换资源换渠道操作。
-------------------------------------------------------
--本文的打包为基于母包去打子渠道子包,这种方式打出来的子包,流畅度没有源码打出来的包那么好。
如果你想使用源码打包,跳转到我的另一篇文章,文章内容是用网站或者winform程序使用命令行进行打包,也可以打批量。
https://www.cnblogs.com/vsirWaiter/p/16639243.html
开发只需要开发完成,上传源码,打包可以直接解放,交给运营自己去操作就行了。
可以达到jenkinesr打包的效果,并且还能自定义做很多事。
--------------------------------------------------------------
废话不多说,本文的打包工具,winform先开起来。
下载一个ApkTools工具。
下载地址:
【金山文档】 apktool
https://kdocs.cn/l/cnzBPJDmtgEc
这个包里的apktool.jar比较老,所以需替换一个新版本的,下载地址如下。
【金山文档】 apktool_2.6.1
https://kdocs.cn/l/csjDyQNnTeB2
之所以脱裤子放个屁,主要是为了让大家知道不同版本的apktool.jar,同样的指令,解出来的东西是有可能不一样的。
然后要在网上下载一个zipalign.exe。
作用:用于未签名的apk对齐。
然后在你的Android Studio的SDK目录里找到apksigner.jar这个东西,我选的是31版本,作用是用来给未签名的APK签名。
如上图,PackagingTools为winform创建的exe,前面所说的需依赖的东西都解压放在这个目录。
那么,开工。
第一步:解包。
启动PackagingTools.exe。
try { using (p2 = new Process()) { //设置要启动的应用程序 try { p2.StartInfo.FileName = @"cmd.exe";// // //是否使用操作系统shell启动 p2.StartInfo.UseShellExecute = false; // 接受来自调用程序的输入信息 p2.StartInfo.RedirectStandardInput = true; //输出信息 p2.StartInfo.RedirectStandardOutput = true; // 输出错误 p2.StartInfo.RedirectStandardError = true; //不显示程序窗口 p2.StartInfo.CreateNoWindow = true; // //启动程序 p2.Start(); SetTextLogoInfo("母包开始解包!"); p2.StandardInput.WriteLine("apktool.bat d " + apkName + " -f -only-main-classes"); p2.StandardInput.WriteLine("ApkUnpack Completed"); StreamReader rd = p2.StandardOutput; bool isUnPack = true; while (isUnPack) { string strOuput = rd.ReadLine(); if (!string.IsNullOrEmpty(strOuput)) { Thread.Sleep(30); SetTextLogoInfo(strOuput); if (strOuput.Contains("ApkUnpack Completed")) { isUnPack = false; Thread.Sleep(30); SetTextLogoInfo("母包解包完成!"); } } } p2.Close(); } catch (Exception ex) { p2.Close(); } } } catch (Exception ex) { }
2、修改AndroidManifest.xml、value/strings.xml、icon等信息。
这一步不上代码了,用代码复制粘贴文件和修改xml。
3、合包回编。
p3 = new Process()
p3.StartInfo.FileName = @"cmd.exe";// // //是否使用操作系统shell启动 p3.StartInfo.UseShellExecute = false; // 接受来自调用程序的输入信息 p3.StartInfo.RedirectStandardInput = true; //输出信息 p3.StartInfo.RedirectStandardOutput = true; // 输出错误 p3.StartInfo.RedirectStandardError = true; //不显示程序窗口 p3.StartInfo.CreateNoWindow = true; // //启动程序 p3.Start(); SetTextLogoInfo("准备开始合包回编译!"); string hFolder = apkName.Substring(0, apkName.LastIndexOf('.')); if (File.Exists(exePath + "\\" + hFolder + "\\dist\\" + hFolder + ".apk")) { File.Delete(exePath + "\\" + hFolder + "\\dist\\" + hFolder + ".apk"); } p3.StandardInput.WriteLine("apktool.bat b " + hFolder); p3.StandardInput.WriteLine("ApkUnpack compile Completed"); StreamReader rd = p3.StandardOutput; bool isUnPack = true; while (isUnPack) { string strOuput = rd.ReadLine(); if (!string.IsNullOrEmpty(strOuput)) { Thread.Sleep(30); SetTextLogoInfo(strOuput); if (strOuput.Contains("ApkUnpack compile Completed")) { isUnPack = false; Thread.Sleep(30); SetTextLogoInfo("合包回编译完成!"); } } }
注意合包回编之后的apk在解包目录下的dist文件夹内。
回编完成后将apk拷贝至解包合包的程序目录下,这样我们的cmd命令就不需要指定各个东西的路径,都会默认在程序目录下。
假如拷贝到程序目录下后,我们将其命名为tmp.apk。
4、APK对齐操作。
p3.StandardInput.WriteLine("zipalign -v 4 tmp.apk dst.apk");//前者为未对齐,后者为已对齐
tmp.apk为合包后的未签名APK,dst.apk为未签名APK对齐后的未签名APK。
如果对齐1次后去签名,如若签名失败,则将对齐一次的dst.apk再对齐一次。
一般情况下2次对齐99.999999999%的都没问题。
5、签名回签。
p3.StandardInput.WriteLine("java -jar apksigner.jar sign -verbose --ks xxxxxxx.keystore --v1-signing-enabled false --v2-signing-enabled true --ks-pass pass:yyyyyyy --ks-key-alias xxxxxxx.keystore --key-pass pass:yyyyyyy --out 1.apk dst.apk");
调用以上代码进行签名。
xxxxxxx.keystore为你的签名文件。
yyyyyyy为你的签名密码。
最后面的dst.apk为未签名的APK。
最后面的1.apk为签名成功后的apk。
完成。
1.apk,再用程序对其重新命名即可。
以上原本都是CMD执行的命令,这里是用winform调用CMD按顺序执行的,因为运营是不想用程序员的操作方式来玩这个的。