美文网首页
react-native 与安卓端通信

react-native 与安卓端通信

作者: 我弟是个程序员 | 来源:发表于2017-07-13 10:54 被阅读0次

这里所说的通信,指的是参数互传,以及react-native调用native的方法。(ps: native 调用react-native中的方法?没有必要吧,毕竟android本地端比react-native多活那么多年,react-native有的,android端都能实现。)

  • 首先创建一个类,继承自ReactContextBaseJavaModule,这个类是以后react-native调用native方法的总管理类:
public class MyIntentModule extends ReactContextBaseJavaModule {
 private ReactApplicationContext mContext;  //用来管理ReactContextBaseJavaModule 的一个全局上下文
public static final String MODULE_NAME = "TTRNBridgeModule"; //别名
 public static final String EVENT_NAME_LOGIN_FOR_REFRESH = "refreshView";//登录监听码

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

    @Override
    public String getName() { //必须重写
        return MODULE_NAME;
    }

    /**
     * RN调用Native的方法
     * @param phone
     */
    @ReactMethod
    public void rnCallNative(String phone) {//该方法是自定的,方法头部必须添加@ReactMethod注解,RN才能找得到
        // 跳转到打电话界面
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_CALL);
        intent.setData(Uri.parse("tel:" + phone));
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // 跳转需要添加flag, 否则报错
        mContext.startActivity(intent);
    }

   /**
     * RN跳转到android页面操作
     */
    @ReactMethod
    public void rnCallNativeToShelf(){
       Intent intent = new Intent(mContext,BookShelfActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        mContext.startActivity(intent);
    }
   /**
     * Native调用RN  监听的方式
     * 从RN端 注册一个监听,然后在本地发送一个监听
     * @param msg
     */
    public void nativeCallRnLoginForRefresh(final int msg) { // 0 -- 登录成功  1 -- 登录失败
        mContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                .emit(EVENT_NAME_LOGIN_FOR_REFRESH,msg);
    }
}

RN操作

  • 创建类实现ReactPackage:
public class MyReactPackage implements ReactPackage {
    public MyIntentModule mModule; //上面创建的ReactContextBaseJavaModule

    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();
        mModule=new MyIntentModule(reactContext);
        modules.add(mModule);
        return modules;
    }

    @Override
    public List<Class<? extends JavaScriptModule>> createJSModules() {
        return Collections.emptyList();
    }

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

这里写法比较固定,一般没有什么大的变化。

  • ** 最后一步就是在你的Application当中,作一下操作:**
public class BaseApp extends Application implements ReactApplication {

   public static final MyReactPackage mCommPackage = new MyReactPackage();//上面创建的ReactPackage 

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

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

   @Override
    public void onCreate() {
        super.onCreate();
        
    }

   @Override
    public ReactNativeHost getReactNativeHost() {
        return mReactNativeHost;
    }
}

是不是很简洁,不得不说RN这点做得很好,完全是0污染。

以上都是准备工作 ,下面我们就来解决问题

1.下面,我们先来RN调用native方法吧,直接在你的RN代码中调用上面在ReactContextBaseJavaModule 已经用@ReactMethod声明了的方法,调用方法如下:

import React, {Component} from 'react';
import {
    ...
    NativeModules,
    ...
} from 'react-native';

export default class Xxxx extends Component {
    rnCallNative = ()=>{
          NativeModules.TTRNBridgeModule.rnCallNativeToShelf();
    }
}

TTRNBridgeModule看起来是不是好眼熟,没错,就是上面创建的ReactContextBaseJavaModule 的别名。

2.native 向RN传参,直接在关联的Activity中重写方法createReactActivityDelegate并传参:

public class CollectionSearchRNActivity extends ReactActivity {
    public static final String MAIN_COMPONENTNAME = "collectionSearch";

    @Override
    protected String getMainComponentName() {
        return MAIN_COMPONENTNAME;
    }

