网站版接入文档

本文介绍如何接入SOT的网站版SDK,接入后即可使用本网站来管理补丁的分发,无需再自己搭建服务器。网站每月免费赠送价值100元的补丁流量,可以满足月活百万的App使用了。

接入SOT热更新,需要对编译工具和流程做一些改变,虽然门槛较高,但只需要做一次即可。教程使用的是x86 cpu架构的Mac电脑,并且用模拟器进行测试。M1的电脑无法使用模拟器测试,但可以直接测试真机。使用的Xcode版本为14.3.1,以示例工程「 ShipOTDemo 」为例。工程有两个分支,读者可以用main分支,然后跟随本篇教程,一步步接入。sot是配置好的分支,只需要下载解压SDK到项目根目录,并安装SDK,就可以测试SOT热更新。

这是一个很简单的工程,仅仅为了演示如何接入SDK,下载工程后,Xcode14直接打开应该就能编译成功和运行: ...

Step1: 下载SDK

「 下载SOT的SDK 」,请用1.16及以上版本,解压到示例工程的目录中: ...


Step2: 工具链修改

先运行一下xcode-select --install安装xcode命令行工具,然后运行 sudo xcode-select --switch Xcode.app的路径,把”xcode.app的路径“改成你mac上的xcode的路径,例如我的是/Applications/Xcode.app。

在terminal运行命令:sudo sh /Applications/ShipOTDemo/sotsdk/compile-script/install.sh, 会把SDK目录compile-script下的clang, libtool, swift等脚本安装到本地编译工具链里,需要输入root密码。/Applications/ShipOTDemo/是我放工程的目录,你按照自己的目录来。 ...

可以自己检查一下是否安装成功,命令行运行:xcrun --find sot_link.sh,例如我的会得到结果 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/sot_link.sh,进入到该目录还能看到其余安装进去的脚本: ...

修改编译工具链不会影响正常项目的编译,假如不想接入SOT SDK了,要完全恢复原状,运行compile-script下的uninstall.sh就行。如在命令行输入sudo sh /Applications/ShipOTDemo/sotsdk/compile-script/uninstall.sh

注意,即使有多个项目接入SOT,也只有第一次需要运行install.sh脚本,不用每个工程都运行。


Step3: 增加Configuration

增加1个Configuration,只有切换到这个Configuration才使用SOT编译模式。这样我们平时还是用原来的Configuration做开发,等到真正要出包给到商店时,才切换到SOT编译模式,对项目影响达到最小,添加的步骤如下:

选中ShipOTDemo Project,然后选择Info面板,点击Configurations的下面加号,复制Release的编译配置,并且命名为SotRelease,别的名字也可以,但注意名字都不要留有空格: ... 加完就是: ... 注意:本例只有此处需要添加,但如果你应用到自己项目中时,需要把所有的Project都加上这个Configuration,否则编译会报找不到文件等等的错误。所以加完这个Configuration之后,就马上去Edit Scheme切换一下,然后Build和Run一下,看是否有编译错误。 ... 如果没有编译错误,正常运行的话,再进行后面的操作。如果有错误,请检查是否漏了一些工程没有添加上。


Step4: 修改编译选项

