微软的CodePush热更新非常难用大家都知道,速度跟被墙了没什么区别。

另外一方面,我们不希望把代码放到别人的服务器。自己写接口更新总归感觉安全一点。

so,就来自己搞个React-Native APP的热更新管理工具吧。暂且命名为hotdog。

/**************************************************/

首先我们要弄清react-native启动的原理,是直接调用jslocation的jsbundle文件和assets资源文件。

由此,我们可以自己通过的服务器接口去判断版本,并下载最新的然后替换相应的文件,然后从这个文件调用启动APP。这就像之前的一些H5APP一样做版本的管理。

以iOS为例,我们需要分以下几步去搭建这个自己的RN升级插件:

一、设置默认jsbundle地址(比如document文件夹):

1.首先打包的时候把jsbundle和assets放入copy bundle resource,每次启动后,检测document文件夹是否存在,不存在则拷贝到document文件夹,然后给RN框架读取启动。

我们建立如下的bundle文件管理类:

MXBundleHelper.h

#import <Foundation/Foundation.h>

@interface MXBundleHelper : NSObject

+(NSURL *)getBundlePath;

@end

MXBundleHelper.m

#import "MXBundleHelper.h"
#import "RCTBundleURLProvider.h"
@implementation MXBundleHelper
+(NSURL *)getBundlePath{
#ifdef DEBUG
NSURL *jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];
return jsCodeLocation;
#else
//需要存放和读取的document路径
//jsbundle地址
NSString *jsCachePath = [NSString stringWithFormat:@"%@/\%@",NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[],@"main.jsbundle"];
//assets文件夹地址
NSString *assetsCachePath = [NSString stringWithFormat:@"%@/\%@",NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[],@"assets"]; //判断JSBundle是否存在
BOOL jsExist = [[NSFileManager defaultManager] fileExistsAtPath:jsCachePath];
//如果已存在
if(jsExist){
NSLog(@"js已存在: %@",jsCachePath);
//如果不存在
}else{
NSString *jsBundlePath = [[NSBundle mainBundle] pathForResource:@"main" ofType:@"jsbundle"];
[[NSFileManager defaultManager] copyItemAtPath:jsBundlePath toPath:jsCachePath error:nil];
NSLog(@"js已拷贝至Document: %@",jsCachePath);
} //判断assets是否存在
BOOL assetsExist = [[NSFileManager defaultManager] fileExistsAtPath:assetsCachePath];
//如果已存在
if(assetsExist){
NSLog(@"assets已存在: %@",assetsCachePath);
//如果不存在
}else{
NSString *assetsBundlePath = [[NSBundle mainBundle] pathForResource:@"assets" ofType:nil];
[[NSFileManager defaultManager] copyItemAtPath:assetsBundlePath toPath:assetsCachePath error:nil];
NSLog(@"assets已拷贝至Document: %@",assetsCachePath);
}
return [NSURL URLWithString:jsCachePath];
#endif
}

二、做升级检测,有更新则下载,然后对本地文件进行替换:

假如我们不立即做更新,可以更新后替换,然后不会影响本次APP的使用,下次使用就会默认是最新的了。

如果立即更新的话,需要使用到RCTBridge类里的reload函数进行重启。

这里通过NSURLSession进行下载,然后zip解压缩等方法来实现文件的替换。

MXUpdateHelper.h

#import <Foundation/Foundation.h>
typedef void(^FinishBlock) (NSInteger status,id data); @interface MXUpdateHelper : NSObject
+(void)checkUpdate:(FinishBlock)finish;
@end

MXUpdateHelper.m

#import "MXUpdateHelper.h"

