ReactNative 告别CodePush,自建热更新版本升级环境
微软的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,自建热更新版本升级环境的更多相关文章
- ReactNative 使用微软的CodePush进行热更新,继续填坑
1.别被开发环境骗了 在我们开发react native的时候,一键运行工程,js改了,只要cmd+R就可以刷新了.然后会轻易以为真正app上线的时候也是一样,只要app一打开就是最新的. 其实!这是 ...
- 在React Native中集成热更新
最近,在项目DYTT集成了热更新,简单来说,就是不用重新下载安装包即可达到更新应用的目的,也不算教程吧,这里记录一下. 1.热更新方案 目前网上大概有两个比较广泛的方式,分别是 react-nativ ...
- react-native热更新之CodePush详细介绍及使用方法
react-native热更新之CodePush详细介绍及使用方法 2018年03月04日 17:03:21 clf_programing 阅读数:7979 标签: react native热更新co ...
- React Native之code-push的热更新(ios android)
React Native之code-push的热更新(ios android) React Native支持大家用React Native技术开发APP,并打包生成一个APP.在动态更新方面React ...
- CodePush热更新组件详细接入教程
CodePush热更新组件详细接入教程 什么是CodePush CodePush是一个微软开发的云服务器.通过它,开发者可以直接在用户的设备上部署手机应用更新.CodePush相当于一个中心仓库,开发 ...
- 深度使用react-native的热更新能力,必须知道的一个shell命令
开篇之前,先讲一个自己开发中的一个小插曲: 今天周日,iOS版 App 周一提交,周三审核通过上架,很给力.不过,中午11:30的时候,运营就反应某个页面有一个很明显的问题,页面没法拉到底部,部分信息 ...
- ReactNative学习笔记(四)热更新和增量更新
概括 关于RN的热更新,网上有很多现成方案,但是一般都依赖第三方服务,我所希望的是能够自己管控所有一切,所以只能自己折腾. 热更新的思路 热更新一般都是更新JS和图片,也就是在不重新安装apk的情况下 ...
- react-native热更新从零到成功中的各种坑
https://github.com/reactnativecn/react-native-pushy/blob/master/docs/guide.md Android NDK暂时没有安装 在你的项 ...
- 用CodePush在React Native App中做热更新
最近在学React Native,学到了CodePush热更新. 老师讲了两种实现的方法,现将其记录一下. 相比较原生开发,使用React Native开发App不仅能节约开发成本,还能做原生开发不能 ...
随机推荐
- jQuery获取短信验证码+倒计时实现
jQuery 短信验证码倒计时 <script type="text/javascript" charset="utf-8"> $(function ...
- 八皇后算法的另一种实现(c#版本)
八皇后: 八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例.该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于 ...
- 日期关联取最近日期的SQL
SQL怎么关联,如下图A表用日期加产品编号关联B表的时候,如果日期不存在,则取之前最近一个日期的值,比如A表2012-07-31 关联B表,B表没有对应日期的,就取2012-07-30的 A表 ...
- SDK接入(1)之Android Facebook SDK接入
SDK接入(1)之Android Facebook SDK接入 由于游戏已上线,且处于维护阶段,所以有空写写各种SDK接入过程和遇到的问题,也当作一种工作总结.SDK接入主流分为这么几类,登录.支付. ...
- ASP.NET MVC的客户端验证:jQuery验证在Model验证中的实现
在简单了解了Unobtrusive JavaScript形式的验证在jQuery中的编程方式之后,我们来介绍ASP.NET MVC是如何利用它实现客户端验证的.服务端验证最终实现在相应的ModelVa ...
- SQL优化技术分析-2:SQL书写的影响
1.同一功能同一性能不同写法SQL的影响. 如一个SQL在A程序员写的为 Select * from zl_yhjbqk B程序员写的为 Select * from dlyx.zl_yhjbqk(带表 ...
- GreenPlum高效去除表重复数据
1.针对PostgreSQL数据库表的去重复方法基本有三种,这是在网上查找的方法,在附录1给出.但是这些方法对GreenPlum来说都不管用. 2.数据表分布在不同的节点上,每个节点的ctid是唯一的 ...
- DependencyResolver.Current
描述: 获取依赖关系解析程序的实现. 命名空间: System.Web.Mvc 程序集: System.Web.Mvc(在 System.Web.Mvc.dll 中) 用例: IRecLockServ ...
- python注释、脚本参数、字节码
python注释.脚本参数.字节码 --道心 python安装 1.下载安装包 https://www.python.org/downloads/ 2.安装 默认安装路径:C:\python27 3. ...
- AD域撤销域用户管理员权限方案
一.简介 公司大部分主机加入域已有一段时间了,由于某软件没管理员权限不能执行,所以管理员权限一直没撤销,不能完全实现域的管理效果.但起码实现了域用户脱离不了域的控制:http://www.cnblog ...