添加热更需要的编译选项,添加SOT虚拟机静态库等,步骤如下:

  1. 选中ShipOTDemo,选择Build Settings: ...
  2. Other Linker FlagsSotRelease中添加中添加-sotmodule $(PRODUCT_NAME) $(SRCROOT)/sotsdk/libs/libsot_web.a -sotsaved $(SRCROOT)/sotsaved/$(CONFIGURATION)/$(CURRENT_ARCH) -sotconfig $(SRCROOT)/sotsdk/project-script/sotconfig.sh ...

    每个选项的意义如下:

    • -sotmodule是module的名字,可以直接用$(PRODUCT_NAME)。也可以自定义名字,名字不要有空格,如果$(PRODUCT_NAME)有空格,需要改掉,改成固定值即可
    • -sotsaved是编译中间产物保存的目录,补丁自动化生成需要对比前后编译的产物来生成补丁
    • -sotconfig指定了项目sotconfig.sh的路径,该脚本控制sot编译器的工作
    • sotsdk/libs/libsot_web.a是SOT虚拟机静态库的路径,链接的是网站版的虚拟机

  3. Other C FlagsSotRelease下添加-sotmodule $(PRODUCT_NAME) -sotconfig $(SRCROOT)/sotsdk/project-script/sotconfig.sh,意义跟上一步是一样的,需要保持一致。 ...
  4. 如果这个Target有Swift代码,在Active Compilation Conditions的SotRelease下添加sotmodule=$(PRODUCT_NAME) sotconfig="$(SRCROOT)/sotsdk/project-script/sotconfig.sh" ...

  5. 目前还不支持m1芯片的模拟器,所以需要排除模拟器的arm64架构,或者把Build Active Architecture Only改为Yes ...

  6. Preprocessor Macros添加USE_SOT=1,后面用来控制是否编译调用SDK的代码 ...

  7. 选中SwiftTest Target,把它的Mach-O Type改为Static Library(推荐静态库热更比较好,动态库也可以,但需要每个动态库都需单独链接libsot)。

    静态库容易很多,重复跟ShipOTDemo差不多的步骤设置:

    • Other C Flags的SotRelease增加-sotmodule $(PRODUCT_NAME) -sotconfig $(SRCROOT)/sotsdk/project-script/sotconfig.sh
    • Active Compilation Conditions的SotRelease下添加sotmodule=$(PRODUCT_NAME) sotconfig="$(SRCROOT)/sotsdk/project-script/sotconfig.sh"
    • 区别是对于非主Target,是在Other Librarian Flags配置,而不是Other Linker Flags并且不需要链接libsot_web.a: -sotmodule $(PRODUCT_NAME) -sotsaved $(SRCROOT)/sotsaved/$(CONFIGURATION)/$(CURRENT_ARCH) -sotconfig $(SRCROOT)/sotsdk/project-script/sotconfig.sh
    全部配好后大致结果如下: ... 自己的项目如果有多个Target需要热更,都要按照这样配置一下。
  8. 最后需要注意,刚才这些配置里的路径和项目名,不要有空格,否则添加的这些配置就会被空格隔开,导致一个变两个,出现错误。

Step5: 增加补丁拷贝脚本

SDK里提供了一个便利脚本,可以sdk目录里找到的project-script/sot_package.sh,它会把生成的补丁拷贝到Bundle文件夹下,方便我们找到它上传到网站。需要在每次SotRelease编译时调用这个脚本,按下面步骤添加:

...

脚本内容为:


if [[ "$CONFIGURATION" == "SotRelease" ]];then
  sh "$SOURCE_ROOT/sotsdk/project-script/sot_package.sh" "$SOURCE_ROOT/sotsdk/project-script/sotconfig.sh" "$SOURCE_ROOT/sotsaved/$CONFIGURATION" ShipOTDemo SwiftTest
fi
    

可以注意到脚本里有两个参数,分别是ShipOTDemoSwiftTest,这个是跟前面添加的Other C Flags里面的-sotmodule $(PRODUCT_NAME)对应的,因为$(PRODUCT_NAME)在这里会被Xcode替换成ShipOTDemo和SwiftTest,所以才能对应上了。如果是你自己的项目,这里要改成对应的名字。

并且把Based on dependency analysis的勾去掉,确保每次编译都会调用。 ...


Step6: 链接C++库

链接libz.tbdlibc++.tbd

还是在这个页面下,打开Link Binary With Libraries页,加入下面这两个库 ...


Step7: 调用SDK API

需要提前在代码里增加调用补丁同步API的代码:

打开ViewController.m文件,先增加引用SOT网站服务API的头文件的代码:

#ifdef USE_SOT
#import "../sotsdk/libs/SotWebService.h"
#endif
    
...

然后再在下面的函数SotUpdate添加下面的代码:

