37手游SDK架构分享

37手游SDK架构分享

大家好,我是加权,本篇文章向大家分享下发行SDK的架构。

需求背景

问题

作为发行SDK,通常需要面对的几大需求

  1. 渠道需求,研发接入发行SDK后,可以适配到TapTap,华为,应用宝等其他渠道

  2. 广告上报需求,广告投放时,需要接入不同的上报SDK,如抖音,腾讯等

  3. 皮肤替换需求,如特定游戏皮肤定制

  4. 试验性功能,如当前较常见的云游戏、直播等功能,特点时效果不佳时会移除

方案:插件化

以上需求,最大的问题是要解决功能灵活性的问题,需要做到面对不同的渠道、广告,游戏,做到功能灵活删减。

为此我们引入功能插件化的概念。

通常行业中的插件化是指

是将整个App拆分成很多模块,每个模块都是一个Apk(组件化的每个模块是一个lib),最终打包的时候将宿主Apk和插件Apk分开打包,只需发布宿主Apk到应用市场,插件Apk通过动态按需下发到宿主Apk。

这里我们只需要实现模块为apk,在切包时灵活组合即可,动态下发、加载可以视为高阶功能,本文不讨论。

方案架构

切包架构

切包是实现插件化的关键步骤,基本架构如下

16117b6a681187ee95418620e916b9f0.png

  1. 37 SDK*(蓝色):是指提供给研发接入的sdk,当不涉及对外API改动时,不需要更新

  2. 37 SDK(绿色):是指包含核心功能的apk包

  3. 渠道功能、广告工程(插件工程/模块):是用来构建插件apk的工程/模块

通过切包流程需要实现

  1. 覆盖37 SDK*(蓝色)的代码,实现功能更新

  2. 合并核心apk和插件apk,往最终包体中接入插件功能

具体的工程结构如下

bed00547c5af8d877071d5a5bc1948f1.png

  1. 打包后台:统一管理sdk、插件、母包以及插件参数

  2. 切包主工程:核心切包逻辑

  3. 补丁工程:针对特殊游戏或者渠道定制化切包流程时使用

  4. 母包:由研发提供

  5. sdk apk:核心功能apk

  6. 插件apk:插件功能apk

代码架构

在具体实现中,为了实现功能的灵活组装,我们需要解决以下问题

  1. 插件不存在的情况

    1. 插件不存在,意味着功能不可用,我们在代码中需要进行特殊处理,避免程序异常

  2. 存在多个插件的情况

    1. 多个插件,意味着我们需要有手段选择具体插件,例如增加配置文件和后台下发配置

  3. 新增插件的情况

    1. 当某个功能没有预留插件功能,需要新增开发,我们需要有手段让旧版本也可以动态加载该插件功能

为了实现以上目的,代码构架设计如下(以登录功能为例)

6e2b9f994163780993f623e99a3a8502.png

我们对功能实现划分以下概念

  1. 对外接口类:这里会直接引入管理类,是所有功能的集合,我们直接替换整个对外接口类就可以实现替换任意功能

  2. 管理类抽象:在代码实现中,大部分都是引用管理类抽象类,这样在替换实现时不会出现问题

  3. 管理类实现:管理类通常是同个模块下多个功能的组合,这样可以提供手段批量替换多个功能

  4. 功能抽象:单一功能的抽象,是最常用的插件层级

  5. 功能实现:具体的实现

对功能进行划分后,我们就可以根据实际需要,使用插件类对不同的类进行替换,来实现不同程度的功能替换。

关于如何处理无插件情况和插件配置化,在下文讲解

插件

参数

对于大多数第三方sdk,都有单独的参数,因此当我们通过插件接入第三方功能时,我们需要有手段处理这些插件的参数。

这里我们主要通过字符串资源获取参数,并通过gradle插件脚本处理参数文件的方式处理,架构如下

10141c784dd9203404e9d94fafdc043d.png

  1. 打包后台:统一管理插件和参数,可以输出sdk和插件关联的参数到json中

  2. JSON参数文件:sdk和插件使用的所有参数

  3. 参数插件、切包工程:逻辑一样,将JSON参数文件中的参数转换成string资源

这里利用了安卓字符串资源加载的特点,可以做到

  1. 编译时修改参数

  2. 动态获取参数,可以通过切包修改参数

实例化

插件的实例化常见的几种形式

  1. 代码枚举

    1. 通过直接枚举所有插件类型进行实例化

  2. 配置文件/接口下发

    1. 根据配置文件的类型,将对应插件实例化

  3. 插件注入

    1. 插件apk自己注入插件实例到sdk中

我们实际会结合第2和第3种方法处理插件的实例化问题

配置文件/接口下发

42e6ad603a0ea9d92399b986b3628dbd.png

关键步骤

  1. 通过读取文件或者接口下发的配置获取配置项

  2. 根据配置项,通过插件管理类获取插件实例

  3. 在插件不可用时,返回fake实例,避免程序异常


插件注入

根据配置获取实例时,我们可以指定插件类型获取,那么sdk是如何知道有哪些插件的呢,比较合适的方法是让插件自己持有插件信息,通过切包注入插件信息到skd中,这样sdk本身对插件完全无感知,解耦更加彻底。

代码架构如下图

4f70ae92d968d609f421a5300e00d237.png

  1. PluginContentProvider:我们利用provider的特点,在应用启动时,通过解析AndroidManifest.xml中的meta-data来获取插件信息,然后注册到PluginManager中

  2. PluginManager:保存所有插件信息,注意在外部获取插件时才实例化插件

  3. Plugin Apk:插件apk,带有插件的meta-data信息,在切包时把插件信息合并到sdk中,实现注入

  4. 插件注解+脚本:使用注解标记插件类,并且利用脚本自动生成插件信息,可以提高插件开发效率和出错几率

至此,我们就已经完整构建了整个插件化架构,包括了插件的基本架构,sdk使用插件的形式,切包架构等多个模块。

总结

使用插件化架构需要多个模块互相配合,关键点如下

  1. 代码需要足够解耦,功能需要足够抽象

  2. 插件模块,包含注册插件、插件实例化等

  3. 切包模块,需要支持多apk融合,并且可以处理多插件参数等情况

  4. sdk模块,需要支持适配多插件情况

  5. 打包后台,需要管理所有插件

整个方案大致就是这样,欢迎大家在评论区回复讨论~

作者:37手游移动客户端团队
链接:https://juejin.cn/post/7306485968135733298

关注我获取更多知识或者投稿

66f7679bce820e3bc17ab3017765c997.jpeg

1cc192e598865d071bdb5f77b999e92d.jpeg

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值