1 问题
Android原生向js发消息,并且可以携带数据
2 实现原理
Android原生可以使用RCTEventEmitter来注册事件,然后这里需要指定事件的名字,然后在js那端进行监听同样事件的名字监听,就可以收到消息得到数据
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(eventName, params);
这里的eventName和下面的'EventName'的值需要保持一致.
js那端的监听
componentWillMount(){ //监听事件名为EventName的事件 DeviceEventEmitter.addListener('EventName', function() { alert("Android send js msg success"); }); }
3 代码实现
可以先参考我前面几篇博客的部分代码和类文件
React Native实现js调用安卓原生代码
React Native之js调用Android原生使用Callback传递结果给js
还是基于上面的文章,然后我这边多加了一个Test.java类,文件如下,这里主要是注册
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 { //定义上下文对象 public ReactContext myContext; public Test(ReactContext context) { this.myContext = context; } //定义发送事件的函数 public void sendEventToUi(ReactContext reactContext, String eventName, @Nullable WritableMap params) { reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(eventName, params); } public void sendMsg() { //在该方法中开启线程,并且延迟1秒,然后向JavaScript端发送事件。 new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } //发送事件,事件名为EventName WritableMap wm = Arguments.createMap(); sendEventToUi(myContext,"EventName", wm); } }).start(); } }
然后在MyToastModule.java文件里面增加了,当js点击文本触发showMyName函数的时候,我们这边就向js发送消息,MyToastModule.java文件如下
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方法返回一个字符串名字,就是js中的模块名 * 到时候我们写js的时候需要导入这个模块,这里我用的是MyToast */ @Override public String getName() { return "MyToast"; } /** * 这是js调用的方法,需要使用注解@ReactMethod,返回类型必须为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(); //向ui发送消息 new Test(mContext).sendMsg(); return "chenyu1"; } }
App.js文件修改如下
/** * 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(){ //监听事件名为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 测试结果
这里修改了App.js,所以需要新生成android.index.bundle文件,执行命令如下
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
然后再执行
react-native run-android
点击Welcome to React Native效果如下