#ifdef USE_SOT
    SotApplyCachedResult ApplyShipResult = [SotWebService ApplyCachedAndPullShip:version_key_str is_dev:false cb:^(SotDownloadScriptStatus status)
        {
            if(status == SotScriptShipAlreadyNewest)
            {
                NSLog(@"SyncOnly SotScriptShipAlreadyNewest");
            }
            else if(status == SotScriptShipHasSyncNewer)
            {
                NSLog(@"SyncOnly SotScriœœptShipHasSyncNewer");
            }
            else if(status == SotScriptShipDisable)
            {
                NSLog(@"SyncOnly SotScriptShipDisable");
            }
            else
            {
                NSLog(@"SyncOnly SotScriptStatusFailure");
            }
        }];

        if(ApplyShipResult.Success)
        {
            if(ApplyShipResult.ShipMD5)
                NSLog(@"sot success apply cached ship md5:%@", ApplyShipResult.ShipMD5);
        }
#endif
    
...

这段代码用一个version_key_str做为唯一的Key向网站拉取补丁,如果拉取成功会把补丁保存下来,下次再调用该API时便能加载这个补丁。在这个示例程序中,version_key_str是通过一个文字输入控件获取的,后面会介绍如何在网站注册,然后获得VersionKey,等启动程序后输入到输入框里,就可以进行补丁拉取。

具体调用的是ApplyCachedAndPullShip这个API,补丁的同步需要考虑网络延迟等问题,可以看「 同步补丁API 」的解释。

如果是用户自己的程序,在网站获得了VersionKey之后,调用API的代码直接写死对应的VersionKey就可以了,本文这里只是为了演示。


Step8: 获得VersionKey

  1. 第一步当然是注册网站,成为会员。点击跳转注册页面,免费注册,注册需要验证邮箱,然后登录。
  2. 从导航栏进入我的APP:...
  3. 点击创建APP,弹出弹窗填写APP的名字:...
  4. 进入APP页面,点击右上角的创建新版本按钮,会弹出弹窗,需要选择网站版,SDK版本选择1.1,然后输入版本号,版本号可以是随意字符串,方便自己区分就行。 ...
  5. 创建版本成功后,点击版本,进入版本页面,左上角是唯一标识该版本的VersionKey,上一步的API接口可以直接写死这个Key。 ...


热更编译和生成补丁

按上面配置完之后,还需要控制sotconfig.sh的开关,否则编译出来的APP是无法热更的,SOT热更流程分为两部分,一部分是热更注入,一部分是生成补丁。

Step1: 热更注入

打开sotconfig.sh,文件在sotsdk/project-script目录下,里面有两个开关,EnableSotGenerateSotShip

  • 如果EnableSot=0,那么编译出来的APP跟原来是没有区别的,无法使用SOT热更
  • 编辑Edit Scheme,Run先切换到SotRelease,设EnableSot=1,GenerateSotShip=0,表示要对APP进行热更注入
  • clean项目后build项目,如果成功的话,这个app就具备了热更能力了,这时去看编译的.m文件的日志,能看到run sot clang compile字样的输出,如果看Target的link日志,会有更多详细内容,提示了哪些函数可以被热更等信息,详细解释看「 热更配置 」
  • 同时可以发现之前配置的sotsaved目录里也多了很多文件,这些文件不能删除,需要保留

此时去看构建日志,能看到很多SOT输出的信息: ... ...

切记如果是自己的APP,要打包发商店,打包是Archive要切换到SotRelease,本文只是测试,不用改这一步也可以: ...


Step2: 生成补丁并上传

