Unity3d Android SDK接入解析(四)通用的Android SDK接入中间件

一、前言

接入Android SDK正式告一段落,在这段时间里面,依次接入了华为、应用宝、小米、360等等大大小小十来个SDK,也算对Unity接入渠道SDK有了较为全面的理解,对各个渠道的坑也算深有体会。。。。在接入过程中时间比较紧张,没办法抽空来进行总结深思。今天正好有空,便对之前的接入SDK的代码进行了一次重构,写了一个比较通用的Unity接入Android SDK的中间件,前人栽树,后人乘凉。

进入正题

如果有对一些只是有疑问的,可以看看我之前的三篇文章:

传送门:

Unity3d Android SDK接入解析(一)Unity3d 与 Android之间的互相调用:

http://blog.csdn.net/yang8456211/article/details/51331358

Unity3d Android SDK接入解析(二)Unity3d Android SDK的设计与两种接入方式

http://blog.csdn.net/yang8456211/article/details/51356193

Unity3d Android SDK接入解析(三)接入Android Library的理解(爱贝云支付为例)

http://blog.csdn.net/yang8456211/article/details/51435465

二、关于中间件的一些思考

2.1 为什么不用第三方平台

为什么要自己做一个Unity接入Android SDK的中间件呢?市面上例如Anysdk、易接这种第三方渠道是可以满足接入一次,生成大部分的SDK的,但是由于大渠道的审查越来越严格,已经禁止了这种第三方的平台SDK。因此,这些大渠道则必须由我们自己来接入了(不过二、三线渠道仍然是可以用第三方进行接入的),如果每个渠道都使用一个单独工程来管理,这无疑是一种非常浪费时间而且难以维护的事情,因此我想做的就是一个Unity的接入Android SDK的插件,所有的SDK的逻辑都封装好在Android层面,不同的游戏都可以按照相同的规则来接入进来,只需要调用通用的接口,准备好对应的资源即可。

2.2 怎么样做方便

我希望把这个中间件做的尽量能够通用,而且能够方便拆分、迭代。对Unity层面逻辑透明,只需要关注接口调用的时机和传入的参数。

  • 通用,形式简单
  • 只关注SDK业务逻辑
  • 调用简单

—— 通用,形式简单 ——

先说说通用吧:

对于Unity游戏来说,通常以Plugins的形式接入SDK比较方便,所以从这个思路出发,中间件的形式,我决定做成了jar包,而不是一个Library的工程,jar包里面只包含纯代码,没有资源和任何配置文件,调用方只用把jar包放在 Plugins/Android/libs 里面就可以使用了。对于不同游戏来说,没有差别。

最终的形式,就是一个uasdkinter的jar包,所有的SDK的逻辑会集成在这个jar里面。

形式简单的也有一层含义是,方便集成和拆分:

因此在package的设计上,每个渠道独立一个package放渠道代码,理论上我们导出jar包的时候,直接把所有渠道的代码都打进jar包就可以了,因为每次代码会根据传入的channel执行唯一的渠道,其他代码也就放在那了。

但是有些渠道会进行代码检测,例如360,会检测到包内含有小米支付相关的代码,审核不过,对应我们只需要在打jar的时候,勾选去掉对应的package就可以了。(因为是重构的代码框架,并没有包含很多sdk)

—— 只关注SDK业务逻辑 ——

中间件本身,只包含设计思想和一个简洁的框架。在接入渠道SDK的时候,我们只需要把渠道的SDK代码以一定的规则加入到中间件中即可。

所以这个中间件必须要健壮,框架写好之后,再添加新的SDK代码必须比较方便,无需对框架做大的改动。

因此我使用接口来实现,每个渠道SDK有两个class,一个管理账号信息,一个管理支付信息,账号与支付分离。

账号接口:

public interface UAGameInterf {

    // 初始化
    public void init(JSONObject sJson);

    // 登录
    public void login(JSONObject sJson);

    // 登出
    public void logout();

    // 退出游戏
    public void exit();

    // 初始化参数检查
    public boolean initParams(JSONObject sJson);

    // 设置生命周期的函数
    public void lifeCycle(int status);

    // 存储用户信息
    public void upUserInfo(JSONObject sJson);
}

支付接口:

public interface UAPayInterf {
    // 支付
    public void pay();

    // 初始化参数
    public boolean initParams(JSONObject sJson);
}

