【iOS&Android】RN学习3——集成进现有原生项目

在做了短暂的技术调研和分析之后,我决心将RN和现有的QDaily项目进行集成,并替换掉其中的广告效果展示页面。

本文开发环境为Mac,在React Native 版本为0.30。同时RN仅仅作为插件形势集成到原有Native工程中,因此主要还是一个Native工程而非RN工程

而且,本文的前提是你已经在本地配好了iOS开发环境或Android开发环境,也就是说,你起码已经是一个Android开发者或者iOS开发者。

一、必备的环境配置

先安装node.js,可以下载pkg包,也可以命令行安装:

brew install node

然后安装React Native的命令行工具(react-native-cli)

npm install -g react-native-cli

这样,最重要的东西就安装好了,其它东西都可以自己看个人情况酌情使用。此处出现任何问题,都可以直接官网或者stackoverflow。

二、集成进入iOS

iOS稍微复杂点,先介绍。

QDaily的iOS和Android客户端各维护自己的代码和git仓库,但React Native作为一个跨平台的解决方案,应该用单一的仓库进行一套代码统一管理。因此,我们这里采用了git仓库进行RN相关代码的管理,并用git submodule方式分别引入原工程。同时,在两个平台git仓库的根目录增加react文件夹,将所有RN的代码相关都放进去。

先截图看下iOS最后的目录结构:
1470152286.jpg

  • node_modules:react native依赖包,rn相关js和android、iOS的依赖lib都在里面。
  • package.json:当前项目的npm package的配置文件。有了它才有node_modules文件夹
  • index.ios.js:iOS平台加载的JS脚本
  • index.android.js:Android平台加载的JS脚本

1、init RN项目

在react文件夹运行React Native初始化命令react-native init [Project Name]

1
react-native init QDaily

2、原工程增加依赖

初始化完成后,打开在react/ios下面的同名工程,会看到下图的依赖proj:
1470152600.jpg

再打开原工程,新建个group,把上图的所有proj都拖进去。依赖工程完成。删掉react/ios和react/android文件夹。

然后在原工程的Build Phases界面里的Link Binary With Libraries,点击最下面的+号,吧所有libRCT开头的.a都加进去,如下图:
1470152888.jpg

3、增加头文件(h文件)

原工程的TARGETS->Build Settings->Header Search Paths中添加一条"$(SRCROOT)/react/node_modules/react-native/React",选择recursive,如下图:
1470153045.jpg

4、增加RN PreBuild shell脚本

这里就是用于模拟器下正确启动node.js服务器,真机下正确编译rn的bundle。

在TARGETS的Build Phases界面,点+号,选择New Run Script Phase添加一个脚本,并命名为Bundle React Native code and images,在内容中填入以下代码:

1
export NODE_BINARY=node
./react/node_modules/react-native/packager/react-native-xcode.sh

具体如下图所示:
1470153271.jpg

5、native固定代码配置指向的bundle

直接看代码:

1
#pragma - mark RCTBridgeDelegate
- (NSURL*) sourceURLForBridge:(RCTBridge *)bridge {
#if (TARGET_IPHONE_SIMULATOR)
    return [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle?platform=ios&dev=true"];
#else
    return [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"main" ofType:@"jsbundle"]];
#endif
}

到此,原有iOS项目集成React Native完成。有两个简单技巧:

  1. 模拟器下cmd+r可以reload刷新
  2. 如果真机下运行,不打算调试RN,请勾选步骤4中图片里的Run script only when installing,可以避免每次都build bundle。如下图:
    1470153671.jpg

三、集成进Android现有工程

我们这里假设已经正确完成了中的iOS集成,并将其react文件夹做git仓库管理(node_modules请ignore)。

我们这里还假设你的工程只支持Android4.1及以上,因为这是RN支持的最低版本。

1、git配置

将react工程git仓库链接到Android原有工程,并作为git submodules的形式引入到原工程根目录。pull后目录结构如下:
1470154017.jpg

2、初始化react

在react文件夹下运行

1
npm insall

之后你就发现node_modules文件夹又出现了

3、gradle配置

根目录的gradle增加本地的maven依赖:

1
allprojects {
    repositories {
        ...
        maven {
            url "$projectDir/../react/node_modules/react-native/android"
        }
    }
}

需要使用RN的module的gradle文件中增加对react native的依赖:

1
dependencies {
    ...
    compile "com.facebook.react:react-native:0.30.0"  
}

该gradle还要在android熟下增加ndk的配置:

1
android {
    ...
    defaultConfig {
        ...
        ndk {
            abiFilters 'armeabi-v7a','armeabi','x86','mips'
        }
    }
}

sync一下,配置完成了。

4、运行

Android这里和iOS不一样,真机不会默认打包到APK中;而且android的模拟器是虚拟机,不能和Mac共享一个localhost,所以一般调试方法如下。

如果用server的bundle,需要手动设置server ip:

现在react文件根目录下把node的server启动:

1
react-native start
  • 模拟器下(geny motion),cmd+m调起开发菜单,选择Dev Settings-Debug server host for device,然后设置Mac的ip和端口号;
  • 同样的,真机可以通过摇一摇调起上面的开发菜单;
  • 真机下在4.4以上也可以设置反向代理,将localhost指向Mac,这样就默认可以调试了。代码如下:
1
adb reverse tcp:8081 tcp:8081

上面的设置完成后,可以选择Reload JS来请求刷新页面,相当于iOS模拟器的cmd+r

注意:上面说的那个开发菜单,facebook使用悬浮窗的形式实现的,如果你使用的奇葩国产Android系统,那很有可能被系统默认禁掉了这个权限,导致白屏,请自行在各自rom的权限管理把显示悬浮窗权限打开。

如果用使用离线bundle,需要手动打包:

下面这个是我写的QDaily的RN bundle打包脚本,可以做参考。因为一些地方定制化了我们自己的热更新方案,所以和官方的略有不同,我会在下一篇介绍QDaily的react native热更新方案中进行具体介绍。
1470155788.jpg

四、项目其它开发者

项目的其它开发者需要完成步骤一,然后在react目录下运行npm install后,就可以正常进行native或者RN开发。


参考链接

http://facebook.github.io/react-native/

React Native移植iOS原生项目-已更新版本

React-Native For Android 环境搭建及踩坑

ReactNative之原生模块开发并发布–iOS篇

React Native iOS配置教程