目录
- 0. 背景
- 1. 打包总览
- 2. 打包前设置
- 3. 其他SDK加入
- 4. UniPack使用
- 5. 包体脚本操作
- 6. 流程自动化
- 7. 渠道提审反馈的问题
- 8. 未来计划
- 9. 附录
其中第一部分为0-4节,而第二部分(本文)为5-9节。
5. 包体脚本操作
打包成candidate app之后,根据项目中的需求对包体进行:反编译解包,文件替换,文件内容修改,重新编译打包操作等等操作。
如果游戏有大量的渠道需要发行,而使用UniPack对每个渠道进行修改显然是费时又费力的,而且也不能保证中间不会有纰漏,那么针对不同的发行渠道,制定不同的修改策略,并在此步骤中自动化执行是非常有必要的。
下面详细讲述使用脚本对整个打包流程(包括针对不同渠道的修改操作)自动化。
6. 流程自动化
这是小结的重要部分,也是自动化流程的主要思想。
首先,第3节“其他SDK接入”可以通过脚本自动化。这里以MA28接入E-play SDK为例,简述自动化脚本流程:
a)由于unity导出的Android工程没有E-play依赖库的信息。需要在目标工程魔塔学院的 AndroidManifest.xml加入SDK的部分内容,并且在src文件夹的主启动activity的事件函数中调用sdk的api。这些工作可以事先做好,并作为一个Patch打入目标工程中的相应位置;
b)将E-play的SDK作为目标工程的依赖工程,最好与目标工程在放同一目录下,确保源码和依赖库编译成功;
c)在目标工程目录下project.properties设置使用android-api进行编译的版本和E-play依赖库的位置;
target=android-21
android.library.reference.1=../Eplay_SDK_Unity3D_jar
- d)在E-play依赖库目录和目标工程目录中,在DOS中分别执行;
android update lib-project -p .
这个命令的作用是在依赖库或是目标目录下生成自动打包相关的文件,-p .的意思是在当前根目录下执行,凡是依赖库都要执行这一步操作;
- e)进入到目标工程目录src_dir,执行:
ant release/debug -buildfile src_dir
如果打包成功,可以在目录下看到未签名的apk文件。
其次,第4节“UniPack使用”可以通过脚本自动化。通过使用UniPack命令行工具,将上一步得到的未签名apk文件的包体进行如下修改:
- 将Apk包反编译
- 加入渠道要求的jar包
- 修改AndroidManifest.xml(添加activity,permission)等操作
- 在assets和res文件夹中添加渠道要求的资源文件
- 将工程目录重新编译成apk并签名
最终生成可以通过短信支付的弱联网apk安装包(candidate app)
接着,第5节“包体脚本操作”可以通过脚本自动化。在UniPack的二级渠道参数中,可以不需要填入一些信息,如包名,Logo闪屏,角标,以及上传计费文件等,这些可以通过自动化脚本进行处理,图5 是包体脚本操作的处理流程图,而像包名,Logo闪屏等则放在红线框“与渠道Ci相关的操作”:
图4. 包体脚本操作的处理流程
a)从配置读取分发渠道
根据项目开发组需要接入的分发渠道,例如魔塔学院接入了包括移动,联通,电信,百度,360,新浪,华为等等分发渠道,针对某个特定的渠道C,需要对apk进行如下操作;b)使用apktool对apk进行反编译,反编译apk教程可以参考博客《APK反编译就这么简单》,也可以向我索取工具,参考代码:
decompileCmd = [ fold_path + 'apktool.bat', # apktools.bat内容:java -jar -Duser.language=en "%~dp0\apktool.jar" %1 %2 %3 %4 %5 %6 %7 %8 %9
'd', # decompile,反编译命令
apk_path # apk路径
]
os.system(' '.join(decompileCmd))
- c) 反编译后,产生目录结构:
图5. apk反编译后工程目录
然后就需要对该目录的某一些文件作一些关于分发渠道 Ci 的修改,这些修改一般都是渠道那边对包体的要求。关于这个操作流程,即红线框“与渠道 Ci 相关的操作”会在 9.附录 详细讲述。
- d) 对游戏代码进行混淆。Unity3d的代码的代码会打包在dll中,保存在\assets\bin\Data\Managed目录下:
图6. Unity代码assets\bin\Data\Managed目录
使用.NET Reflector等反编译工具可以直接看到里面的源码,使用Obfuscar工具可以对代码相关dll进行混淆。具体请移步博客《Unity3D避免代码被反编译》中有非常详细的操作步骤,也可参考Obfuscar官网。当按照文章配置好Obfuscar工具后,参考脚本代码:
obfuscarCmd = [cls.fold_path +'obfuscar.bat', # obfuscar.bat内容: Obfuscar %~1
'99bricks.xml'] # 混淆选项的配置文件,也是Obfuscar.exe的输入参数
os.system(' '.join(obfuscarCmd))
- e)重新编译apk。与b步骤类似,参考脚本代码:
compileCmd = [ cls.fold_path + 'apktool.bat', # 与b步骤的apktool.bat内容相同
'b', # build,重新编译成apk
dir_path] # 重新编译后apk存放的位置
os.system(' '.join(compileCmd))
- f)对游戏apk进行加壳,移步上述KM文章,参考脚本代码:
clienttool_cmd = [ cls.fold_path + 'clienttool.bat', # clienttool.bat内容 : ClientTool %~1 %~2 %~3 %~4
apk_path, #编译成apk后的路径
tmp_path, #加壳后apk存放路径
'-unity3d' #使用u3d引擎开发
]
antirepack and clienttool_cmd.append('-antirepack') #配置是否需要"防二次打包"
os.system(' '.join(clienttool_cmd))
- g)对游戏apk重签。此步大家很熟悉,略。
7. 渠道提审反馈的问题
- 1) 某些渠道对于提审的游戏包体可能会进行二次打包或是其他处理,所以在加壳要注意是否是需要配置”防二次打包”参数(哪些渠道不能“防二次打包”见 9.附录 );
- 2) 电信单网渠道:egame channel 为1000000时,包名一定要是申请的包名,不得随意扩展一位,否则feeinfo.dat就会对不上,支付失败;
- 3) 移动mm三网母包提审,记的加壳,因为当母包通过之后,上传派生包时,移动mm平台需要将派生包和母包比对,只有clssses.dex的CRC32相同才能上传;
图7. 使用解压工具打开apk包体
如果不一样,则会导致:
图8. class.dex的CRC32不一致导致上传失败
4) 当移动mm母包完成之后,在自签名文件mmiap.xml中只能修改channel中的值,其他的内容都不能动,即使是添加一个空格或是回车,都会在调取付费窗口后支付失败。 下面的滚动字幕是:弱联网,订购失败,应用身份验证失败。错误码:1090007。当使用window平台使用脚本修改mmiap.xml中的channel值时,注意原文件是UNIX平台,所以读入程序内存时,注意以二进制读入,因为若以文本读入,有可能会改变文件未Window,这样在调取支付窗口是会报“渠道文件加载失败”的错误
5)单机版oppo的包名为
com.<productor>.<product_name>.oppo
,并不是com.<productor>.<product_name>.nearme.gamecenter
。6)如果在AndroidManifest中有谷歌的广告,如果没有接入的,考虑删除。
图9. 4399渠道反馈7)移动mm的货币名字需要和计费申请时候一样,不然会被打回;
- 8)注意unisdk与一级、二级渠道的更新和最新的要求,如果更新了,及时更新 UniPack的channel_configs文件夹。
8. 未来计划
在第二节“打包前设置”中“其次”步骤-Unity3d工程菜单栏File/Build Settings设置参数并导成Android工程也可以使用c#脚本进行自动化操作,具体可参考博客《Unity3D的Android全自动打包生成apk》。
9. 附录
与渠道Ci相关修改操作
在apk反编译之后,代码混淆之前,与渠道Ci相关的操作,流程如图7所示:
图10. 与渠道Ci相关的操作
以下步骤若没有特别说明,均在AndroidManifest.xml
文件中进行修改(python的xml.etree.ElementTree
的ElementTree库来解析xml)。
1)首先修改渠道Ci的包名。一般每个渠道都有对应的包,在 AndroidManifest 的
package=" com.netease.<product_name>.<channel_ci>"
,其中product_name为产品名,chanel_ci
为渠道名,可以参考 包名与Bundle Identifier;2)修改百度子渠道的dksdk_channel。如果Ci是baidu,那个需要检查其百度子渠道(91手机助手,百度手机助手,百度多酷,百度贴吧)的渠道号;
3) 修改爱游戏渠道号。若渠道ci的一级渠道包含电信爱游戏,那么在
manifest/application/meta-data
中
android:name="EGAME_CHANNEL" android:value=<egame_channel_no>
其中<egame_channel_no
>为渠道在电信爱游戏的渠道号,接入电信爱游戏的渠道都需要修改此值,值可参考营销给开发组的运营商渠道号中的电信爱游戏列;4)若渠道ci的一级渠道包含电信爱游戏,那么:
a)修改联通框架名。在manifest/application/service中:
android:name="com.unicom.wostore.unipay.paysecurity.SecurityServiceFramework"
的子节点 intent-filter/action 节点,修改成
android:name="com.<productor>.<product_name>.<channel_ci>.unicom.wostore.unipay.securityserviceframework"
b)替换uwc文件。营销提供了
UnicomConsume.uwc
联通计费文件,替换反编译后的assets/UnicomConsume/UnicomConsume.uwc
文件
5)若渠道ci的一级渠道包含移动mm,那么:
- a) 在
unknown/mmiap.xml
中替换C的联移动mm渠道号:
<channel
>000000000000</channel
>
将channel节点的值改成渠道在移动mm上的渠道号,值可参考营销给开发组的运营商渠道号中的移动mm列。 - b)修改移动mm渠道服务名
purchaseservice.BIND
与mmiap.activity
。在manifest/application/service
中:
android:exported="true" android:name="mm.purchasesdk.iapservice.PurchaseService"
中的子节点intent-filter/action
节点, 修改成:
android:name="com.netease.<product_name>.<channel_ci>.purchaseservice.BIND"
在manifest/application/activity
的:
android:exported="true" android:name="mm.purchasesdk.iapservice.BillingLayoutActivity"
中的子节点intent-filter/action
节点, 修改成
android:name="com.netease.<product_name>.<channel_ci>.com.mmiap.activity"
- a) 在
- 6)替换渠道制定的带角标的icon。有些渠道对Logo角标的要求,如安智,UC,百度等等,替换相关文件即可。
- 7)替换渠道制定的闪屏。有些渠道对闪屏的要求,如移动基地三网包,移动mm单网包,电信爱游戏单网包,替换相关文件即可。
哪些渠道不能“防二次打包”
1)如果有针对客户端进行加壳和防止重签名的操作,那么在提交下列包的时候需要注意:
2)移动MM单网包只能加壳,不能做防止冲签名的操作;
3)移动基地单网包不能加壳,也不能做防止重签名的操作——这种包被破解的风险极大,需要做好代码混淆,优化服务端协议安全性;
4)沃商店单网包不能加壳,也不能做防止重签名的操作——这种包被破解的风险极大,需要做好代码混淆,优化服务端协议安全性;
5)和游戏单网包只能加壳,不能做防止重签名的操作;
6)所有的移动MM三网派生包,可以加壳,可以防止重签名;
7)所有的移动基地三网派生包,不能加壳,也不能做防止重签名的操作——这种包被破解的风险极大,需要做好代码混淆,优化服务端协议安全性。
第二部分(本文)目录: