2017年2月27日,天气晴,我永远记得这天,我心潮澎湃,因为终于把优谈TOP 集成了React Native,从去年开始,公司陆陆续续的集成和学习React Native,通过demo的形式,写了不少组件和API,也能和后端调通,也多次,多个人尝试把优谈TOP集成React Native,但是每次都是失败的,因为缺少经验,不能直接通过错误判断原因,只能通过Google查找各种资料,慢慢解决,下面记录了我们,优谈TOP 原生 集成React Native 的那些事。也许也是你的那些事?
常规思路:
通过百度搜索 已有Android工程集成ReactNative
出现一大堆教程,大部分教程都是通过在原来的基础上增加React Native的支持,比如这个:《Android之原生项目集成React Native》 ,这也是官方推荐的集成方式,我也推荐这个,只是我这样,一直报错,有一个启动 MainaAtivity的错,一直过不去,所以我就换一种思路。。。
在React Native基础上增加原生
开始通过官方文档安装和初始化React Native项目。
创建和运行React Native 项目
react-native init UtanTop
cd UtanTop
react-native run-android
如果没有错,再继续。如果有错,说明你环境都没有安装好,哈哈。请参考环境安装文档
恭喜你,第一步搞定了。接下来,巨坑的地方要来了。
把原生的 build.gradle
文件先集成进去
这一步比较简单,就是把gradle
相关文件复制替换就可以了,你想的好简单哈。。。
我建议:
首先把原项目的gradle相关文件复制到新建的React Native项目,不要破坏原来的React Native项目的配置。
如果原生项目里有Module,先不要把Module导入,为了保险,把最简单的导入。
修改Root 目录下的build.gradle
allprojects {
repositories {
mavenLocal()
jcenter()
maven {
url "http://192.168.1.205:8081/repository/utancenter/"
}
maven {
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
url "$rootDir/../node_modules/react-native/android"
}
}
}
如果有其他maven仓库直接这么写就可以了。
配置app目录下的build.gradle
buildTypes {
// release {
// // 不显示Log
// buildConfigField "boolean", "LOG_DEBUG", "false"
//
// minifyEnabled enableProguardInReleaseBuilds
// zipAlignEnabled true
// shrinkResources true
// proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt'
// signingConfig signingConfigs.release
//
// applicationVariants.all { variant ->
// variant.outputs.each { output ->
// def outputFile = output.outputFile
// if (outputFile != null && outputFile.name.endsWith('.apk')) {
//
// //if ("woman".equals(WOMAN)){
// // def fileName = "WomanTop_v${defaultConfig.versionName}_${variant.productFlavors[0].name}.apk"
// //output.outputFile = new File(outputFile.parent+File.separator+"v"+defaultConfig.versionName, fileName)
// //} else {
// def fileName = "UtanTop_v${defaultConfig.versionName}_${variant.productFlavors[0].name}.apk"
// output.outputFile = new File(outputFile.parent + File.separator + "v" + defaultConfig.versionName, fileName)
// //}
//
//
// }
// }
// }
// }
release {
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
}
}
贴这个的意思就是先把打渠道包的去掉,使用React Native生成的配置,之后打渠道包在说,记得把下面几段也要先注释掉。
// // 多渠道打包
// productFlavors {
// T1 {}
// T2 {}
// T3 {}
//
// }
//
// productFlavors.all { flavor ->
// flavor.manifestPlaceholders = [CHANNEL_VALUE: name]
// }
如果集成友盟的多渠道包,还需要在AndroidManifest.xml
中注释掉。
<meta-data
android:name="UMENG_APPKEY"
android:value="${UMENG_APPKEY}" />
在这个时候我们还没集成源码,再执行:
react-native run-android
如果编译通过,恭喜你,如果没有过那是正常的,因为还有一个坑。
我的报错信息是
* What went wrong:
Execution failed for task ':app:packageAllDebugClassesForMultiDex'.
> java.util.zip.ZipException: duplicate entry: bolts/AggregateException.class
是因为导入了重复的条目。
可能是在某些某些gradle版本才有吧。。。
我的解决方法:
compile('com.facebook.fresco:fresco:0.10.0') {
exclude group: 'com.parse.bolts',
module: 'bolts-android'
}
compile ('com.facebook.fresco:animated-gif:0.10.0'){
exclude group: 'com.parse.bolts',
module: 'bolts-android'
}
这时候再执行:
react-native run-android
现在问题应该不大了,按道理可以运行起来了,反正我的运行起来了,但是还没有加入源码。。。
现在就把java
res
libs
assets
目录下的文件和 AndroidManifest.xml
复制到React Native项目中。
把MainApplication
集成你原生项目的Application
一般项目都会自定一个
Application
public class MainApplication extends UtanToutiaoApp 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()
);
}
};
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
@Override
public void onCreate() {
super.onCreate();
SoLoader.init(this, /* native exopackage */ false);
}
}
注意:不要把
MainActivity
MainApplication
,文件覆盖了。
再执行:
react-native run-android
应该可以成功了,如果默认启动的是MainActivity
,那展示的就是React Native 界面,如果默认不是MainActivity
,那就通过下面的方式启动。
Intent i = new Intent(context, MainReactActivity.class);
context.startActivity(i);
到这里我反正就ok了,不知道你ok了没?
如果不OK ,请留言,一起探讨。。
还有我在学习和使用React Native 之后也会贴出来供大伙参考。。请关注 quanke