美文网首页
[JSPatch] 初尝JSPatch快速集成

[JSPatch] 初尝JSPatch快速集成

作者: 任尔东西南北疯 | 来源:发表于2017-04-22 21:56 被阅读487次

    JSPatch作为热更新技术的黑科技,已经不是什么前沿的新闻了,像腾讯、美团等大公司也在使用JSPatch。前段时间苹果对使用这些像JSPatch,weex等热更新技术下发警告通知或强制下架的事,技术圈里让很多小伙伴们坐不住了,闹的沸沸扬扬,这个15年就问世的框架具备很多之前的类似框架所不具备的优点,更加的小巧便捷,并且处于持续维护中,不仅如此,还由此成为了一个生态圈,bang神还为此开发了oc转js的代码转换器、可以自动提示的JSPatchX插件、以及基于这个技术的JSPatchPlatform平台。总之让大伙可以很方便的进行patch。作为技术方面的一个小探索,抱着学习的态度,初次测试一下效果。

    如何混淆JSPatch热修复框架以绕过苹果的机器检测

    • HotFix概述
    • 集成JSPatch

    <h3>HotFix概述</h3>

    iOS中的HotFix方案总结详解

    对于iOS,这种HotFix方案大致可以分为四种:

    • WaxPatch(Alibaba)
    • Dynamic Framework(Apple)
    • React Native(Facebook)
    • JSPatch(Tencent)

    WaxPatch
    WaxPatch是一个通过Lua语言编写的iOS框架,不仅允许用户使用 Lua 调用 iOS SDK和应用程序内部的 API, 而且使用了 OC runtime 特性调用替换应用程序内部由 OC 编写的类方法,从而达到HotFix的目的。

    WaxPatch的优点在于它支持iOS6.0,同时性能上比较的优秀,但是缺点也是非常的明显,不符合Apple3.2.2的审核规则即不可动态下发可执行代码,但通过苹果JavaScriptCore.framework或WebKit执行的代码除外;同时Wax已经长期没有人维护了,导致很多OC方法不能用Lua实现,比如Wax不支持block;最后就是必须要内嵌一个Lua脚本的执行引擎才能运行Lua脚本;Wax并不支持arm64框架。


    Dynamic Framework
    动态的Framework,其实就是动态库;首先我介绍一下关于动态库和静态库的一些特性以及区别。

    不管是静态库还是动态库,本质上都是一种可执行的二进制格式,可以被载入内存中执行。
    iOS上的静态库可以分为.a文件和.framework,动态库可以分为.dylib(xcode7以后变成了.tdb)和.framework。

    • 静态库: 链接时完整地拷贝至可执行文件中,被多次使用就有多份冗余拷贝。
    • 动态库: 链接时不复制,程序运行时由系统动态加载到内存,供程序调用,系统只加载一次,多个程序共用,节省内存。

    静态库和动态库是相对编译期和运行期的:静态库在程序编译时会被链接到目标代码中,程序运行时将不再需要改静态库;而动态库在程序编译时并不会被链接到目标代码中,只是在程序运行时才被载入,因为在程序运行期间还需要动态库的存在。

    • 总结:同一个静态库在不同程序中使用时,每一个程序中都得导入一次,打包时也被打包进去,形成一个程序。而动态库在不同程序中,打包时并没有被打包进去,只在程序运行使用时,才链接载入(如系统的框架如UIKit、Foundation等),所以程序体积会小很多。

    好,所以Dynamic Framework其实就是我们可以通过更新App所依赖的Framework方式,来实现对于Bug的HotFix,但是这个方案的缺点也是显而易见的它不符合Apple3.2.2的审核规则,使用了这种方式是上不了Apple Store的,它只能适用于一些越狱市场或者公司内部的一些项目使用,同时这种方案其实并不适用于BugFix,更适合App线上的大更新。所以其实我们项目中的引入的那些第三方的Framework都是静态库,我们可以通过file这个命令来查看我们的framework到底是属于static还是dynamic。


    React Native
    React Native支持用JavaScript进行开发,所以可以通过更改JS文件实现App的HotFix,但是这种方案的明显的缺点在于它只适合用于使用了React Native这种方案的应用。


    JSPatch
    JSPatch是只需要在项目中引入极小的JSPatch引擎,就可以使用JavaScript语言调用Objective-C的原生接口,获得脚本语言的能力:动态更新iOS APP,替换项目原生代码、快速修复bug。但是JSPatch也有它的自己的缺点,主要在由于它要依赖javascriptcore,framework,而这个framework是在iOS7.0以后才引入进来,所以JSPatch是不支持iOS6.0的,同时由于使用的是JS的脚本技术,所以在内存以及性能上面是要低于Wax的。


    <h3>集成JSPatch</h3>

    JSPatch 需要使用者有一个后台可以下发和管理脚本,并且需要处理传输安全等部署工作,JSPatch 平台帮你做了这些事,提供了脚本后台托管,版本管理,保证传输安全等功能,让你无需搭建一个后台,无需关心部署操作,只需引入一个 SDK 即可立即使用 JSPatch。

    Github 开源的是 JSPatch 核心代码,使用完全免费自由,若打算自己搭建后台下发 JSPatch 脚本,可以直接使用 github 上的核心代码,与 JSPatch 平台上的 SDK 无关。JSPatch 平台的 SDK 在核心代码的基础上增加了向平台请求脚本/传输解密/版本管理等功能,只用于这个平台。

    官方接入文档
    注册JSPatch平台账号

    1.从官网上下载提供的SDK API包来后,导入工程,在TARGETS -> Build Phases -> Link Binary With Libraries -> + 添加 libz.dylib 和 JavaScriptCore.framework
    2.生成和配置RSA密钥
    自定义 RSA 密钥对 RSA 密钥的作用详见安全问题。目前为了更高的安全性,平台强制要求所有补丁下发都使用自定义 RSA 密钥,生成 RSA 密钥,在 Mac 终端上执行 openssl,再执行以下三句命令,生成 PKCS8 格式的 RSA 公私钥,执行过程中提示输入密码,密码为空(直接回车)就行。

    openssl >
    genrsa -out rsa_private_key.pem 1024
    pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM –nocrypt
    rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
    

    生成的公私钥,在上传布丁时要用:


    RSA 公私钥

    用JSPatch�官网工具中提供的RSA配置工具,拖入公钥文件直接生成配置代码


    RSA生成配置代码

    注册账号成功后,在我的App中添加新应用,应用的图标生成是填写了已上架应用的Appkey,这里只是测试,就没必要了,确定之后会生成平台应用的AppKey

    添加新APP
    3.在 AppDelegate.m中按顺序调用startWithAppKeysetupRSAPublicKeysync方法,可以把 [JSPatch sync] 放在 -applicationDidBecomeActive: 里,每次唤醒都能同步更新 JSPatch 补丁,不需要等用户下次启动
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        
        /**
         *AppKey:JSPatch添加应用时生成的AppKey
         *RSAPublicKey:刚才生成的公钥RSA字符串
         */
        [JSPatch startWithAppKey:@"834abc498b14c64b"];
        [JSPatch setupRSAPublicKey:@"-----BEGIN PUBLIC KEY-----RSABLABLABLA45/44DJFJJNKSDLKS-----END PUBLIC KEY-----"];
    
        //用来检测回调的状态,是更新或者是执行脚本之类的,相关信息,会打印在你的控制台
        [JSPatch setupCallback:^(JPCallbackType type, NSDictionary *data, NSError *error) {
            NSLog(@"error-->%@",error);
            switch (type) {
                case JPCallbackTypeUpdate: {
                    NSLog(@"更新脚本 %@ %@", data, error);
                    break;
                }
                case JPCallbackTypeRunScript: {
                    NSLog(@"执行脚本 %@ %@", data, error);
                    break;
                }
                case JPCallbackTypeCondition: {
                    NSLog(@"条件下发 %@ %@", data, error);
                    break;
                }
                case JPCallbackTypeGray: {
                    NSLog(@"灰度下发 %@ %@", data, error);
                    break;
                }
                default:
                    break;
            }    }];
        
        [JSPatch setupDevelopment];
        [JSPatch sync];
        
        return YES;
    }
    

    4.在ViewController中创建一个laber,声明一个test方法用来给laber赋值

    
    #import "ViewController.h"
    
    @interface ViewController ()
    @property (nonatomic, strong) UILabel *textLaber;
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        
        self.textLaber = [[UILabel alloc] initWithFrame:CGRectMake(0, 50, self.view.frame.size.width, 60)];
        _textLaber.textAlignment = NSTextAlignmentCenter;
        _textLaber.backgroundColor = [UIColor cyanColor];
        [self.view addSubview:_textLaber];
        
        [self test];
    }
    
    - (void)test{
        self.textLaber.text = @"像疯了一样";
    }
    
    @end
    

    5.创建main.js, 保存

    console.log('run success')
    defineClass("ViewController", {
                test: function() {
                self.textLaber().setText("内容就这样改变了");
                },
    })
    
    

    6.就是发布布丁了,布丁文件就是上面的main.js文件,RSA密钥就是生成的,**rsa_public_key.pem **公钥文件,因为只是测试,所以勾选开发预览选项,

    • 开发预览:是用来测试开发用的
    • �全量下发:给所有安装布丁的人下发
    • �条件下发:可以根据JSPatch设定的userId设定筛选条件下发
    • 灰度下发:按人数灰度可以指定补丁对多少个用户生效,超过设置的人数后不会再生效。灰度人数可以修改增加,但不能减少,可以逐渐增加灰度人数,直到全量发布。
    发布布丁

    点击提交之后,显示发布成功


    布丁详情

    7.再看看我们的demo,�打印台收到如下消息就说明布丁更新加载成功

    success

    即使这样,你还会发现,laber的值并没有改变啊,好吧,因为补丁是先下载再生效的,所以下一次运行你才能看到效果,后续我会不断去踩坑,这是我们在main.js 中设的值

    屏幕快照 2017-04-22 21.48.26.png

    可坑能踩的坑

    • 布丁脚本加载成功,却出错MD5加密之类的,当然就是你的�RSA公私钥有问题喽,重新生成一份
    • JSPatch网站上的版本要一定要和工程里的一样
    • label的名字别写错了
    • Swift一定要在方法和属性前加dynamic,如果不是继承自NSObject的Swift类不能被动态替换
    • Swift替换类和方法要比OC在类/方法名之前添加工程名
    • 如果项目跑起来控制台输出没有找到文档就是网站上配置错了

    相关连接:
    JSPatch 基础用法
    JSPatch实现原理详解:让JS调用/替换任意OC方法

    相关文章

      网友评论

          本文标题:[JSPatch] 初尝JSPatch快速集成

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