接入QRN4Android(>=2.0.0) #


配置依赖 #

配置依赖/Spider框架 #

在gradle文件中配置如下:

atomCompile 'com.qunar.spider:react:{lib-version}@aar'

atom.dps文件中配置如下:

{
        "packageName": "com.mqunar.react",
        "versionCode": "{atom-version}"
}

其中lib-version为QRN的最新版本,atom-version为Spider组件形式的RN4A的组件版本。

配置依赖/独立App #

需要配置公司内网的Maven仓库,如果没有内网环境请联系我们支持。

以AS工具生成的标准Android工程为例说明,首先在工程根部的build.gradle文件中加入如下配置:

allprojects {
    repositories {
        maven {
            url "http://l-nexus1.wap.cn8.qunar.com:8081/nexus/content/groups/public"
        }
        maven {
            url "http://svn.corp.qunar.com:8081/nexus/content/groups/public"
        }
        jcenter()
        //如果你需要本地依赖aar,则加入该段代码,否则可以注释掉
        flatDir {
            dirs 'libs'
        }
    }
}

在App模块的build.gradle文件中加入如下配置:

    compile ('com.qunar.spider:qrn_lib:0.0.2@aar') {
        transitive=true
    }
    compile ('com.qunar.spider:yrn_core:0.0.1-SNAPSHOT@aar') {
        transitive=true
    }
    compile 'com.qunar.spider:qrn_independent:0.0.0.1-SNAPSHOT@aar'
    //如果需要用到我们的热更新机制,请加入以下依赖
    compile "com.qunar.spider:goblin:3.0.3:boat@aar"
    compile "com.qunar.3dparty:libammsdk:1.0.1"

配置依赖/防混淆设置 #

在防混淆文件中加入如下配置:

    -keep class  com.mqunar.react.** {*;}
    -keep class  com.yrn.core.** {*;}
    -keep class  com.facebook.react.** {*;}

RN4A初始化 #

QRN For Android端采用了Builder模式配置,你可以根据项目的具体需求配置需要的,我们提供了非常丰富的定制接口,只需要构造一个QRNConfigure实例进行QRN的初始化工作即可。

建议初始化工作放到Application的onCreate()生命周期中,最简单的配置如下:

        QRNConfigure conf = QRNConfigure.newBuilder()
                .env(fakeEnv())
                .customJsBundleLoaderWorker(new MyBundleLoader(this))
                .build();
        ReactSdk.init(this, conf);

下面详细介绍QRNConfigure类的配置项:

  • showNetTips: 设置是否显示使用网络提示,默认为true
  • customForwardingCookieHandler: 设置是否在网络请求中使用自定义的Cookie处理器,默认为官方的CookieHandler
  • env: 设置当前的环境信息,不能为空
  • addReactPackage: 添加自定义的RN包
  • addGlobalReactPackage: 全局添加自定义的RN包
  • soLoadErrorCallback: so初始化失败相关回调
  • schemeModuleProxy: 自定义Scheme跳转相关操作,不设置默认使用通用方式
  • cookieManagerHandler: 用于CookieModule相关的实现类,如果有需要CookieModule功能请配置一个处理器
  • shouldInterceptFrescoInitOperation: 设置是否拦截Fresco库初始化操作,默认为false
  • errorReportListener: 设置Js崩溃捕获,以及桥加载异常的捕获处理
  • resourceUriHelper: 设置资源映射关系,主要用于离线资源加载机制,默认为通用映射行为(优先使用资源顺序:assets->qp->http)
  • customJsBundleLoaderWorker: 自定义加载Js Bundle文件行为,用于指定加载指定位置的Bundle包,如果自定义该加载器,则RN设置中的加载类型(本地、Beta和线上)配置都将失效,RN4A均走自定义的加载器
  • bundleUrlMapper: 自定义Bundle包加载地址的映射规则,与RN设置中的加载类型(本地、Beta和线上)配置一一对应,与resourceUriHelper冲突
  • appIdWechat: 设置微信分享使用的AppId

RN4A配置Scheme #

在独立App中,如果需要通过Scheme来打开RN页面,需要在AndroidManifest.xml中为RN4A的Scheme分发器配置一个Scheme头,示例代码如下:

        <activity android:name="com.mqunar.react.base.QRNSchemeController">
            <intent-filter>
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <data
                    android:host="react"
                    android:scheme="{your_shceme}"/>
            </intent-filter>
        </activity>

RN4A开放API #

我们把RN4A所有的开放API集中在QReactNative类中统一提供,请尽量不要使用RN4A内部一些类的方法,如果有新需求请联系我们支持。

RN4A开放API/打开QRN页面 #

除了直接用Scheme方式('{scheme头}://react/open?hybridId=xxx&moduleName=xxx&qInitView=xxx&initProps=encode({xxx})')打开之外,还可以用RN4A提供的代码方式打开。

QReactNative.startReactActivity(
    activity,
    hybridId,
    moduleName,
    jsonParams,
    initProps,
    showLoading);

我们提供了startReactActivity的三种重载函数,可以根据具体需求选用,以上面函数为例,参数相关信息如下:

  • activity: Activity类型,非空,当前调用的Activity实例
  • hybridId: String类型,非空,业务对应的HybridId
  • moduleName: String类型,非空,业务HybridId对应的模块名
  • jsonParams: String类型,可空,用于初始化的Json类型字符串,将会被解析并放到initProps对象中
  • initProps: Bundle类型,可空,传递给Js的初始化参数
  • showLoading: boolean类型,控制加载Loading显示

如果需要获取Activity返回的状态,请使用下面两个变量:

  • QReactNative.ACTIVITY_FAILURE: 当RN4A桥加载失败时候会返回此值
  • QReactNative.ACTIVITY_CANCLE: 当用户取消加载RN页面时候返回此值

