U8SDK——当Flash游戏遇到应用宝YSDK
前一段时间,一个U8SDK的客户需要在应用宝上架一款用Flash开发的游戏,遇到了一个Flash游戏和应用宝YSDK不可磨合的冲突……
起源:
应用宝SDK:要求游戏Activity的生命周期中,需要调用应用宝SDK对应的onCreate, onResume, onPause,onActivityResult, onNewIntent等函数。
Adobe的Air引擎:根本没有对外暴露onCreate和onNewIntent生命周期函数。
问题:
如果不在这些生命周期函数中调用应用宝YSDK的对应函数,那么应用宝YSDK的微信登陆收不到回调。
同时,我们又发现另一个棘手的问题。 应用宝SDK登陆过一次之后, 再次进入的时候, 它默认会触发一次自动登录。 现在这个自动登录收不到回调了。
后来尝试了很多种方式,才发现: 应用宝的初始化接口和onCreate调用,必须在游戏启动Activity的onCreate生命周期函数中,自动登录才能收到回调。
这个就真的没法直接处理了。
对于微信收不到回调,我们试着重写了应用宝SDK的WXEntryActivity类,让他触发onNewIntent()。 这样处理之后,微信登陆终于可以收到回调了。
但是自动登录这个,因为Flash游戏和Android层的交互,需要通过ANE Extention来处理。 Adobe Air并没有对底层暴露引擎Activity的onCreate函数或者可以注入触发的监听器等。所以, SDK的初始化,只能在Flash层调用。
无论如何,甲方客户的游戏要上架应用宝。 作为乙方的我们绝对不能跟他说, 应用宝这个渠道上不了。
解决
后来,我们就想能否通过在U8SDK打包工具打包的过程中,来完成“移花接木”, 将SDK的初始化接口注入到最终游戏Activity的onCreate中去调用。
经过调研发现, Flash在导出apk的时候, 会在【air.包名】(这个包名是Flash游戏层设置的包名,不同游戏是不同的)下面生成一个AppEntry.class文件, 这个类就是最终启动Activity。
那我们就需要想办法,在打包的时候, 将U8SDK的初始化,注入到AppEntry的onCreate中。
看过U8SDK一键打包工具原理的同学应该知道, U8SDK打包的时候, 是先将母包apk反编译,再将渠道SDK的代码、资源等合并进去,最终再回编译成最终的渠道apk。
回编译之后, 母包的代码会被回编译成smali格式。那么我们参考之前对Application做的移花接木的方案, 我们也一样可以通过修改smali文件,将我们的SDK初始化逻辑插入到AppEntry中onCreate函数的对应位置。
如果我们直接在AppEntry的onCreate函数中某个位置插入SDK的初始化(smali)代码的话,对于不熟悉smali语法的同学可能有难度。 那我们换一种更简单的方式,将主要的工作在java中完成,这样我们就可以尽可能少地去修改smali。
最终,我们整理后的实现方式如下:
1、我们在Flash ANE库的Android层部分, 自定义一个Activity类(U8ANEActivity.java), 在这个Activity类中, 实现生命周期函数的调用,并在onCreate函数中完成SDK的初始化。
2、打包客户端中,通过自定义脚本(post_script.py), 将上面U8ANEActivity类的继承类改为AppEntry类(也是Activity的子类)
核心处理代码也很简单:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
def modifyClassExtends(smaliPath, targetClassName): targetClassName = targetClassName.replace(".", "/") f = open(smaliPath, 'r') lines = f.readlines() f.close() result = "" for line in lines: if line.strip().startswith('.super'): result = result + '\n' + '.super L'+targetClassName+';\n' else: result = result + line f = open(smaliPath, 'w') f.write(result) f.close() return 0 |
3、然后在post_script.py中, 将AndroidManifest.xml中配置的启动类(AppEntry)改为我们的U8ANEActivity。
1 2 |
filePath = os.path.join(decompileDir, 'AndroidManifest.xml') file_utils.modifyFileContent(filePath, baseStartActivity, 'com.u8.sdk.ane.U8ANEActivity') |
4、这样最终的渠道apk包, 启动的时候, 启动类就是我们的U8ANEActivity类(通过修改smali将其改为继承了AppEntry)。然后启动的时候, 执行U8ANEActivity中的onCreate函数的时候,里面就有U8SDK的初始化逻辑。 其他生命周期函数中调用了U8SDK的对应生命周期函数。
通过这样操作之后,也不需要上面重写WXEntryActivity类的逻辑了,也不需要其他针对ANE做的生命周期逻辑的曲折实现了。 也算一个比较完美的解决方案了。
本文出自 U8SDK技术博客,转载时请注明出处及相应链接。
本文永久链接: http://www.uustory.com/?p=2355