    @Override
    protected ReactActivityDelegate createReactActivityDelegate() {
        PreLoadReactActivityDelegate preLoadReactActivityDelegate =new PreLoadReactActivityDelegate(this, this.getMainComponentName());
        Bundle launchOptions = new Bundle();
        launchOptions.putString("orgGid", MyIntentModule.ORGGID);
        launchOptions.putString("passportGid",MyIntentModule.PASSPORTGID);
        launchOptions.putString("authorizationCode",MyIntentModule.AUTHORIZATIONCODE);
        preLoadReactActivityDelegate.setBundle(launchOptions);
        return  preLoadReactActivityDelegate;
    }
}

还有一种做法,RN在需要的时候,让native向RN传参,callback形式:

    @ReactMethod
    public void  rnInvokeisLoginCallBack(Callback callback){
        if (UserLoginActivity.isRNLogined(mContext.getCurrentActivity(),true,REQUEST_CODE)){
            String passport = SPUtils.get(DefineParamsKey.PASSPORT_GID,"").toString();
            String orgGid = SPUtils.get(DefineParamsKey.ORG_GID,"").toString();
            callback.invoke(orgGid,passport);
        }
    }

那么RN怎么获取呢?如下:

//TTRNBridgeModule 是别名,rnInvokeisLoginCallBack是函数名,NativeModules为依赖
NativeModules.TTRNBridgeModule.rnInvokeisLoginCallBack((orgGid, passportGid) => {                 
                    if (orgGid == "" || passportGid == null) {//未登录
                        return;
                    } else {
                        global.orgGid = orgGid;//global全局变量记录参数
                        global.passportGid = passportGid;      
                        callback();//得到数据后可以调用该方法做相关操作
                    }

                });

RN这里也是很简单很棒的设计。
3.RN向native传参,这个很简单了吧,不过好多人刚开始可能并没有想到,RN既然能够调用native方法,那么在方法里面放一个参数,又有什么不行的呢,不过传递对象过来的时候,通常传json字符串,然后自己在解析一下就行了。上面已经讲过RN调用native方法了,实际上传参也可以一并解决,不懂的自己去面壁思过~~~

4.最后一个就是native调用RN的方法了,目前native并不能直接调用RN的方法,而是通过native发送监听的方式,然后RN端接受到监听后,操作相应的方法,这个可以应用到登录的后需要更新RN视图的某些场景。
先看RN监听代码:

import React, {
    DeviceEventEmitter,
    NativeModules,
    Platform
}from 'react-native';

export default class EventManager{
    _subscriber = null; //监听者

    /**
     * @param eventType  监听的名称,用来区分监听,String类型
     * @param callback      监听的回调,需要监听的方法
     */
    init = (eventType,callback) =>{
        this._subscriber = DeviceEventEmitter.addListener(eventType,(msg) =>{//msg,监听发过来的参数
              if(msg == 0){
                    return ;
              }   
              callback();         
        });
    }

    /**
     * 销毁监听
     */
    destroy=()=>{
        if (this._subscriber != null) {
            this._subscriber.remove();
        }
    }
}

以上是我封装的DeviceEventEmitter监听类的代码,下面看RN调用过程:

import React, {Component} from 'react';
import {
    NativeModules,
    DeviceEventEmitter,
} from 'react-native';

import EventManager from '../../util/event_manager';

export default class BookDetails extends Component {
        constructor(props) {
        super(props);
        this.eventManager = new EventManager();//创建
        this.eventManager.init('refreshView', this.getBookdetail);//注册
      }

      getBookdetail = ()=>{
      //相关业务操作  
      }

      //销毁
     componentWillUnmount() {
          this.eventManager.destroy();
     }

}

native 发送监听的代码,在需要发送监听的地方使用

   /**
     * Native调用RN的方法  通过监听的方式
     * 该方法是登录都发送的一个监听
     * @param msg
     */
    public void nativeCallRnLoginForRefresh(final int msg) { // 1 -- 登录成功  0 -- 登录失败
        mContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                .emit("refreshView",msg);
    }

nativeCallRnLoginForRefresh当android本地调用该方法,就会发送一个监听消息,RN接受到消息后,执行对应的方法,从而实现了native调用RN的方法。

好了,今天的共享就写到这里了,不明白的可以踊跃发言,相互学习。

相关文章

网友评论

      本文标题:react-native 与安卓端通信

      本文链接:https://www.haomeiwen.com/subject/qlxwhxtx.html