Android 手游聚合SDK小知识(一)
Android 手游聚合SDK小知识(二) 聚合分包
前言
回头想想,在安卓游戏SDK这个领域,我也呆了4年了,从啥都不懂的小菜鸟,逐渐靠自己不断学习,对这个行业也算有了一些理解,趁着最近有空,我想了一下,还是把最近这几年对游戏SDK聚合的一些理解分享出来给大家,希望能和大家一起进步。PS:目前我做的聚合SDK只能适用于国内,海外谷歌包用的是aab,并且海外渠道sdk资源引用时经常不使用反射,所以海外SDK目前我还没想出来如何聚合,希望有朋友能解决这个问题分享给我。
1、渠道SDK
一个游戏需要庞大的用户量,毕竟玩的人越多,越多人充值,老板就赚得越多,你的工资奖金才能越多嘛,这时候就需要接入一些第三方渠道,让他们帮你进行有偿推广,这些第三方渠道拥有大量用户,可以帮你进行迅速的起量,让大家都去玩你的游戏。
1.1、联运渠道SDK
我们可以接入一些联运SDK渠道,使用他们的渠道来帮我们推广游戏,百度、360、应用宝,Huawei、OPPO 等,包含了最核心的登陆、支付等体系。如果接入了这些渠道,就可以使用他们的SDK服务(登陆、支付等)。
当然了,使用这些联运渠道,一般情况下都是要与对方分成的,充值的时候吊起来的是对方的充值界面,先充到对方的账户上,再进行分成,一般来说分成比例从37开到19开不等。
1.2、自有SDK渠道
如同上面说的,联运SDK需要与渠道方分成,而且分成比例极高,这个时候如果老板自己有稳定的推广渠道,就可以使用自有的SDK,说白了,自有SDK和联运渠道SDK本质上没什么区别,也拥有登录、支付等一系列体系,只不过它属于发行公司内的的SDK,使用自有的SDK就可以100%收入归自己了,但是相应的,推广的成本也要自己掏,这里就不赘述了。
内部SDK可以封装在聚合SDK中,也可以单独写成一个moudle,我这里是单独写成了一个moudle,用的时候打包成aar,和聚合sdk一起给cp接入,cp接入后就可以吊起我们自有的SDK,完成登录支付等一系列操作,后续我再将包用脚本进行渠道分包。
2、游戏研发(CP)
游戏研发也就是专门开发游戏的公司,一般称为CP。
3、聚合SDK
在游戏行业中,聚合SDK可以理解为一个中间层,一个桥梁,作用是沟通游戏CP和渠道SDK。
聚合SDK = 聚合层接口 + 渠道SDK(或者是自有SDK)
使用聚合SDK,聚合层接口不变,变得是渠道SDK,可以在游戏接入一次聚合SDK后,用脚本自动反编译回编译,替换掉渠道SDK代码,实现一包多渠道,减少CP方的工作量。
图中是游戏未接入聚合SDK的情况下,调用登录逻辑。
- 游戏客户端调用SDK客户端的登录API进行登录,SDK客户端会拉起登录界面
- SDK客户端在登录界面输入账密或调用第三方登录
- SDK服务端校验登录信息成功,返回userID和token给SDK客户端
- SDK客户端通过回调将userID和token返回给游戏客户端
- 游戏客户端获取到token和userID后,将其传给游戏服务器端
- 游戏服务器将数据传给SDK服务器进行校验
- 校验通过,游戏服务器将用户的账户信息返回给游戏客户端
- 游戏客户端登录成功
上面的步骤解释了游戏和渠道SDK的交互逻辑,理论上CP是可以直接接入SDK渠道的,但是,目前有一个问题,那就是如果有多个SDK渠道怎么办,目前国内大大小小的渠道有上百个,如果要将这上百个渠道挨个接入,这里面的工作量想必巨大无比,需要占用游戏研发非常多的工作时间,那么有没有这么一种方法,游戏研发接入一遍就可以实现完成多个sdk渠道的上架呢,这时候,聚合SDK就应运而生了。
聚合SDK只有一个,游戏研发只用接入一个聚合SDK,然后剩下都交给聚合方,由聚合方进行分包上架。
下图是加入聚合SDK后的登录逻辑:
4、聚合SDK对外接口及注意事项
1、初始化
Application 的初始化,让CP使用或继承我们的Application,我们再继承渠道方的Application。
Activity中的init方法。
2、登录
统一登录接口,接收渠道方的登录回调参数,再将登录回调参数去聚合服务器校验,通过校验后,聚合服务器返回token和userID,聚合SDK再将参数传给游戏客户端,由游戏客户端和服务器完成登录校验。
/*** 登录方法* @param activity 上下文环境*/public void login(Activity activity){Log.v(TAG,"进入登录");}
3、支付
4、注销(切换账号)
5、生命周期
/*** onCreate生命周期方法* @param activity*/public void onCreate(Activity activity, Bundle savedInstanceState){Log.v(TAG,"进入onCreate");Log.v(TAG,"onCreate执行完成");}/*** onResume生命周期方法* @param activity 之前的塔防版署包这里是context*/public void onResume(Activity activity){Log.v(TAG,"进入onResume");Log.v(TAG,"onResume执行完成");}/*** onPause生命周期方法* @param activity 之前的塔防版署包这里是context*/public void onPause(Activity activity){Log.v(TAG,"进入onPause");Log.v(TAG,"onPause执行完成");}/*** onDestroy生命周期方法* @param context*/public void onDestroy(Context context){Log.v(TAG,"进入onDestroy");Log.v(TAG,"onDestroy执行完成");}/*** onRestart生命周期方法* @param context*/public void onRestart(Context context){Log.v(TAG,"进入onRestart");Log.v(TAG,"onRestart执行完成");}/*** onStart生命周期方法* @param context*/public void onStart(Context context){Log.v(TAG,"进入onStart");Log.v(TAG,"onStart执行完成");}/*** onStop生命周期方法* @param context*/public void onStop(Context context){Log.v(TAG,"进入onStop");Log.v(TAG,"onStop执行完成");}
6、退出
/*** 退出游戏弹窗*/public void exitGame(Context context){}
7、数据上报
- 创建角色
- 角色升级
- 进入游戏
- 选择区服
这些场景一般是接收游戏传递过来的数据上报到渠道或聚合sdk中,用于数据统计用
Map map = new HashMap();map.put("uid", "123456"); //角色idmap.put("server_id", "310"); //区服idmap.put("server_name", "houruoyu333"); //区服名称map.put("role_id", "1225883"); //角色idmap.put("role_name ", "houruoyu"); //角色名称map.put("role_level", "3"); //角色等级map.put("game_name", ""); //游戏名称map.put("role_type", "战士"); //角色职业map.put("vip_level", "13"); //vip等级map.put("game_money", "999"); //玩家拥有金币数量map.put("create_role_time", Long.valueOf(1616136064)); //创角时间map.put("level_up_role_time", Long.valueOf(1616136064)); //升级时间map.put("has_gold", "3000"); //补充字段
8、实名认证接口
5、聚合SDK规范
1、尽量少使用第三方开源库,避免和cp引入的依赖发生冲突
2、命名规范
聚合SDK中可能会使用string、color、布局文件等资源,如果和cp或渠道sdk发生重名会很麻烦,会导致合并资源的时候发生冲突。所以一般来说,资源等命名,都需要加上自己独特的前缀,避免冲突,例如:
<string name="houruoyu_app_online">登录</string>
如果不加上 houruoyu_作为前缀的话,很容易冲突。
3、聚合SDK中使用资源索引(R.java),会导致合包的时候资源冲突,或者缺失资源等问题。
解决方法:所有涉及到R.java资源的引用,统一使用context.getResources().getIdentifier(“资源名”, “资源类型”, “包名”);
4、回调统一
建议在初始化处,统一做回调处理,例如:
HouruoyuSDK.getInstance().init(this, new Callback(){@Overridepublic void onInitSuccess() {//初始化成功}@Overridepublic void onInitFailed() {//初始化失败}@Overridepublic void onLoginSuccess(User user) {//登录成功}@Overridepublic void onLoginFailed(String msg) {//登录失败}@Overridepublic void onLoginCancel() {//登录取消}@Overridepublic void exitGame() {//退出游戏}});