1, Why RN and native intermodulation?
RN will not complete things, such as opening a local camera, native interface. Dealing with hardware, then they die.
2, the first to use Android studio open android directory under ReactNative project;
we look at this project: it has two classes, MainActivity and MainApplication; in app.gradle file, dependencies (dependent), you will find that it has a react-native dependencies.
3, js call the java, is the first call js c, c calling java.
4, js call java process
to create ToastExampleMoudle
package com.nativeapp;
import android.widget.Toast;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nullable;
//
public class ToastExampleMoudle extends ReactContextBaseJavaModule {
private static final String MESSAGE = "MESSAGE";
public ToastExampleMoudle(ReactApplicationContext reactContext) {
super(reactContext);
}
//通过js去弹出一个原生的吐丝
@ReactMethod//要想这个方法暴露给js必须增加这个注解
public void show(int duration){
Toast.makeText(getReactApplicationContext(), "dongnao:" + duration, Toast.LENGTH_SHORT).show();
}
@Override
public String getName() {
return "ToastForAndroid";
}
@Override
public boolean canOverrideExistingModule() {
return true;
}
}
Creating ExampleReactNativePackage class
package com.nativeapp;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
//注册模块,注册到c
public class ExampleReactNativePackage implements ReactPackage {
//完成注入,需要被js调用java方法
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
//NativeModule添加到这个集合里,React Native通过这个方法知道当前有多少个需要给js调用的对象
List<NativeModule> modules = new ArrayList<>();
modules.add(new ToastExampleMoudle(reactContext));
return modules;
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
//注意这里不能写return null;
return Collections.emptyList();
}
}
This is MainActivity
package com.nativeapp;
import com.facebook.react.ReactActivity;
public class MainActivity extends ReactActivity {
/**
* Returns the name of the main component registered from JavaScript.
* This is used to schedule rendering of the component.
*/
//这里的nativeapp与index.js中的appName名字一样
//AppRegistry.registerComponent(appName, () => App);
@Override
protected String getMainComponentName() {
return "nativeapp";
}
}
Modify MainApplication
package com.nativeapp;
import android.app.Application;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import com.facebook.soloader.SoLoader;
import java.util.Arrays;
import java.util.List;
//注册java的模块,提前应用到缓存中心
public class MainApplication extends Application implements ReactApplication {
// reactNative主机
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
//是否是开发者
return BuildConfig.DEBUG;
}
@Override
protected List<ReactPackage> getPackages() {
//返回的是一个集合
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
//添加我们定义的ReactPackage
new ExampleReactNativePackage()
);
}
@Override
protected String getJSMainModuleName() {
//指向了程序的入口,index就是rn的主界面
return "index";
}
};
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
@Override
public void onCreate() {
super.onCreate();
SoLoader.init(this, /* native exopackage */ false);
}
}
Look App.js file
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* @format
* @flow
* @lint-ignore-every XPLATJSCOPYRIGHT1
*/
import React, {Component} from 'react';
//这里的ToastAndroid,是ToastExampleMoudle类中方法
// @Override
// public String getName() {
// return "ToastForAndroid";
// }
// 返回的名字。
import {
Platform,
StyleSheet,
ToastAndroid,
DeviceEventEmitter,
Text,
TouchableOpacity,
View,
NativeModules
} from 'react-native';
export default class App extends Component<Props> {
_onPressButton() {
/*调用ToastExampleMoudle类这个方法
* @ReactMethod
* public void show(int duration){
* Toast.makeText(getReactApplicationContext(), "dongnao:" + duration, Toast.LENGTH_SHORT).show();
* }
*/
// NativeModules.ToastForAndroid就表示调用ToastExampleMoudle类。
NativeModules.ToastForAndroid.show(1000);
}
render() {
return (
<View style={styles.container}>
//this._onPressButton.bind(this),调用_onPressButton(),注意这里是es6写法
<TouchableOpacity onPress={this._onPressButton.bind(this)}>
<Text style={styles.hello}>点击了</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
hello: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
We run the project, click on the word "hit", will pop up spinning
5,
ToastExampleMoudle type which add the following code
//1,具有回调参数的
//2,callback是ReactNative里面的一个接口。这个接口只有一个方法。
@ReactMethod
public void testAndroidCallBack(String msg, Callback callback) {
Toast.makeText(getReactApplicationContext(),msg,Toast.LENGTH_LONG).show();
//invoke方法的参数是一个可变参数
callback.invoke("david");
}
Modify app.js class
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* @format
* @flow
* @lint-ignore-every XPLATJSCOPYRIGHT1
*/
import React, {Component} from 'react';
//这里的ToastAndroid,是ToastExampleMoudle类中方法
// @Override
// public String getName() {
// return "ToastForAndroid";
// }
// 返回的名字。
import {
Platform,
StyleSheet,
ToastAndroid,
DeviceEventEmitter,
Text,
TouchableOpacity,
View,
NativeModules
} from 'react-native';
export default class App extends Component<Props> {
constructor(props) {
super(props);
this.state = {
text: "river",
text2: "默认",
}
}
_onPressButton2() {
NativeModules.ToastForAndroid.testAndroidCallBack("hello David", (result) => {
this.setState({
text: result
})
});
}
render() {
return (
<View style={styles.container}>
<TouchableOpacity onPress={this._onPressButton2.bind(this)}>
<Text style={styles.hello}>{this.state.text}</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
hello: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
Run the project, screen text appears river, river click on the text, the text becomes a river david; while spinning pop
"the Hello David"
6,
NA callback method to pass parameters through the promise realized.
Add method in the ToastExampleMoudle
//最后一个参数是promise
@ReactMethod
public void textAndroidPromiseMethod(String msg, Promise promise){
Toast.makeText(getReactApplicationContext(),msg,Toast.LENGTH_SHORT).show();
String result = "david";
//resolve代表正常运行,会走下面的then方法,如果是reject,则会走catch();
promise.resolve(result);
}
app.js file modification
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* @format
* @flow
* @lint-ignore-every XPLATJSCOPYRIGHT1
*/
import React, {Component} from 'react';
//这里的ToastAndroid,是ToastExampleMoudle类中方法
// @Override
// public String getName() {
// return "ToastForAndroid";
// }
// 返回的名字。
import {
Platform,
StyleSheet,
ToastAndroid,
DeviceEventEmitter,
Text,
TouchableOpacity,
View,
NativeModules
} from 'react-native';
export default class App extends Component<Props> {
constructor(props) {
super(props);
this.state = {
text: "river",
text2: "默认",
}
}
_onPressButton3() {
NativeModules.ToastForAndroid.textAndroidPromiseMethod("hello David").then((result) => {
this.setState({
text2: result
})
})
}
render() {
return (
<View style={styles.container}>
<TouchableOpacity onPress={this._onPressButton3.bind(this)}>
<Text style={styles.hello}>{this.state.text2}</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
hello: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
Operating results, the screen appears "default" word, click the word becomes the default david, while the pop-up spinning "hello david"
7, to pass an object js. We do not use callback, nor promise, another way.
Should do the following
js as an observer to be, want to inform the viewer, such as js life cycle, I would like to inform java, life cycle to what extent. There are a java method, but this method is not now call react when a page loads, I notice java call this method
we add in the code in ToastExampleMoudle
private static final String MESSAGE = "MESSAGE";
@Nullable
@Override
public Map<String, Object> getConstants() {
//让js那边能够使用这些常量
Map<String,Object> constants = new HashMap<>();
constants.put(MESSAGE,"动脑 常量");
return constants;
}
@ReactMethod
public void onScaning() {
WritableMap params = Arguments.createMap();
params.putString("key","mydata");
//通过java的方式发送一个对象事件,java通知js
getReactApplicationContext().getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit("EventName", params);
}
Look App.js file
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* @format
* @flow
* @lint-ignore-every XPLATJSCOPYRIGHT1
*/
import React, {Component} from 'react';
//这里的ToastAndroid,是ToastExampleMoudle类中方法
// @Override
// public String getName() {
// return "ToastForAndroid";
// }
// 返回的名字。
import {
Platform,
StyleSheet,
ToastAndroid,
DeviceEventEmitter,
Text,
TouchableOpacity,
View,
NativeModules
} from 'react-native';
export default class App extends Component<Props> {
constructor(props) {
super(props);
this.state = {
text: "river",
text2: "默认",
}
}
componentDidMount(): void {
//1,观察者对象 监听java 调用js
//2,js去监听java
//3.msg为我接收的数据
DeviceEventEmitter.addListener("EventName", function (msg) {
//获取到类里面的成员变量:
let rest = NativeModules.ToastForAndroid.MESSAGE;
//这个ToastAndroid是ReactNative自己带的。
ToastAndroid.show("DeviceEventEmitter收到消息:" + "\n" + rest, ToastAndroid.SHORT)
})
}
//js作为一个被观察者,想去通知观察者,
// 比如js有生命周期,我想通知java,生命周期到了一个什么程度。
//java里面有一方法,但这个方法并不是现在调用,当react某个页面
//加载的时候,我在通知java这个方法进行调用
_onPressButton4() {
NativeModules.ToastForAndroid.onScaning();
}
render() {
return (
<View style={styles.container}>
<TouchableOpacity onPress={this._onPressButton4.bind(this)}>
<Text style={styles.hello}>{this.state.text2}</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
hello: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
We click on the text, triggering _onPressButton4 method, then onScaning android method of triggers; call onScanning method when executing the following code generates an object
WritableMap params = Arguments.createMap(); params.putString("key","mydata");
We then getReactApplicationContext().getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) .emit("EventName", params);
called EventName event sends a name,
the final operating results: We run the project "default" text appears on the screen, click the "default" pop-up: "DeviceEventEmitter receive the message: mental and physical constants"
8, I put the complete code affixed:
package com.nativeapp;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
//注册模块,注册到c
public class ExampleReactNativePackage implements ReactPackage {
//完成注入,需要被js调用java方法
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
//NativeModule添加到这个集合里,React Native通过这个方法知道当前有多少个需要给js调用的对象
List<NativeModule> modules = new ArrayList<>();
modules.add(new ToastExampleMoudle(reactContext));
return modules;
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
//注意这里不能写return null;
return Collections.emptyList();
}
}
package com.nativeapp;
import com.facebook.react.ReactActivity;
public class MainActivity extends ReactActivity {
/**
* Returns the name of the main component registered from JavaScript.
* This is used to schedule rendering of the component.
*/
@Override
protected String getMainComponentName() {
return "nativeapp";
}
}
package com.nativeapp;
import android.widget.Toast;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nullable;
//
public class ToastExampleMoudle extends ReactContextBaseJavaModule {
private static final String MESSAGE = "MESSAGE";
public ToastExampleMoudle(ReactApplicationContext reactContext) {
super(reactContext);
}
@Nullable
@Override
public Map<String, Object> getConstants() {
//让js那边能够使用这些常量
Map<String,Object> constants = new HashMap<>();
constants.put(MESSAGE,"动脑 常量");
return constants;
}
//通过js去弹出一个原生的吐丝
@ReactMethod//要想这个方法暴露给js必须增加这个注解
public void show(int duration){
Toast.makeText(getReactApplicationContext(), "dongnao:" + duration, Toast.LENGTH_SHORT).show();
}
//1,具有回调参数的
//2,callback是ReactNative里面的一个接口。这个接口只有一个方法。
@ReactMethod
public void testAndroidCallBack(String msg, Callback callback) {
Toast.makeText(getReactApplicationContext(),msg,Toast.LENGTH_LONG).show();
//invoke方法的参数是一个可变参数
callback.invoke("david");
}
//最后一个参数是promise
@ReactMethod
public void textAndroidPromiseMethod(String msg, Promise promise){
Toast.makeText(getReactApplicationContext(),msg,Toast.LENGTH_SHORT).show();
String result = "david";
//resolve代表正常运行,会走下面的then方法,如果是reject,则会走catch();
promise.resolve(result);
}
@ReactMethod
public void onScaning() {
WritableMap params = Arguments.createMap();
params.putString("key","mydata");
//通过java的方式发送一个对象事件,java通知js
getReactApplicationContext().getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit("EventName", params);
}
@Override
public String getName() {
return "ToastForAndroid";
}
@Override
public boolean canOverrideExistingModule() {
return true;
}
}
package com.nativeapp;
import android.app.Application;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import com.facebook.soloader.SoLoader;
import java.util.Arrays;
import java.util.List;
//注册java的模块,提前应用到缓存中心
public class MainApplication extends Application implements ReactApplication {
// reactNative主机
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
//是否是开发者
return BuildConfig.DEBUG;
}
@Override
protected List<ReactPackage> getPackages() {
//返回的是一个集合
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
//添加我们定义的ReactPackage
new ExampleReactNativePackage()
);
}
@Override
protected String getJSMainModuleName() {
//指向了程序的入口,index就是rn的主界面
return "index";
}
};
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
@Override
public void onCreate() {
super.onCreate();
SoLoader.init(this, /* native exopackage */ false);
}
}
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* @format
* @flow
* @lint-ignore-every XPLATJSCOPYRIGHT1
*/
import React, {Component} from 'react';
//这里的ToastAndroid,是ToastExampleMoudle类中方法
// @Override
// public String getName() {
// return "ToastForAndroid";
// }
// 返回的名字。
import {
Platform,
StyleSheet,
ToastAndroid,
DeviceEventEmitter,
Text,
TouchableOpacity,
View,
NativeModules
} from 'react-native';
export default class App extends Component<Props> {
constructor(props) {
super(props);
this.state = {
text: "river",
text2: "默认",
}
}
componentDidMount(): void {
//1,观察者对象 监听java 调用js
//2,js去监听java
//3.msg为我接收的数据
DeviceEventEmitter.addListener("EventName", function (msg) {
//获取到类里面的成员变量:
let rest = NativeModules.ToastForAndroid.MESSAGE;
//这个ToastAndroid是ReactNative自己带的。
ToastAndroid.show("DeviceEventEmitter收到消息:" + "\n" + rest, ToastAndroid.SHORT)
})
}
_onPressButton() {
/*调用ToastExampleMoudle类这个方法
* @ReactMethod
* public void show(int duration){
* Toast.makeText(getReactApplicationContext(), "dongnao:" + duration, Toast.LENGTH_SHORT).show();
* }
*/
NativeModules.ToastForAndroid.show(1000);
}
_onPressButton2() {
NativeModules.ToastForAndroid.testAndroidCallBack("hello David", (result) => {
this.setState({
text: result
})
});
}
_onPressButton3() {
NativeModules.ToastForAndroid.textAndroidPromiseMethod("hello David").then((result) => {
this.setState({
text2: result
})
})
}
//js作为一个被观察者,想去通知观察者,
// 比如js有生命周期,我想通知java,生命周期到了一个什么程度。
//java里面有一方法,但这个方法并不是现在调用,当react某个页面
//加载的时候,我在通知java这个方法进行调用
_onPressButton4() {
NativeModules.ToastForAndroid.onScaning();
}
render() {
return (
<View style={styles.container}>
//this._onPressButton.bind(this),调用_onPressButton(),注意这里是es6写法
<TouchableOpacity onPress={this._onPressButton.bind(this)}>
<Text style={styles.hello}>点击了</Text>
</TouchableOpacity>
<TouchableOpacity onPress={this._onPressButton2.bind(this)}>
<Text style={styles.hello}>{this.state.text}</Text>
</TouchableOpacity>
<TouchableOpacity onPress={this._onPressButton3.bind(this)}>
<Text style={styles.hello}>{this.state.text2}</Text>
</TouchableOpacity>
<TouchableOpacity onPress={this._onPressButton4.bind(this)}>
<Text style={styles.hello}>{this.state.text2}</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
hello: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});