RN4A开放API/预加载桥 #

由于RN4A桥初始化需要一定的耗时,我们提供了可以后台预加载桥的API用于业务加载提速,请合理地使用它。

QReactNative.preloadBridge(app, hybridId, fitSystemWindow, callback)

参数信息如下:

  • app: Application类型,当前应用的Application实例
  • hybridId: String类型,非空,业务对应的HybridId
  • fitSystemWindow: 当打开沉浸式时候是否为RN视图往下偏移一个状态栏高度的值,默认为true,
  • callback: QReactPreloadCallback类型,可空,预加载的结果回调

RN4A开放API/注册业务组件 #

注册业务组件非常简单,需要注意的是,受限于RN4A目前不支持动态挂在Package,该API需要在未初始化对应业务的RN桥前调用方有效。

QReactNative.registerReactPackage(hybridId, reactPackage);

参数信息如下:

  • hybridId: String类型,非空,业务对应的HybridId
  • reactPackage: ReactPackage类型,非空,已经封装好的RN Package

RN4A开放API/发送Js广播消息 #

boolean result = QReactNative.sendJsBroadCastReceiver(hybridId, action, writableMap);

参数信息如下:

  • hybridId: String类型,可空,业务对应的HybridId,如果传空则向全局发送消息
  • action: String类型,非空,发送给Js消息的Action名
  • writableMap: WritableMap,非空,发送消息的实体内容
  • 返回参数: boolean类型,如果发送消息成功,则返回true

RN4A开放API/定制ReactRootView #

如果你想高度定制ReactRootView控件,比如自由控制RN控件的展示区域,以及随意指定RN桥的加载时机等等,有两种方式可以实现,一种是继承我们的QReactActivity类,另一种方式是自己控制的QReactHelper实例,前者相对后者而言更为简单,下面会分别说明。

1. 继承QReactActivity方式

该方式只需要考虑在合适时机调用initReactInstanceManager()onResume()方法就行,两者方法区别如下:

  • initReactInstanceManager(): 第一次初始化rn页面调用,用于初始化RN桥和渲染RN界面
  • onResume(): 在Activity生命周期onResume中调用,主要用于Activity被系统销毁之后,重新绑定ReactRootView和渲染之前的RN页面

①关于initReactInstanceManager方法

protected final void initReactInstanceManager(Application app,
                                                ReactRootView rootView,
                                                String hybridId,
                                                String moduleName,
                                                Bundle launchOptions,
                                                boolean fitSystemWindow,
                                                QReactHelperCreatCallback listener)

请注意:该方法应该在第一次初始化RN4A桥的时候被调用,桥创建之后不可重复调用。

参数信息如下:

  • app: 当前应用的Application实例
  • rootView: RN4A的根View,自己创建
  • hybridId: 对应业务的HybridId信息
  • moduleName: 对应业务的模块名
  • launchOptions: 应用启动带过去的初始化Bundle
  • fitSystemWindow: 当打开沉浸式时候是否为RN视图往下偏移一个状态栏高度的值,默认为true,
  • listener: 创建RN4A桥的相关生命周期回调

关于launchOptions使用

这个参数用于给Js传送参数,Bundle类型,不支持传输SerializableParcelable对象。

launchOptions保留key(isQRCTDefCreate, __hybridId_do_not_change_or_you_will_be_fired, isCreateFromDestroy)。

如果你需要传输自定义的Bean对象,建议使用第三方库将其转成json字符串,然后放到keyqJsonInitProps中即可,我们会将qJsonInitProps的值解析成js对象,并且qJsonInitProps的值不会传输给Js。

示例如下:

...
launchOptions.putString('name', 'boger');
launchOptions.putBoolean('isCool', true);
String json = parseJson(aBean);
//json字符串将会被qrn提取解析并从参数中移除
launchOptions.putString('qJsonInitProps', json);
...

Q: Js端如何获取Native传递的launchOptions参数?

A: 使用Ext的话只需在bindEvents绑定生命周期actived,事件中的param参数包含有launchOptions;不使用Ext的话this.props即可。

②关于onResume方法

protected final void onResume(@Nullable Application app, @Nullable ReactRootView view, @Nullable QReactHelperCreatCallback callback)

考虑到当栈中的RN Activity被系统回收之后重新创建的Case,我们封装了onResume方法使之能在Activity恢复之后直接显示RN界面而非白屏,你需要额外传入一些参数,当然,不使用这个功能的可以不传这些额外的参数。

参数信息如下:

  • app: 当前应用的Application实例
  • view: RN4A的根View,自己创建
  • callback: 创建RN4A桥的相关生命周期回调,这里当RN4A恢复UI时候会被调用
2. 直接使用QReactHelper操作

需要先创建一个QReactHelper实例,然后在Activity的相应生命周期中回调QReactHelper相对应的方法。具体使用可以参考我们提供的示例工程

这里有个问题需要注意下,QReactHelper有个onResume方法比较特殊,为了实现Activity被销毁之后的UI恢复,提升用户体验,请尽可能地传有效值而非空值。

RN4A开放API/使用HeadlessJsTaskService #

由于QRN与官方RN相比,存在多桥状态,你需要通过重载getReactInstanceManager方法来返回一个与Server绑定的桥实例,示例代码如下:

public class MyJsService extends HeadlessJsTaskService {

    //省略其他代码
    ...

    @Override
    protected ReactInstanceManager getReactInstanceManager() {
        return myReactInstanceManager;
    }

    //省略其他代码
    ...
}

示例工程 #

Demo入手最快了,可以从这里开始QRN4A之旅!我是传送门