在添加SDK的时候,只需要新建账号class和支付的class,分别实现对应的接口,而不用管外层是怎么调用的,消息是怎么返回Unity的,而只用具体的实现每个接口即可,做到只关注SDK的业务逻辑(具体接口的设计说明后面详叙)。

—— 调用简单 ——

调用上,C#初始化“包名+类名”的AndroidJavaClass对象,使用这个对象来调用对应功能,区别于新建一个Activity继承UnityPlayerActivity 的模式,这个方法避免了一系列的蛋疼的问题(例如中间件工程需要和游戏工程的包名一样)

C#的调用:

中间件工程的包名是: com.uainter.main

接口类名是:UAMain

因此可以在C#创建AndroidJavaClass对象:

AndroidJavaClass ajc_SDKCall ajc_SDKCall = new AndroidJavaClass("com.uainter.main.UAMain");

为了方便调用,把对外的接口都做成了静态方法,所以用CallStatic去调用,因为每个渠道需要的参数类型和参数个数不确定,因为把传入参数定义成了一个Json。

例如调用小米渠道的Init方法:

小米渠道需要3个参数:appid、appkey、islandscape(登录与支付横屏还是竖屏显示)

string json = "{‘channel‘:‘11‘,‘debugmode‘:1,‘appid‘:‘xxx‘,‘appkey‘:‘xxx‘,‘islandscape‘:false}";
ajc_SDKCall.CallStatic("uaInit",json);

Login方法:

string json = "{}";
ajc_SDKCall.CallStatic("uaLogin",json);

对于每个可能会有参数传入的方法,都设置了一个json对象作为参数,例如login方法,在接入应用宝的时候,需要在json数据中传入一个platform来判断是登录微信还是QQ。

中间键暴露出的接口有以下几个:

2.3 一些特殊操作的思考与处理

Activity生命周期的处理

理论我希望做到不需要修改启动的Activity,所以Activity生命周期的处理,放在了C#去控制,Android提供接口public void lifeCycle(int status); 在这个接口里面处理渠道SDK需要做的生命周期操作。

例如华为:

(Android 代码)

    public void lifeCycle(int status) {
        if (getActivity() == null) {
            DybGSdkUtil.E("还未Init初始化,不执行生命周期操作 ");
            return;
        }

        switch (status) {
        case DybGSdkConstants.onStart:
            break;
        case DybGSdkConstants.onResume:
            BuoyOpenSDK.getIntance().showSmallWindow(getActivity());
            break;
        case DybGSdkConstants.onPause:
            BuoyOpenSDK.getIntance().hideSmallWindow(getActivity());
            BuoyOpenSDK.getIntance().hideBigWindow(getActivity());
            break;
        case DybGSdkConstants.onStop:
            break;
        case DybGSdkConstants.onDestroy:
            OpenHwID.releaseResouce();
            BuoyOpenSDK.getIntance().destroy(getActivity());
            break;
        default:
            break;
        }
    }

(C#调用)

    void OnApplicationPause(bool isPause)
        {
            if (isPause) {
                string json = "{‘status‘:‘3‘}";
                ajc_SDKCall.CallStatic("uaLifeCycle",json);
            }
        }

    void OnApplicationFocus(bool isFocus)
    {
        if (isFocus)
        {
            if (ajc_SDKCall != null){
                string json = "{‘status‘:‘1‘}";
                ajc_SDKCall.CallStatic("uaLifeCycle",json);
                json = "{‘status‘:‘2‘}";
                ajc_SDKCall.CallStatic("uaLifeCycle",json);
            }
        }
    }

    void OnApplicationQuit()
    {
        string json = "{‘status‘:‘5‘}";
        ajc_SDKCall.CallStatic("uaLifeCycle",json);
    }

(对应的status和生命周期)

    // Android Activity生命周期
    public static final int onStart = 1;
    public static final int onResume = 2;
    public static final int onPause = 3;
    public static final int onStop = 4;
    public static final int onDestroy = 5;
    public static final int onRestart = 6;

实在遇到需要Activity的地方怎么处理?

只有在接入应用宝的时候,遇到了需要接入Activity的两个方法onNewIntent和onActivityResult时,需要接受qq和微信的回调,这种情况我也没有想到什么好办法,只有创建一个Activity,然后实现这个两个方法,并修改这个Activity为AndroidManifest里面的启动Activity。

遇到需要自定application的情况呢?

跟Activity类似,这个时候我们新建一个Application即可。

大部分的SDK方法需要在UI线程中调用

这个之前有说过,在这里只是列出来不详述了:

例如登录:

    public static void uaLogin(String jsonString) {
        try {
            final JSONObject sJson = new JSONObject(jsonString);

            final UAGameInterf uaManager = getSdkObj(sChannel);

            activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    uaManager.login(sJson);
                }
            });

        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

