网站开发成本核算,写网页的素材图片, 百度一下,大学生毕业设计课题做网站微软的CodePush热更新非常难用大家都知道#xff0c;速度跟被墙了没什么区别。 另外一方面#xff0c;我们不希望把代码放到别人的服务器。自己写接口更新总归感觉安全一点。 so#xff0c;就来自己搞个React-Native APP的热更新管理工具吧。暂且命名为hotdog。 /**********…微软的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.hinterface MXBundleHelper : NSObject(NSURL *)getBundlePath;end MXBundleHelper.m #import MXBundleHelper.h
#import RCTBundleURLProvider.h
implementation MXBundleHelper
(NSURL *)getBundlePath{
#ifdef DEBUGNSURL *jsCodeLocation [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:index.ios fallbackResource:nil];return jsCodeLocation;
#else//需要存放和读取的document路径//jsbundle地址NSString *jsCachePath [NSString stringWithFormat:%/\%,NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0],main.jsbundle];//assets文件夹地址NSString *assetsCachePath [NSString stringWithFormat:%/\%,NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0],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.himplementation 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(1,data);}else{finish(0,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;
endimplementation AppDelegate- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{NSURL *jsCodeLocation;jsCodeLocation [MXBundleHelper getBundlePath];_bridge [[RCTBridge alloc] initWithBundleURL:jsCodeLocationmoduleProvider:nillaunchOptions: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:1];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 1){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 1){//更新[[MXFileHelper shared] downloadFileWithURLString:_versionDic[fileurl] finish:^(NSInteger status, id data) {if(status 1){NSLog(下载完成);NSError *error;NSString *filePath (NSString *)data;NSString *desPath [NSString stringWithFormat:%,NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0]];[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 转载于:https://www.cnblogs.com/rayshen/p/5737293.html