美文网首页技术老司机
安卓多SDK接入与集成 (Unity/Cocos2d)

安卓多SDK接入与集成 (Unity/Cocos2d)

作者: 晨辰辰辰辰 | 来源:发表于2017-06-22 16:27 被阅读392次

项目上线期,加上公司原有未配置热更新的Cocos2d / Unity游戏项目的日常更新,工作中遇到了不少多SDK接入集成的事。
打算做一个打包工具,记录进度和遇到的坑。

pre

Unity提供了调用安卓静态和非静态的方法,

/// <summary>
    /// Unity访问安卓非静态方法
    /// </summary>
    public void CallAndroid()
    {
        AndroidJavaClass UnityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        AndroidJavaObject activity = UnityClass.GetStatic<AndroidJavaObject>("currentActivity");
        activity.Call("Init");
    }

    /// <summary>
    /// Unity访问安卓静态方法
    /// </summary>
    public void CallAndroidStatic()
    {
        AndroidJavaClass jc = new AndroidJavaClass("com.sdk.chenchenInterface");
        jc.CallStatic("Login");
    }

    /// <summary>
    /// Unity收到从SDK发来的通知
    /// </summary>  
    /// <param name="s"></param>    s为待解析的json文件
    public void ReceiveNotifyFromSDK(string s)
    {
        Debug.LogError("Unity --------ReceiveNotifyFromSDK--------:" + s);
    }

安卓部分加入相对应的方法,静态函数写在自己定义的类com.sdk.chenchenInterface里面,非静态方法写在安卓程序入口UnityPlayerActivity里面,打一下日志,分别调用成功。将Unity和安卓之间互相调用的流程跑通。

part1 Unity/Cocos部分

每次都把各渠道SDK与游戏登录等逻辑写在一起很混乱,也不能重用,所以需要在这两者之间封装一层
SDKBase为SDK基础类,以后可以让iOS和安卓继承SDKBase,在SDKManager里面进行判断

BaseSDK

public class SDKBase {
    /// <summary>
    /// 初始化
    /// </summary>
    public virtual void Init() { }
    
    /// <summary>
    /// 登录
    /// </summary>
    public virtual void Login() { }

    /// <summary>
    /// 登出
    /// </summary>
    public virtual void Logout() { }

    /// <summary>
    /// 支付
    /// </summary>
    /// <param name="s"></param>
    public virtual void Pay(string s) { }

    /// <summary>
    /// 游戏中心
    /// </summary>
    /// <param name="s"></param>
    public virtual void GameCenter(string s) { }
}

安卓SDK 采用非静态方法

public class SDKAndroid : SDKBase {
    //安卓渠道SDK集成类