@implementation MXUpdateHelper
+(void)checkUpdate:(FinishBlock)finish{
NSString *url = @"http://www.xxx.com/xxxxxxx";
NSMutableURLRequest *newRequest = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:url]];
[newRequest setHTTPMethod:@"GET"];
[NSURLConnection sendAsynchronousRequest:newRequest queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * response, NSData * data, NSError * connectionError) {
if(connectionError == nil){
//请求自己服务器的API,判断当前的JS版本是否最新
/*
{
"version":"1.0.5",
"fileUrl":"http://www.xxxx.com/xxx.zip",
"message":"有新版本,请更新到我们最新的版本",
"forceUpdate:"NO"
}
*/
//假如需要更新
NSString *curVersion = @"1.0.0";
NSString *newVersion = @"2.0.0";
//一般情况下不一样,就是旧版本了
if(![curVersion isEqualToString:newVersion]){
finish(,data);
}else{
finish(,nil);
}
}
}];
}
@end

三、APPdelegate中的定制,弹框,直接强制更新等

如果需要强制刷新reload,我们新建RCTView的方式也需要稍微改下,通过新建一个RCTBridge的对象。

因为RCTBridge中有reload的接口可以使用。

#import "AppDelegate.h"
#import "RCTBundleURLProvider.h"
#import "RCTRootView.h"
#import "MXBundleHelper.h"
#import "MXUpdateHelper.h"
#import "MXFileHelper.h"
#import "SSZipArchive.h"
@interface AppDelegate()<UIAlertViewDelegate>
@property (nonatomic,strong) RCTBridge *bridge;
@property (nonatomic,strong) NSDictionary *versionDic;
@end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{ NSURL *jsCodeLocation;
jsCodeLocation = [MXBundleHelper getBundlePath]; _bridge = [[RCTBridge alloc] initWithBundleURL:jsCodeLocation
moduleProvider:nil
launchOptions:launchOptions];
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:_bridge moduleName:@"MXVersionManager" initialProperties:nil]; rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [UIViewController new];
rootViewController.view = rootView;
self.window.rootViewController = rootViewController; [self.window makeKeyAndVisible]; __weak AppDelegate *weakself = self;
//更新检测
[MXUpdateHelper checkUpdate:^(NSInteger status, id data) {
if(status == ){
weakself.versionDic = data;
/*
这里具体关乎用户体验的方式就多种多样了,比如自动立即更新,弹框立即更新,自动下载下次打开再更新等。
*/
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:data[@"message"] delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"现在更新", nil];
[alert show];
//进行下载,并更新
//下载完,覆盖JS和assets,并reload界面
// [weakself.bridge reload];
}
}];
return YES;
} - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if(buttonIndex == ){
//更新
[[MXFileHelper shared] downloadFileWithURLString:_versionDic[@"fileurl"] finish:^(NSInteger status, id data) {
if(status == ){
NSLog(@"下载完成");
NSError *error;
NSString *filePath = (NSString *)data;
NSString *desPath = [NSString stringWithFormat:@"%@",NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[]];
[SSZipArchive unzipFileAtPath:filePath toDestination:desPath overwrite:YES password:nil error:&error];
if(!error){
NSLog(@"解压成功");
[_bridge reload];
}else{
NSLog(@"解压失败");
}
}
}];
}
}

流程简单,通过接口请求版本,然后下载到document去访问。 其中需要做版本缓存,Zip的解压缩,以及文件拷贝等。

运行iOS工程可以看到效果。 初始为1.0.0版本,然后更新后升级到1.0.1版本。

demo: https://github.com/rayshen/MXHotdog

