1 problem
Android sends messages to js natively and can carry data
2 implementation principle
Android native can use RCTEventEmitter to register events, then you need to specify the name of the event here, and then listen to the name of the same event on the js side, and you can receive the message and get the data
Key code for Android registration
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(eventName, params);
The EventName here and the value of 'EventName' below need to be consistent
Monitoring on js
componentWillMount(){ //Listen for an event named EventName DeviceEventEmitter.addListener('EventName', function() { alert("Android send js msg success"); }); }
3 code implementation
Please refer to some code and class files of my previous blogs
React Native implementation js calls Android native code
js of React Native calls Android native to use Callback to pass the result to js
Based on the above article, I added a Test.java class. The file is as follows. Here is the registration
package com.pro_react; import android.content.Context; import android.provider.Settings; import android.support.annotation.Nullable; import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.WritableMap; import com.facebook.react.modules.core.DeviceEventManagerModule; public class Test { //Define context object public ReactContext myContext; public Test(ReactContext context) { this.myContext = context; } //Define functions to send events public void sendEventToUi(ReactContext reactContext, String eventName, @Nullable WritableMap params) { reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(eventName, params); } public void sendMsg() { //Start the thread in this method, delay for 1 second, and then send the event to the JavaScript side. new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } //Send an event named EventName WritableMap wm = Arguments.createMap(); sendEventToUi(myContext,"EventName", wm); } }).start(); } }
Then it is added in the MyToastModule.java file. When js clicks the text to trigger the showMyName function, we will send a message to js. The MyToastModule.java file is as follows
package com.pro_react; import android.content.Context; import android.util.Log; import android.widget.Toast; import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; /** * Created by chenyu on 9/15/18. */ public class MyToastModule extends ReactContextBaseJavaModule { public ReactContext mContext; public MyToastModule(ReactApplicationContext reactContext) { super(reactContext); mContext = reactContext; } /** * getName Method returns a string name, which is the module name in js * When we write js, we need to import this module. Here I use MyToast */ @Override public String getName() { return "MyToast"; } /** * This is the method called by js. You need to use the annotation @ react method. The return type must be void */ @ReactMethod public void show() { Toast.makeText(getReactApplicationContext(), "I am chenyu", Toast.LENGTH_SHORT).show(); } @ReactMethod(isBlockingSynchronousMethod = true) public String showMyName() { NotificationUtil util = NotificationUtil.getInstance(mContext); //util.showMessage(); //Send message to ui new Test(mContext).sendMsg(); return "chenyu1"; } }
The App.js file is modified as follows
/** * Sample React Native App * https://github.com/facebook/react-native * * @format * @flow */ import React, {Component} from 'react'; import {Platform, StyleSheet, Text, View, NativeModules, DeviceEventEmitter} from 'react-native'; const instructions = Platform.select({ ios: 'Press Cmd+R to reload,\n' + 'Cmd+D or shake for dev menu', android: 'Double tap R on your keyboard to reload,\n' + 'Shake or press menu button for dev menu', }); var myAndroidToast = NativeModules.MyToast; type Props = {}; export default class App extends Component<Props> { componentWillMount(){ //Listen for an event named EventName DeviceEventEmitter.addListener('EventName', function() { alert("Android send js msg success"); }); } constructor(props){ super(props); this.state={ myName:'chenzixuan', } } render() { return ( <View style={styles.container}> <Text onPress={()=> this._androidShowMsg()} style={styles.welcome}>Welcome to React Native!</Text> <Text style={styles.instructions}>To get started, edit App.js</Text> <Text style={styles.instructions}>{instructions}</Text> <Text style={styles.instructions}>{this.state.myName}</Text> </View> ); } _androidShowMsg = () => { var value = myAndroidToast.showMyName(); this.setState({myName:value}); }; } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', }, welcome: { fontSize: 20, textAlign: 'center', margin: 10, }, instructions: { textAlign: 'center', color: '#333333', marginBottom: 5, }, });
4 test results
App.js has been modified here, so you need to generate android.index.bundle file. Execute the command as follows
react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res
And then
react-native run-android
The effect is as follows
Click Welcome to React Native and the effect is as follows