    /// <summary>
    /// 安卓渠道SDK的Init接口入口
    /// </summary>
    public override void Init()
    {
        using (AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
        {
            using (AndroidJavaObject jo = jo.GetStatic<AndroidJavaObject>("currentActivity"))
            {
                jo.Call("init");
            }
        }
    }

    /// <summary>
    /// 安卓渠道SDK的Login接口入口
    /// </summary>
    public override void Login()
    {
        using (AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
        {
            using (AndroidJavaObject jo = jo.GetStatic<AndroidJavaObject>("currentActivity"))
            {
                jo.Call("login");
            }
        }
    }

    /// <summary>
    /// 安卓渠道SDK的Logout接口入口
    /// </summary>
    public override void Logout()
    {
        using (AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
        {
            using (AndroidJavaObject jo = jo.GetStatic<AndroidJavaObject>("currentActivity"))
            {
                jo.Call("logout");
            }
        }
    }

    /// <summary>
    /// 安卓渠道SDK的Pay接口入口
    /// </summary>
    public override void Pay(string s)
    {
        using (AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
        {
            using (AndroidJavaObject jo = jo.GetStatic<AndroidJavaObject>("currentActivity"))
            {
                jo.Call("pay", s);
            }
        }
    }

    /// <summary>
    /// 安卓渠道SDK的GameCenter接口入口
    /// </summary>
    public override void GameCenter(string s)
    {
        using (AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
        {
            using (AndroidJavaObject jo = jo.GetStatic<AndroidJavaObject>("currentActivity"))
            {
                jo.Call("gameCenter", s);
            }
        }
    }
}

SDKManager单例类,匹配相应的SDK,并调用相应SDK的接口

调用时直接
chenchenSDKMgr.Instance.Init();
这样就把SDK与项目逻辑隔离开,框架可以重复使用了

public class chenchenSDKMgr : MonoBehaviour {

    private static chenchenSDKMgr mInstance;

    public static chenchenSDKMgr Instance
    {
        get {
            if (mInstance == null)
                mInstance = new chenchenSDKMgr();
            return mInstance;
        }
        
    }

    private static SDKBase mSDKApi;

    void Awake()
    {
        mInstance = this;

#if UNITY_EDITOR
        mSDKApi = new SDKBase();
#elif UNITY_ANDROID //切换iOS/安卓(不同渠道)
        mSDKApi = new SDKAndroid();
//#elif UNITY_IOS
#endif
    }

    public void Init()
    {
        mSDKApi.Init();
    }

    public void Login()
    {
        mSDKApi.Login();
    }

    public void Logout()
    {
        mSDKApi.Logout();
    }

    public void Pay(string s)
    {
        mSDKApi.Pay(s);
    }

    public void GameCenter(string s)
    {
        mSDKApi.GameCenter(s);
    }

    /// <summary>
    /// Unity收到从SDK发来的通知
    /// </summary>  
    /// <param name="s"></param>    s为待解析的json文件
    public void ReceiveNotifyFromSDK(string s)
    {
        Debug.LogError("Unity --------ReceiveNotifyFromSDK--------:" + s);
    }

}

part2 Eclipse部分

新建一个Unity空工程,将他导出到ADT,作为SDK基类使用,libs里面有unity-classes.jar这个文件,就可以实现Unity部分的回调等,新建一个Android项目空工程,是具体某个渠道的SDK,把android-support-v4.jar文件(安卓相关)拷到上面那个工程中。
基类工程中新建BaseActivity Class,作为UnityPlayerActivity的扩展

public class BaseActivity extends UnityPlayerActivity{
    public static String mUnityListenerObject = "chenchenSDK";
    public static String mUnityListenerMethod = "ReceiveNotifyFromSDK";
    
    @Override
    public void onCreate(Bundle b) {
        super.onCreate(b);
    }
}

将两个项目都设置成库,并且渠道SDK引用基类SDK
MainActivity类继承BaseActivity,把Unity调用的安卓方法实现。

public class MainActivity extends BaseActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
    public void login() {
        Log.i("Unity", "login -------------- SDK");
    }    
    public void init() {
        Log.i("Unity", "init ---------------SDK");
    }    
    public void logout() {
        Log.i("Unity", "logout -------------SDK");
    }    
    public void pay(String s) {
        Log.i("Unity", "pay ----------------SDK");
    } 
    public void gameCenter(String s) {
        Log.i("Unity", "gameCenter -------------SDK");
    }
}

使用的时候,将基类SDK和渠道SDK build出来的jar包导入Unity工程中。将渠道SDK的AndroidManifest文件也导入。
这样启动项为渠道SDK项目的MainActivity,然后从渠道SDK去调用基类

======================2017.6.28

Cocos2d-lua部分

如果项目使用Cocos引擎,需要在C++框架层使用jni与java底层交互,使用CallStaticMethod方法,获取SDK传回来的Callback,游戏逻辑内解析后传到服务器归档。
UserActivity单例模式,如果在Cocos中使用Require头文件,需要注意如果不写一个单例模式get方法的话,多次返回会产生不同的User类,在别的文件中访问就会被初始化。

jni返回一次登陆数据之后,可以进行归档,将微信和qq三方授权的TokenID和密码存储在本地并手动创建一个原生的账号,可以避免多次请求微信授权的问题。
密码在游客登录的时候已经自动生成,需要执行一次修改密码的操作。如果绑定了手机,就不用进行密码修改。在不同的渠道,该操作均相同,所以需要保留渠道信息。

结合新手引导界面

有两种方式,第一种是在界面上放一层遮罩,通过改变按钮的层级来改变他们的交互性(是否能够进行响应),第二种是动态改变按钮的位置和响应方法,使用入口函数做成Manager来实现。
第一种方式较为复杂但是易读,但是可以写config配置文件来较为方便的修改前后顺序。第二种实现较为简单。

我自己使用的是第二种方法。

相关文章

网友评论

    本文标题:安卓多SDK接入与集成 (Unity/Cocos2d)

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