react-native 与安卓端通信

这里所说的通信,指的是参数互传,以及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的方法。

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,922评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,591评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,546评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,467评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,553评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,580评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,588评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,334评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,780评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,092评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,270评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,925评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,573评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,194评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,437评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,154评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容

  • ¥开启¥ 【iAPP实现进入界面执行逐一显】 〖2017-08-25 15:22:14〗 《//首先开一个线程,因...
    小菜c阅读 6,389评论 0 17
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,008评论 25 707
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,647评论 18 139
  • 重入锁ReentrantLock,顾名思义,就是支持重进入的锁,它表示该锁能够支持一个线程对资源的重复加锁。除此之...
    Q南南南Q阅读 240评论 0 0
  • 我们都不知道 结局竟然是这样 果然 世界不是围着我们的 一切之前美好的愿望 都会被周围各种各样的事情给打扰 可是又...
    Sun艾维阅读 217评论 0 0