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
深信服三年半工作经验,目前就职游戏厂商,希望能和大家交流和学习,
微信公众号:编程入门到秃头 或扫描下面二维码
零基础入门进阶人工智能(链接)