2017年2月27日,天氣晴,我永遠(yuǎn)記得這天,我心潮澎湃,因?yàn)榻K于把優(yōu)談TOP 集成了React Native,從去年開(kāi)始,公司陸陸續(xù)續(xù)的集成和學(xué)習(xí)React Native,通過(guò)demo的形式,寫(xiě)了不少組件和API,也能和后端調(diào)通,也多次,多個(gè)人嘗試把優(yōu)談TOP集成React Native,但是每次都是失敗的,因?yàn)槿鄙俳?jīng)驗(yàn),不能直接通過(guò)錯(cuò)誤判斷原因,只能通過(guò)Google查找各種資料,慢慢解決,下面記錄了我們,優(yōu)談TOP 原生 集成React Native 的那些事。也許也是你的那些事?
常規(guī)思路:
通過(guò)百度搜索 已有Android工程集成ReactNative 出現(xiàn)一大堆教程,大部分教程都是通過(guò)在原來(lái)的基礎(chǔ)上增加React Native的支持,比如這個(gè):《Android之原生項(xiàng)目集成React Native》 ,這也是官方推薦的集成方式,我也推薦這個(gè),只是我這樣,一直報(bào)錯(cuò),有一個(gè)啟動(dòng) MainaAtivity的錯(cuò),一直過(guò)不去,所以我就換一種思路。。。
在React Native基礎(chǔ)上增加原生
開(kāi)始通過(guò)官方文檔安裝和初始化React Native項(xiàng)目。
創(chuàng)建和運(yùn)行React Native 項(xiàng)目
react-native init UtanTop
cd UtanTop
react-native run-android
如果沒(méi)有錯(cuò),再繼續(xù)。如果有錯(cuò),說(shuō)明你環(huán)境都沒(méi)有安裝好,哈哈。請(qǐng)參考環(huán)境安裝文檔
恭喜你,第一步搞定了。接下來(lái),巨坑的地方要來(lái)了。
把原生的 build.gradle 文件先集成進(jìn)去
這一步比較簡(jiǎn)單,就是把gradle相關(guān)文件復(fù)制替換就可以了,你想的好簡(jiǎn)單哈。。。
我建議:
首先把原項(xiàng)目的gradle相關(guān)文件復(fù)制到新建的React Native項(xiàng)目,不要破壞原來(lái)的React Native項(xiàng)目的配置。
如果原生項(xiàng)目里有Module,先不要把Module導(dǎo)入,為了保險(xiǎn),把最簡(jiǎn)單的導(dǎo)入。
修改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倉(cāng)庫(kù)直接這么寫(xiě)就可以了。
配置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"
}
}
貼這個(gè)的意思就是先把打渠道包的去掉,使用React Native生成的配置,之后打渠道包在說(shuō),記得把下面幾段也要先注釋掉。
// // 多渠道打包
// productFlavors {
// T1 {}
// T2 {}
// T3 {}
//
// }
//
// productFlavors.all { flavor ->
// flavor.manifestPlaceholders = [CHANNEL_VALUE: name]
// }
如果集成友盟的多渠道包,還需要在AndroidManifest.xml中注釋掉。
<meta-data
android:name="UMENG_APPKEY"
android:value="${UMENG_APPKEY}" />
在這個(gè)時(shí)候我們還沒(méi)集成源碼,再執(zhí)行:
react-native run-android
如果編譯通過(guò),恭喜你,如果沒(méi)有過(guò)那是正常的,因?yàn)檫€有一個(gè)坑。
我的報(bào)錯(cuò)信息是
* What went wrong:
Execution failed for task ':app:packageAllDebugClassesForMultiDex'.
> java.util.zip.ZipException: duplicate entry: bolts/AggregateException.class
是因?yàn)閷?dǎo)入了重復(fù)的條目。
可能是在某些某些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'
}
這時(shí)候再執(zhí)行:
react-native run-android
現(xiàn)在問(wèn)題應(yīng)該不大了,按道理可以運(yùn)行起來(lái)了,反正我的運(yùn)行起來(lái)了,但是還沒(méi)有加入源碼。。。
現(xiàn)在就把java res libs assets 目錄下的文件和 AndroidManifest.xml 復(fù)制到React Native項(xiàng)目中。
把MainApplication 集成你原生項(xiàng)目的Application
一般項(xiàng)目都會(huì)自定一個(gè)
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);
}
}
注意:不要把
MainActivityMainApplication,文件覆蓋了。
再執(zhí)行:
react-native run-android
應(yīng)該可以成功了,如果默認(rèn)啟動(dòng)的是MainActivity,那展示的就是React Native 界面,如果默認(rèn)不是MainActivity,那就通過(guò)下面的方式啟動(dòng)。
Intent i = new Intent(context, MainReactActivity.class);
context.startActivity(i);
到這里我反正就ok了,不知道你ok了沒(méi)?
如果不OK ,請(qǐng)留言,一起探討。。
還有我在學(xué)習(xí)和使用React Native 之后也會(huì)貼出來(lái)供大伙參考。。請(qǐng)關(guān)注 quanke