React Native ReactNative学习记录ReactNative

06 ReactNative和Android原生的交互

2018-03-30  本文已影响27人  与之书

从RN向Android端发送消息

public class RNTest extends ReactContextBaseJavaModule {

    private Context reactContext;

    public RNTest(ReactApplicationContext reactContext) {
        super(reactContext);
        this.reactContext= reactContext;
    }

    @Override
    public String getName() {
        return "RNTest";    // 不一定是类名,要和NativeModules.RNTest对应
    }

    // 自定义一个方法 处理消息
    // 通过注解  表示可以被RN侧调用
    @ReactMethod
    public void handleMsg(String msg){
        Toast.makeText(reactContext,msg,Toast.LENGTH_SHORT).show();
        // 自己创建一个普通的Activity
        Intent intent = new Intent(reactContext,MyActivity.class);
        // 一定要加  否则报错
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        reactContext.startActivity(intent);
    }

}

public class TestReactPackage implements ReactPackage {
    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();
        modules.add(new RNTest(reactContext)); // 添加上面定义的类
        return modules;
    }

    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }
}

public class MainApplication extends Application implements ReactApplication {

  private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
    @Override
    public boolean getUseDeveloperSupport() {
      return BuildConfig.DEBUG;
    }

    @Override
    protected List<ReactPackage> getPackages() {
      return Arrays.<ReactPackage>asList(
          new MainReactPackage(),new TestReactPackage()
      );
    }

... 下略
  sendMsgToAndroid() {
    var { NativeModules } = require('react-native');
    let test = NativeModules.RNTest;
    test.handleMsg('this is a rn msg');
  }

Android发送消息到RN端

    <!--读取联系人相关权限-->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_CONTACTS"/>


import static android.app.Activity.RESULT_OK;

/**
 * Created by shakespace on 2018/3/15.
 */

public class RNTest extends ReactContextBaseJavaModule {
    private static final String TAG = "RNTest";
    private ReactContext reactContext;

    // 创建一个mActivityEventListener
    private ActivityEventListener mActivityEventListener = new BaseActivityEventListener() {
        @SuppressWarnings("deprecation")
        @Override
        public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
            super.onActivityResult(activity, requestCode, resultCode, data);
            if (requestCode == 1 && resultCode == RESULT_OK && data != null) {
                Uri uri = data.getData();   // 获取地址
//                CursorLoader loader = new CursorLoader(activity, uri, null, null, null, null);
//                Cursor cursor = loader.loadInBackground();
                Log.e(TAG, uri.toString());
                Cursor cursor = activity.managedQuery(uri, null, null, null, null);

                cursor.moveToFirst();    //
                String msg = getInfo(cursor);
                sendMsgToRN(msg);
            }
        }
    };


    public RNTest(ReactApplicationContext reactContext) {
        super(reactContext);
        this.reactContext = reactContext;
        reactContext.addActivityEventListener(mActivityEventListener);
    }

    // 发送消息到RN端
    private void sendMsgToRN(String msg) {
        reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("AndroidToRNMessage", msg);
    }

    private String getInfo(Cursor cursor) {
        String name = "";
        String phone = "";

        //取得联系人姓名
        int nameFieldColumnIndex = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
        name = cursor.getString(nameFieldColumnIndex);

        // 联系人和电话数据库不在一起  获取字段  拼接查询条件
        int id = cursor.getColumnIndex(ContactsContract.Contacts._ID);
        String contactID = cursor.getString(id);
        String queryString = ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=" + contactID;
        Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;

        Cursor phoneCursor = reactContext.getContentResolver().query(uri, null, queryString, null, null);
        String phoneNumber = ContactsContract.CommonDataKinds.Phone.NUMBER;
        if (phoneCursor != null && phoneCursor.moveToFirst()) {
            phone = phoneCursor.getString(phoneCursor.getColumnIndex(phoneNumber));
        }
        phoneCursor.close();
//        cursor.close();//  使用managedQuery 不用手动关
        String result = "{\"msgType\": \"pickContactResult\",\"name\":\"" + name + "\", \"number\":\"" + phone + "\"}";
        Log.e(TAG, result);
        return result;
    }

