React Native之Android原生通过DeviceEventEmitter发送消息给js
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() {
@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效果如下
作者:chen.yu
深信服三年半工作经验,目前就职游戏厂商,希望能和大家交流和学习,
微信公众号:编程入门到秃头 或扫描下面二维码
零基础入门进阶人工智能(链接)