1 問題
Android原生向js發消息,并且可以攜帶資料
2 實作原理
Android原生可以使用RCTEventEmitter來注冊事件,然後這裡需要指定事件的名字,然後在js那端進行監聽同樣事件的名字監聽,就可以收到消息得到資料
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
ReactNative效果如下