    @Override
    public String getName() {
        return "RNTest";    // 要和NativeModules.RNTest对应
    }

    // 自定义一个方法 处理消息
    // 通过注解  表示可以被RN侧调用
    @ReactMethod
    public void handleMsg(String msg) {
        Toast.makeText(reactContext, msg, Toast.LENGTH_SHORT).show();
        Intent intent = new Intent(reactContext, MyActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        reactContext.startActivity(intent);
    }

    @ReactMethod
    public void pickContact() {
        Intent intent = new Intent(Intent.ACTION_PICK);
        intent.setType(ContactsContract.Contacts.CONTENT_TYPE);
        reactContext.startActivityForResult(intent, 1, null);
    }

}

主要步骤

添加监听 reactContext.addActivityEventListener
RN调用的方法中使用startActivityForResult调起原生页面
在onActivityResult处理回传的数据
使用reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("AndroidToRNMessage", msg);向RN端发送消息

import RCTDeviceEventEmitter组件,添加方法

  getContactFromAndroid(){
    // 监听安卓消息
    DeviceEventEmitter.addListener('AndroidToRNMessage',this.handleAndroidMsg.bind(this));
    var { NativeModules } = require('react-native');
    let test = NativeModules.RNTest;
    test.pickContact();
  }

  handleAndroidMsg(msg){
    console.log(msg);
    let aObj = JSON.parse(msg);
    this.updateName(aObj.name);
    this.updateNum(aObj.number);
    // this.setState({name:aObj.name,num:aObj.number})
    DeviceEventEmitter.removeAllListeners();
  }

完整案例查看:Demo

案例实现了从安卓端读取联系人并返回
在魅族手机上可能无法申请联系人权限,没有做更多适配,需要安装后自己手动在设置里打开权限。否则报错。
书中建议,如果是原生需要主动通信RN端,使用消息回调方式,如果是RN想原生请求操作并希望原生返回一个结果时,建议使用Promise方式。
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("AndroidToRNMessage", msg);属于消息机制
下例属于回调函数方式,因为桥接是异步的,所以不会立即执行

@ReactMethod
    public void handleMsg(String msg, Callback callback) {
        ...
      callback.invoke(msg);     // 回调函数方式
        ...
    }
  1. 创建一个promise成员变量,在ReactMethod中初始化
    Promise mPromise;  
    @ReactMethod
    public void pickContact(String msg,Promise promise) {
        this.mPromise = promise;    // 使用Promise方式时添加,在这里初始化
        ...
    }
  1. 返回结果时使用resolve函数
 mPromise.resolve(msg);
 发生异常时使用reject相关函数
  1. RN不用注册函数,调用方式如下
getContactFromAndroid(){
    // 监听安卓消息
    // DeviceEventEmitter.addListener('AndroidToRNMessage',this.handleAndroidMsg.bind(this));
    var { NativeModules } = require('react-native');
    let test = NativeModules.RNTest;
    // test.pickContact('testMsg');

    // 使用promise方式时,上面不用再注册回调
    test.pickContact('testMsg').then(
      // 表示处理结果的回调
      (result)=>{
        this.handleAndroidMsg(result);
      }
    ).catch(
      // 异常的处理
      (error)=>{
        console.log(error+"msg = "+ error.message + "code = "+ error.code);
      }
    );
  }
  1. 监听生命周期
    通过implements LifecycleEventListener可以监听原生的生命周期

  2. 跨语言常量

    @Nullable
    @Override
    public Map<String, Object> getConstants() {
        Map<String,Object> cons = new HashMap<>();
        cons.put("consName","tom");
        return cons;
    }
    
    在RN侧使用 模块名.consName 来访问被导出的常量
  1. 类型对应
Boolean -> Bool
Integer -> Number
Double -> Number
Float -> Number
String -> String
Callback -> function
ReadableMap -> Object
ReadableArray -> Array
上一篇 下一篇

猜你喜欢

热点阅读