按上一步编译成功后,运行APP,点击Run按钮,看到输出的是hello SOT: ... 接下来通过生成补丁,把hello SOT改成其它字。

  1. 设置sotconfig.shEnableSot=1,GenerateSotShip=1,此时代表后续编译都是用来生成补丁的。
  2. 然后修改源代码,把Viewcontroller.m里的RunDemoCode里的hello SOT改成hello SOT test patch ...
  3. Build项目,如果没有任何报错的话,就能在Bundle目录下得到热更补丁了,找到它的步骤如下,对Products的.app右键,选择Show In Finder ... 然后对APP右键选择Show Package Contents,进到Bundle目录里: ... 补丁文件就是sotship_xxxx.sot,xxxx是它的编译架构,本例是模拟器所以是x86_64: ...
  4. 接下来把这个补丁上传到网站上,先回到网站的版本页面,点击右侧上传补丁按钮,然后如果是真机选arm,否则模拟器选x86: ... ...
  5. 上传成功后,补丁默认是停用状态,需要点击左下角的编辑来启用它: ...
  6. 这里选择全量启用,点击下面的提交按钮,然后补丁就会成功启用了: ...


Step3: 测试补丁拉取

运行APP,点击Run按钮,看到输出的是hello SOT。 ...

此时把刚才在网站得到的VersionKey填入上面的控件中,并且点击Sot Sync按钮。 ...

会在Xcode控制台得到类似下面的输出,意思是同步到了最新的补丁。 ...

再点一次Sot Sync按钮,就会加载刚才下载好的补丁,并且会再次去同步补丁。 ...

这时候去点击Run按钮,就得到了新的输出, ...

下次再打开APP,第一次点击Sot Sync按钮就会成功加载补丁,因为补丁被缓存了下来。如果接下来同步到最新的补丁,就会把缓存的补丁替换掉。

特别说明:

不是所有新加的代码都能够生效,举个例子来说,如果调用了老代码没有调用过的函数,就可能不会生效。这个Demo工程只是用来演示的,原本的代码量很少,不用对其做过多测试。具体什么能热更生效,什么不能,参看文档「 热更能力 」

有任何问题可以到「 github发issue 」,我们会统一解答,也方便其他人看到。


网站版FAQ

1: 费用是多少?

APP每同步一次补丁信息,则消耗1瓦力,1元能够买10000瓦力。同步补丁信息发现有新补丁要下载,则还需按补丁大小额外收费,补丁每100KB消费3瓦力,不足100KB按100KB计算。假如同步补丁信息后发现已经下载过此补丁,则不会重新下载了,只消耗同步补丁信息的费用。举个例子,每日10000用户使用APP,那每日同步补丁信息消耗10000瓦力,开发每5日发布一个新补丁,大小100KB,发布新补丁后,APP需要下载此补丁,第一次下载的时候消费3瓦力,此后不需要再消耗下载费用。

目前每月赠送用户100万瓦力,足够百万月活的App使用了,无需充值。

注意:此处的补丁大小并不是指用户上传的补丁的大小,而是上传后经过网站解析生成的产物,并且使用zlib压缩过的大小,上传后才可以看到,通常比用户生成的补丁大小要小一些。

2: 假如APP没有网络,能热更吗?

网站版提供了两种同步补丁的方式,Sync接口必须是通过网络同步到补丁信息,才能加载补丁,APP没有网络的情况下,则调用Sync接口会失败,也不会加载到任何补丁,即使之前有网并且成功同步过也一样。而ApplyCachedAndPullShip接口则可以在无网络情况下也能加载上次缓存好的补丁,具体请看「 同步补丁API 」解释。

3: 网站版补丁支持多少并发?

补丁信息都保存在CDN上,支持非常高的并发,即使本网站被攻击无法访问,也不影响APP同步补丁,所以可以放心使用。

4: 如果欠费怎么办?

如果账户瓦力值小于0时,则APP无法加载任何补丁,即使它们之前已经同步到了最新的补丁。可以在版本信息页面看到每个版本消耗的瓦力值,网站统计瓦力的消耗有几分钟的延迟。另外需要说明的是,欠费并且重新充值后,可能也会有几分钟延迟APP才能重新同步并加载补丁,此时如果着急,可以编辑一下版本信息,可能能让CDN更快的刷新缓存。

5: 最大支持多大补丁?

目前最大支持5MB的补丁,补丁大小通常不会那么大,取决于要修复的代码。当然也可以把本方案用于减包,把大量逻辑生成为补丁,原生代码在热更注入时就删掉了,如何配置sotconfig.sh请看:「 热更配置 」