ReactNative 与原生App通信(Android)
1:将项目相关文件夹拷贝到Android项目更目录下,如ASMobileInbox项目需要拷贝的文件:node_modules、js、res、App.js、index.js、package.json。
2:配置App:
AndroidManifest.xml文件:
<uses-sdk
android:minSdkVersion="15"
android:targetSdkVersion="25"
tools:overrideLibrary="com.facebook.react" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<application
android:name=".MainApplication"
…
App: build.gradle 与原生app对比,将ndk、configurations.all、dependencies、ask添加到对应模块。
android {
compileSdkVersion 25
defaultConfig {
applicationId "com.asm.test.rnapp"
minSdkVersion 15
targetSdkVersion 25
versionCode 1
versionName "1.0"
ndk {
abiFilters "armeabi-v7a", "x86"
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
configurations.all {
resolutionStrategy.force 'com.google.code.findbugs:jsr305:1.3.9'
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile("com.facebook.react:react-native:+", {
exclude group: 'com.android.support', module: 'recyclerview-v7'
exclude group: 'com.android.support', module: 'support-v4'
})
compile 'com.android.support:appcompat-v7:25.3.1'
compile 'com.android.support.constraint:constraint-layout:1.0.0-alpha7'
}
task copyDownloadableDepsToLibs(type: Copy) {
from configurations.compile
into 'libs'
}
工程的build.gradle: (添加不同的代码到对应模块中)
allprojects {
repositories {
google()
jcenter()
maven {
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
url "$rootDir/node_modules/react-native/android"
}
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
3:在RN项目中:android目录下中java文件copy到原生App的java包目录下。同时,其中RN的MainActivity文件放在你需要展现的Activity中,并需要将RN中MainActivity不同的方法copy到需要的Activity记B中,并且在B的getMainComponentName()方法的返回值和index.js文件的registerComponent(‘name’,()=>App)方法的name与App项目名称一致。同时,创建一个通信类,如下:
public class MainModule extends ReactContextBaseJavaModule {
private final String MODULE_NAME="mainModule";
private ReactContext mContext;
private String eventName="nativeCallRn";
public MainModule(ReactApplicationContext reactContext) {
super(reactContext);
mContext=reactContext;
}
@Override
public String getName() {
return MODULE_NAME;
}
/**
* Native调用RN
* @param msg
*/
public void nativeCallRn(String msg){
mContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit(eventName, msg);
}
/**
* DeviceEventEmitter方法传送参数
*/
@ReactMethod
public void sendMsgToRN() {
Log.e("---","sendMsgToRN");
nativeCallRn("hello");
}
/**
* CallBack 方法
* @param callback:处理方法
*/
@ReactMethod
public void rnCallNativeCallback(Callback callback){
JSONObject object=new JSONObject();
try {
object.put("session","null");
object.put("userBadge","80028939");
object.put("appId","A000025");
object.put("type","3");
object.put("appName","TestApp01");
object.put("imgUrl","null");
} catch (JSONException e) {
e.printStackTrace();
}
callback.invoke(object.toString());
}
/**
* 实现跳转界面
*/
@ReactMethod
public void rnCallbackNative(){
Intent intent=new Intent(mContext,TestActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent);
}
/**
* 调用数据传参
* @param callback
*/
@ReactMethod
public void rnCallbackIsflag(Callback callback){
callback.invoke("detail");
}
/**
* Promise 方式
* @param msg:传送参数
* @param promise:Promise对象
*/
@ReactMethod
public void rnCallNativeFromPromise(String msg, Promise promise) {
String result = "处理结果:" + msg;
Toast.makeText(mContext, "Result==="+result, Toast.LENGTH_SHORT).show();
JSONObject object=new JSONObject();
try {
object.put("session","null");
object.put("userBadge","80028939");
object.put("appId","A000025");
object.put("type","3");
} catch (JSONException e) {
e.printStackTrace();
}
// 2.回调RN,即将处理结果返回给RN
promise.resolve(object.toString());
}
}
以上方法可选其中一种,但需要与rn中的js引用的方法名和事件一致,否则调用不成功。。。
RN项目中调用代码(标记为蓝色的代码则为通信方法),其中的mainModule与app中通信类的返回Name值一致,如下:
/**
* callBack通信方式:获取信息
*/
callbackCommunication(){
NativeModules.mainModule.rnCallNativeCallback((result)=>{
// console.log(constants.logTag+"++++++: ",result);
//其中result来自App传过来的数据
let paramJson=MethodDao.stringToJson(result);
this.session=paramJson.session.toString();
this.userBadge=paramJson.userBadge.toString();
this.appId=paramJson.appId.toString();
this.type=paramJson.type.toString();
this.appName=paramJson.appName.toString();
this.imgUrl=paramJson.imgUrl.toString();
// console.log(constants.logTag+"++++++: ",this.session+', '+this.userBadge+', '+this.appId+', '+this.type+', '+this.imgUrl);
//获取数据请求方法 this.getDataSources(this.session,this.userBadge,this.appId,this.type,this.state.page);
});
}
4:如运行后有一下错误:
java.lang.RuntimeException: Unable to load script from assets 'index.android.bundle'. Make sure your bundle is packaged correctly or you're running a packager server.
则需做:若Android项目app/src/main目录下没有assets文件夹,先创建assets文件夹,接着在Android Studio的Terminal执行以下命令(执行命令的位置必须与node_modules处于同一级别下,即 处于Android项目的根目录下):
react-native bundle --platform android --dev false --entry-file index.js --bundle-output ./app/src/main/assets/index.android.bundle --assets-dest ./app/src/main/res/