1 问题
Android原生向js发消息,并且可以携带数据
2 实现原理
Android原生可以使用RCTEventEmitter来注册事件,然后这里需要指定事件的名字,然后在js那端进行监听同样事件的名字监听,就可以收到消息得到数据
Android注册关键代码
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() {@Overridepublic void run() {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}//发送事件,事件名为EventNameWritableMap 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*/@Overridepublic String getName() {return "MyToast";}/*** 这是js调用的方法,需要使用注解@ReactMethod,返回类型必须为void*/@ReactMethodpublic 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效果如下