ReactNative 告别CodePush,自建热更新版本升级环境的更多相关文章

  1. ReactNative 使用微软的CodePush进行热更新,继续填坑

    1.别被开发环境骗了 在我们开发react native的时候,一键运行工程,js改了,只要cmd+R就可以刷新了.然后会轻易以为真正app上线的时候也是一样,只要app一打开就是最新的. 其实!这是 ...

  2. 在React Native中集成热更新

    最近,在项目DYTT集成了热更新,简单来说,就是不用重新下载安装包即可达到更新应用的目的,也不算教程吧,这里记录一下. 1.热更新方案 目前网上大概有两个比较广泛的方式,分别是 react-nativ ...

  3. react-native热更新之CodePush详细介绍及使用方法

    react-native热更新之CodePush详细介绍及使用方法 2018年03月04日 17:03:21 clf_programing 阅读数:7979 标签: react native热更新co ...

  4. React Native之code-push的热更新(ios android)

    React Native之code-push的热更新(ios android) React Native支持大家用React Native技术开发APP,并打包生成一个APP.在动态更新方面React ...

  5. CodePush热更新组件详细接入教程

    CodePush热更新组件详细接入教程 什么是CodePush CodePush是一个微软开发的云服务器.通过它,开发者可以直接在用户的设备上部署手机应用更新.CodePush相当于一个中心仓库,开发 ...

  6. 深度使用react-native的热更新能力,必须知道的一个shell命令

    开篇之前,先讲一个自己开发中的一个小插曲: 今天周日,iOS版 App 周一提交,周三审核通过上架,很给力.不过,中午11:30的时候,运营就反应某个页面有一个很明显的问题,页面没法拉到底部,部分信息 ...

  7. ReactNative学习笔记(四)热更新和增量更新

    概括 关于RN的热更新,网上有很多现成方案,但是一般都依赖第三方服务,我所希望的是能够自己管控所有一切,所以只能自己折腾. 热更新的思路 热更新一般都是更新JS和图片,也就是在不重新安装apk的情况下 ...

  8. react-native热更新从零到成功中的各种坑

    https://github.com/reactnativecn/react-native-pushy/blob/master/docs/guide.md Android NDK暂时没有安装 在你的项 ...

  9. 用CodePush在React Native App中做热更新

    最近在学React Native,学到了CodePush热更新. 老师讲了两种实现的方法,现将其记录一下. 相比较原生开发,使用React Native开发App不仅能节约开发成本,还能做原生开发不能 ...

随机推荐

  1. Atitit.可视化与报表原理与概论

    Atitit.可视化与报表原理与概论 1.  信息可视化1 2. Gui可视化1 3. 报表系统(三大图表,金字塔,组织结构图等)1 4. <可视化数据>目录3 5. 可视化的具体实现(c ...

  2. 【原】Bootstrap+Knockout.JS+ASP.Net MVC3+PetaPOCO实现CRUD操作

    1.需求: 1.1)页面要美观大气 1.2)前端代码要简洁清晰,要用MVC或是MVVM框架 1.3)服务端要用MVC框架,要Rest风格 1.4)数据访问要用ORM 2.效果: 2.1)列表 2.2) ...

  3. 【代码笔记】iOS-自定义开关

    一,效果图. 二,工程图. 三,代码. RootViewController.h #import <UIKit/UIKit.h> #import "ToggleView.h&qu ...

  4. Java 性能分析工具 , 第 2 部分:Java 内置监控工具

    引言 本文为 Java 性能分析工具系列文章第二篇,第一篇:操作系统工具.在本文中将介绍如何使用 Java 内置监控工具更加深入的了解 Java 应用程序和 JVM 本身.在 JDK 中有许多内置的工 ...

  5. docker通过iptables修改或新增镜像映射端口

    443 8088 22 端口是初始映射端口 [root@SERVER ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAM ...

  6. hibernate注解CascadeType

    http://blog.csdn.net/strong8808/article/details/6318994(参考) CascadeType.REFRESH:级联刷新,当多个用户同时作操作一个实体, ...

  7. sqoop:Failed to download file from http://hdp01:8080/resources//oracle-jdbc-driver.jar due to HTTP error: HTTP Error 404: Not Found

    环境:ambari2.3,centos7,sqoop1.4.6 问题描述:通过ambari安装了sqoop,又添加了oracle驱动配置,如下: 保存配置后,重启sqoop报错:http://hdp0 ...

  8. problems during rovio build

    1. rovio的readme中使用的是catkin build, ROS tutorial中用的是catkin_make. 关于build与make的区别: build重新编译所有文件:make默认 ...

  9. win10打开IL DASM步骤:

  10. centos7的网络设置

    必备知识:linux下对文件的编辑操作 首先给出的是vi的基础  后面会有详细的远程连接Centos的方法 vi的基本概念 基本上vi可分为三种操作状态,分别是命令模式(Command mode).插 ...