RN怎么与native交互的呢?
下面我们通过一个简单的Demo来实现:RN页面调起Native页面,Native页面选择电话本数据,将数据回传给RN展示。
首先是 Native侧
1、MainActivity
package com.rnandroid01;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract;
import com.facebook.react.ReactActivity;
public class MainActivity extends ReactActivity {
/**
* Returns the name of the main component registered from JavaScript.
* This is used to schedule rendering of the component.
*/
@Override
protected String getMainComponentName() {
return "RNAndroid01";
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode!=200 || resultCode!=RESULT_OK) return;
Uri contactData = data.getData();
Cursor cursor = managedQuery(contactData, null, null, null, null);
cursor.moveToFirst();
String num = getContactPhone(cursor);
//下面的话 就是将num发送给rn侧 需要调用nativeModule对象里面的方法
MainApplication.getMyReactPackage().myNativeModule.sendMsgToRn(num);
}
//这个是Native代码,与RN其实没什么关系
private String getContactPhone(Cursor cursor) {
// TODO Auto-generated method stub
int phoneColumn = cursor
.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER);
int phoneNum = cursor.getInt(phoneColumn);
String result = "";
if (phoneNum > 0) {
// 获得联系人的ID号
int idColumn = cursor.getColumnIndex(ContactsContract.Contacts._ID);
String contactId = cursor.getString(idColumn);
// 获得联系人电话的cursor
Cursor phone = getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "="
+ contactId, null, null);
if (phone.moveToFirst()) {
for (; !phone.isAfterLast(); phone.moveToNext()) {
int index = phone
.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
int typeindex = phone
.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE);
int phone_type = phone.getInt(typeindex);
String phoneNumber = phone.getString(index);
result = phoneNumber;
}
if (!phone.isClosed()) {
phone.close();
}
}
}
return result;
}
}
package com.rnandroid01;
import android.app.Application;
import android.util.Log;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import java.util.Arrays;
import java.util.List;
public class MainApplication extends Application implements ReactApplication {
private static final MyReactPackage myReactPackage=new MyReactPackage();
public static MyReactPackage getMyReactPackage() {
return myReactPackage;
}
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
protected boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
myReactPackage
);
}
};
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
}
package com.rnandroid01;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.JavaScriptModule;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class MyReactPackage implements ReactPackage {
public MyNativeModule myNativeModule;
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
List<NativeModule> modules=new ArrayList<>();
myNativeModule=new MyNativeModule(reactContext);
modules.add(myNativeModule);
return modules;
}
@Override
public List<Class<? extends JavaScriptModule>> createJSModules() {
return Collections.emptyList();
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
}
package com.rnandroid01;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.widget.Toast;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.modules.core.DeviceEventManagerModule;
public class MyNativeModule extends ReactContextBaseJavaModule {
private ReactApplicationContext mContext;
public MyNativeModule(ReactApplicationContext reactContext) {
super(reactContext);
mContext = reactContext;
}
@Override
public String getName() {
//一定要有这个名字的 在rn代码里面是需要这个名字来调用该类的方法的
return "MyNativeModule";
}
//函数不能有返回值,因为被调用的原生代码是异步的,原生代码执行结束之后只能通过回调函数或者发送消息给rn那边
//有一个错误
@ReactMethod
public void rnCallNative(String msg) {
Toast.makeText(mContext, msg, Toast.LENGTH_SHORT).show();
// Intent intent = new Intent(mContext, MyActivity.class);
// intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//一定要加上这句 否则报错
// mContext.startActivity(intent);
Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
Bundle bundle = new Bundle();
mContext.startActivityForResult(intent,200,bundle);
}
public void sendMsgToRn(String msg){
//将消息msg发送给RN侧
mContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("AndroidToRNMessage",msg);
}
}
/**
* Sample React Native App
* https://github.com/facebook/react-native
* @flow
*/
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
NativeModules,
DeviceEventEmitter,
View
} from 'react-native';
class RNAndroid01 extends Component {
componentWillMount(){
DeviceEventEmitter.addListener('AndroidToRNMessage',this.handleAndroidMessage);
}
componentWillunMount(){
DeviceEventEmitter.remove('AndroidToRNMessage',this.handleAndroidMessage);
}
handleAndroidMessage=(msg)=>{
//RN端获得native端传递的数据
console.log(msg);
}
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}
onPress={this.CallAndroid}
>
Welcome to React Native!RN与Android的通信
</Text>
<Text style={styles.instructions}>
To get started, edit index.android.js
</Text>
<Text style={styles.instructions}>
Shake or press menu button for dev menu
</Text>
</View>
);
}
CallAndroid=()=>{
NativeModules.MyNativeModule.rnCallNative('rn调用原生模块的方法-成功啦');
}
}
重点使用了React Native的RCTDeviceEventEmitter,通过消息机制来实现。
好了,RN与native的交互还可以通过Promise和Callback回调方式实现,我们下篇文章再看。