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效果如下

(0)

相关推荐