React Native之Android原生通過DeviceEventEmitter傳送訊息給js
阿新 • • 發佈:2018-12-11
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 程式碼實現
可以先參考我前面幾篇部落格的部分程式碼和類檔案
還是基於上面的文章,然後我這邊多加了一個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效果如下