怎么发送消息回Unity

    // 发送消息回Unity3d
    public static void dybCallback(JSONObject rjson) {
        UnityPlayer.UnitySendMessage(UAMain.callBackobj, UAMain.callBackFun,
                rjson.toString());
    }

其中callBackobj 和 callBackFun,分别对应接收返回值的对象的名称和回调方法。(此处我是写死的常量,也可以通过在init中传入对应的key来动态的修改这两个值)

可以看到,返回的也是一个json,里面包括了一个“callbackType”的key用来判断是哪个接口回调的结果,例如Init回调:

            JSONObject jsonObj = new JSONObject();
            String code = "1";
            jsonObj.put("callbackType", "Init");
            jsonObj.put("code", code);
            UAMain.dybCallback(jsonObj);

三、中间件对外接口说明

  • uaInit
public static void uaInit(String jsonString)

主要用于各个渠道SDK的初始化,传入的json字符串中,必须包含的是,debugMode和channel这两个key,channel是用于区分目前调用的是哪个渠道,debugMode是用于区分调试模式还是正式模式(一般SDK都会有两种模式),这里的debugMode我也用来作为显示日志的开关。剩下的key就要根据不同SDK所需要的不同的参数来传入。

  • uaLogin
public static void uaLogin(String jsonString)

一般SDK不用传入jsonString,直接传一个空的json字符串“{}”即可,当有些SDK需要在Login功能中加上切换账号功能是,我会传一个type进来,用来判断此时的操作是登录还是切换账号。

  • uaLogout
public static void uaLogout()

用于账号的退出,这个接口不需要参数。

  • uaExit
public static void uaExit()

用于退出游戏,一般SDK会有一个弹出框来显示一些论坛或者相关的广告信息,这个接口也不需要参数。

  • uaUpUserInfo
public static void uaUpUserInfo

用于信息的打点,就是报备一些信息,例如创建角色、角色升级、退出等等。

  • uaLifeCycle
public static void uaLifeCycle

用于生命周期函数的调用。

  • uaPay
public static void uaPay

用于支付。

四、后续思考

  • 最初写这个框架的时候,大概花费了2天的时间,后续接入中遇到了一些问题,也对这个中间件进行了一些修改,总的来说,能够满足基本上市面上大部分sdk的接入(至少我现在没有遇到接入不了的)。重构之后更加的简洁了,删掉了不少无用的东西。
  • 但是对于需要监听onNewIntent等函数的SDK,虽然可以处理(新建一个Activity去处理),却不太满意。在思考是否做成一个Activity形式的中间件更好(而不是一个Java的class),当然,还有生命周期上的处理,感觉很多东西都有优化的空间。
  • 花了整整一天写的东西,也希望“爬虫们”在转发的同时,也留个原文链接,因为不仅仅是我想把我拥有的知识去分享给他人,我也希望从他人的到宝贵的意见,指出我的错误和不足,这才是我写这篇文章的用意,是作为一个程序员最珍贵的东西,在此谢谢。

源码地址:

https://github.com/yang8456211/UASDKInter

杨光(atany)原创,转载请注明博主与博文链接,未经博主允许,禁止任何商业用途。

博文地址:http://blog.csdn.net/yang8456211/article/details/52231305

博客地址:http://blog.csdn.net/yang8456211

本文遵循“署名-非商业用途-保持一致”创作公用协议

时间: 2024-10-16 14:20:35

Unity3d Android SDK接入解析(四)通用的Android SDK接入中间件的相关文章

Android Bitmap 全面解析(四)图片处理效果对比 ...

对比对象: UIL Volley 官方教程中的方法(此系列教程一里介绍的,ImageLoader的处理方法和官方的差不多) ------------------------------------------------------------------------ 首先单张图片的压缩处理,也是分析重点 专门撸了一个小demo(结尾会放出下载连接)将对应计算方法copy了出来,然后计算了几十组数据,进行了对比 原图宽高都是一个10000以内的随机整数,限定大小是400 200,然后进行压缩处理

