一、相信使用RN 开发的同学们都会遇到这样一个问题,第三方没有支持相关的RN库,或者有一些方法在iOS上可以,但是并没有提供Android相关的方法,那么我们就只能考虑用原生去桥接第三方SDK或者自己实现相关的方法。
二、我们自己实现的方法该如何接入,在JS里面我们又是如何去调用呢?
首先自定义一个react package,我们可以叫它MyReactPackage
/**
* Created by jiawei.zhu on 2017/2/12.
*/
public class MyReactPackage implements ReactPackage {
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new UpdateJsBundle(reactContext));//添加需要实现功能的JavaModule类,可以添加多个类
return modules;
}
@Override
public List<Class<? extends JavaScriptModule>> createJSModules() {
return Collections.emptyList();
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
}
接着我们实现自定义的JavaModule类,在这里我需要实现下载热更新热bundle后重启APP.
1.继承ReactContextBaseJavaModule 类,添加功能方法restartApp
/**
* Created by jiawei.zhu on 2017/2/12.
*/
public class UpdateJsBundle extends ReactContextBaseJavaModule {
public static final String MODULENAME = "UpdateJsBundle";
private Context mContext;
public UpdateJsBundle(ReactApplicationContext reactContext) {
super(reactContext);
mContext = reactContext;
}
@Override
public String getName() {
return MODULENAME ;
}
/**
* 必须添加注解不然会报错
* 这个方法就是ReactNative将要调用的方法,会通过此类名字调用
*/
@ReactMethod
public void restartApp() {
Intent i = getReactApplicationContext().getPackageManager()
.getLaunchIntentForPackage(getReactApplicationContext().getPackageName());
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
mContext.startActivity(i);
}
}
然后像第三方的库一样把实现的自定义的MyReactPackage 加到MainApplication
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new WeChatPackage(),
new ImagePickerPackage(),
new RNFSPackage(),
new AlipayPackage(),
new RCTZipPackage(),
new RCTFileTransferPackage(),
new MyReactPackage()//自定义
);
}
最后我们在JS代码里面调用自定义的UpdateJsBundle 就可以实现自己需要的功能了
引入NativeModules
import {
Platform,
AsyncStorage,
NativeModules
} from 'react-native';
调用自定义JavaModule
async checkShouldUpdate(res){
let newSv = res.sv;
let that = this;
var sv = await AsyncStorage.getItem(this.svKey);
if (!sv) {
sv = '0';
}
console.log("newSv ,old sv",newSv,sv);
if (NumberUtil.compareVersionNum(newSv,sv)>0) {
console.log("进行加载新包 地址是 re.svurl",res.svurl);
let fileHeadPath = Platform.OS=='ios'?RNFS.LibraryDirectoryPath:RNFS.ExternalDirectoryPath;
let fileTialPath = '/tempjsbundle/'+newSv+'tempjsbundle.zip';
var downzippath = fileHeadPath + fileTialPath;
console.log("downzippath",downzippath);
// Platform.OS=='ios'?'/client/tempfolder/tempjsbundle.zip':'/sdcard/data/tempfolder/tempjsbundle.zip'
var fileTransfer = new FileTransfer();
var uri = encodeURI(res.svurl);
fileTransfer.onprogress = (progress) => console.log("1",progress.loaded+'/'+progress.total);
fileTransfer.download(
uri,
downzippath,
function(result) {
console.log(result);
var downJsBundlePath = fileHeadPath + '/downjsbundle/';
console.log("downJsBundlePath",downJsBundlePath);
Zip.unzip(downzippath, downJsBundlePath, (err)=>{
if (err) {
console.log("解压失败");
} else {
NativeModules.UpdateJsBundle.restartApp();//调用自定义JavaModule
console.log("解压成功,将zip删除");
let nowTime = (new Date()).valueOf();
that.saveCheckTime(nowTime);
that.saveSV(newSv);
console.log("保存newsv,time",newSv,nowTime);
RNFS.unlink(downzippath).then(() => {
// 通过解压得到的补丁文件生成最新版的jsBundle
});
}
});
},
function(error) {
console.log("下载失败");
console.log(error);
},
);
}else{
console.log("sv版本已经是最高")
}
}
总结:实现js调用原生模块有4个步奏
(1)自定义MyReactPackage继承ReactPackage ,并在createNativeModules方法内添加自己需要实现的类 modules.add(new UpdateJsBundle(reactContext));//添加需要实现功能的JavaModule类,可以添加多个类。
(2)实现自定义的UpdateJsBundle,继承ReactContextBaseJavaModule 实现功能方法restartApp该方法必须添加@ReactMethod注解。
(3)在MainApplication引入MyReactPackage
(4)JS通过NativeModules调用NativeModules.UpdateJsBundle.restartApp();