React Native之Android原生通過(guò)DeviceEventEmitter發(fā)送消息給js

1 問(wèn)題

Android原生向js發(fā)消息,并且可以攜帶數(shù)據(jù)


2 實(shí)現(xiàn)原理

Android原生可以使用RCTEventEmitter來(lái)注冊(cè)事件,然后這里需要指定事件的名字,然后在js那端進(jìn)行監(jiān)聽(tīng)同樣事件的名字監(jiān)聽(tīng),就可以收到消息得到數(shù)據(jù)

Android注冊(cè)關(guān)鍵代碼

reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(eventName, params);

這里的eventName和下面的'EventName'的值需要保持一致.

js那端的監(jiān)聽(tīng)

       componentWillMount(){  
          //監(jiān)聽(tīng)事件名為EventName的事件
          DeviceEventEmitter.addListener('EventName', function() {  
              alert("Android send js msg success");  
          });                                
        }


3 代碼實(shí)現(xiàn)

可以先參考我前面幾篇博客的部分代碼和類(lèi)文件

React Native實(shí)現(xiàn)js調(diào)用安卓原生代碼

React Native之js調(diào)用Android原生使用Callback傳遞結(jié)果給js

還是基于上面的文章,然后我這邊多加了一個(gè)Test.java類(lèi),文件如下,這里主要是注冊(cè)

    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 {
     
        //定義上下文對(duì)象
        public ReactContext myContext;
     
        public Test(ReactContext context) {
            this.myContext = context;
        }
     
        //定義發(fā)送事件的函數(shù)
        public void sendEventToUi(ReactContext reactContext, String eventName, @Nullable WritableMap params) {
            reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(eventName, params);
        }
     
        public void sendMsg()
        {
            //在該方法中開(kāi)啟線程,并且延遲1秒,然后向JavaScript端發(fā)送事件。
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    //發(fā)送事件,事件名為EventName
                    WritableMap wm = Arguments.createMap();
                    sendEventToUi(myContext,"EventName", wm);
                }
            }).start();
        }
    }

然后在MyToastModule.java文件里面增加了,當(dāng)js點(diǎn)擊文本觸發(fā)showMyName函數(shù)的時(shí)候,我們這邊就向js發(fā)送消息,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方法返回一個(gè)字符串名字,就是js中的模塊名
         * 到時(shí)候我們寫(xiě)js的時(shí)候需要導(dǎo)入這個(gè)模塊,這里我用的是MyToast
         */
        @Override
        public String getName() {
            return "MyToast";
        }
     
        /**
         * 這是js調(diào)用的方法,需要使用注解@ReactMethod,返回類(lèi)型必須為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發(fā)送消息
            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(){  
          //監(jiān)聽(tīng)事件名為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 測(cè)試結(jié)果

這里修改了App.js,所以需要新生成android.index.bundle文件,執(zhí)行命令如下

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

然后再執(zhí)行

react-native run-android

效果如下

點(diǎn)擊Welcome to React Native效果如下

 



 










作者:chen.yu
深信服三年半工作經(jīng)驗(yàn),目前就職游戲廠商,希望能和大家交流和學(xué)習(xí),
微信公眾號(hào):編程入門(mén)到禿頭 或掃描下面二維碼
零基礎(chǔ)入門(mén)進(jìn)階人工智能(鏈接)