[JSPatch] 初尝JSPatch快速集成

2017-04-22  本文已影响487人  任尔东西南北疯

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

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


<h3>HotFix概述</h3>

iOS中的HotFix方案总结详解

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


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。

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

好,所以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 **公钥文件,因为只是测试,所以勾选开发预览选项,

发布布丁

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


布丁详情

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

success

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

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

可坑能踩的坑


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

上一篇下一篇

猜你喜欢

热点阅读