美文网首页
U8SDK——当Flash游戏遇到应用宝YSDK

U8SDK——当Flash游戏遇到应用宝YSDK

作者: U8SDK | 来源:发表于2021-01-16 12:04 被阅读0次

    前一段时间,一个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的子类)

    核心处理代码也很简单:

    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。

        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——当Flash游戏遇到应用宝YSDK

          本文链接:https://www.haomeiwen.com/subject/gzhnaktx.html