Android Volley完全解析(四),带你从源码的角度理解Volley

转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/17656437 经过前三篇文章的学习,Volley的用法我们已经掌握的差不多了,但是对于Volley的工作原理,恐怕有很多朋友还不是很清楚.因此,本篇文章中我们就来一起阅读一下Volley的源码,将它的工作流程整体地梳理一遍.同时,这也是Volley系列的最后一篇文章了. 其实,Volley的官方文档中本身就附有了一张Volley的工作流程图,如下图所示. 多数朋友突然看到一张这样

Android进阶:十四、熟悉Android打包编译的流程

Android进阶系列性文章最后一篇,之后我会更新其他系列性文章,欢迎关注 从事Android高级研发,怎能不知道Android的打包流程呢?今天就为大家讲解Android打包的流程: Android 构建系统编译应用资源和源代码,然后将它们打包成可测试.部署.签署和分发的 APK.一般使用 Android Studio开发的时候使用Gradle构建工具包来自动执行和管理构建流程,同时也可以灵活地自定义构建配置.Gradle 和 Android 插件独立于 Android Studio 运行.所

[转]Android Volley完全解析(四),带你从源码的角度理解Volley

转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/17656437 经过前三篇文章的学习,Volley的用法我们已经掌握的差不多了,但是对于Volley的工作原理,恐怕有很多朋友还不是很清楚.因此,本篇文章中我们就来一起阅读一下Volley的源码,将它的工作流程整体地梳理一遍.同时,这也是Volley系列的最后一篇文章了. 其实,Volley的官方文档中本身就附有了一张Volley的工作流程图,如下图所示. 多数朋友突然看到一张这样

36、Android Bitmap 全面解析

Android Bitmap 全面解析(一)加载大尺寸图片 http://www.eoeandroid.com/thread-331669-1-1.html Android Bitmap 全面解析(二)加载多张图片的缓存处理http://www.eoeandroid.com/thread-332399-1-1.html Android Bitmap 全面解析(三)开源图片框架分析1-UIL(上)http://www.eoeandroid.com/thread-333220-1-1.html An

Unity3d Android SDK接入解析(二)Unity3d Android SDK的设计与两种接入方式

一.前言 上篇说清楚了Unity和Android调用的方式,但很多实际接入的部分没有讲的很详细,因为重头在这篇,会详细讲述具体接入Android SDK的方式,和怎么去做一个方便Unity接入的SDK. 传送门: 前篇:Unity3d 与 Android之间的互相调用 http://blog.csdn.net/yang8456211/article/details/51331358 后篇:Unity3d Android SDK接入解析(三)接入Android Library的理解 http://

Android支付接入(四):联通VAC计费

原地址:http://blog.csdn.net/simdanfeg/article/details/9012031 注意事项: 1.联通支付是不需要自己标识软硬计费点的,当平台申请计费点的时候会提交每个计费点是否允许重复支付(即软硬计费点),支付时我们只需要传入相应的计费点即可,平台会帮我们记录哪个是软计费点,哪个是硬计费点. 2.联通需将premessable.txt文件copy到工程assets目录下,用来配置渠道,每个渠道对应不同的渠道号,例如联通渠道号为:“00012243”. 3.游

ubuntu下搭建android开发环境(四)核心篇安装AndroidStudio、sdk、jdk(by 星空武哥)

转载请标注原创地址:http://blog.csdn.net/lsyz0021/article/details/52215996 所有的软件均在ubuntu 14.04 LTS下测试 ubuntu下搭建android开发环境(一)安装ubuntu系统 ubuntu下搭建android开发环境(二)设置ubuntu的root管理员密码 ubuntu下搭建android开发环境(三)ubuntu安装搜狗输入法 ubuntu下搭建android开发环境(四)核心篇安装AndroidStudio.sdk

Android笔记(四十七) Android中的数据存储——XML(三)SAX解析

SAX是一个解析速度快并且占用内存少的xml解析器,非常适合用于Android等移动设备. SAX解析XML文件采用的是事件驱动,也就是说,它并不需要解析完整个文档,在按内容顺序解析文档的过程中,SAX会判断当前读到的字符是否合法XML语法中的某部分,如果符合就会触发事件.所谓事件,其实就是一些回调(callback)方法,这些方法(事件)定义在ContentHandler接口.下面是一些ContentHandler接口常用的方法: startDocument():当遇到文档的开头的时候,调用这