編譯環(huán)境
官方的編譯環(huán)境要求如下,值得注意的是這里的NDK版本最好是r10e,親測過其他兩個(gè)版本的NDK并沒有成功,因此這里最好是下載r10e版本的NDK。
- Android SDK version 23 (編譯SDK版本號在build.gradle中可以找到)
- SDK build tools version 23.0.1(編譯工具版本號在build.gradle中可以找到)
- Android Support Repository >= 17
- Android NDK r10e下載地址
將Gradle指向你的安卓SDK: 設(shè)置$ANDROID_SDK和$ANDORID_NDK為對應(yīng)的目錄抢蚀,或者按照以下內(nèi)容在react-native根目錄下創(chuàng)建local.properties文件(注意:windows下需要使用反雙斜杠)。
sdk.dir=指向android sdk目錄的絕對路徑
ndk.dir=指向android ndk目錄的絕對路徑
例如:
ndk.dir=D\:\\android-ndk-r10e
sdk.dir=C\:\\Users\\AppData\\Local\\Android\\Sdk
獲取源碼
按照官方給的下面命令獲取源碼镰禾,我試了運(yùn)行失敗皿曲。
npm install --save github:facebook/react-native#master
其實(shí)當(dāng)我們 react-native init [ProjectName] 的時(shí)候,工程node-modules/react-native/ReactAndroid的目錄就包含了源碼吴侦,因此我們可以直接讓我們的應(yīng)用工程引用這一個(gè)源碼工程屋休,因此這里我們直接運(yùn)行一下命令初始化一個(gè)react native工程testapp。
react-native init testapp
添加gradle依賴
(1) 在生成的React Native工程中备韧,將android/build.gradle文件中添加gradle-download-task依賴博投。
...
dependencies {
// gradle可以不替換,還是原來的版本
classpath 'com.android.tools.build:gradle:1.3.1'
classpath 'de.undercouch:gradle-download-task:3.1.2' //新增加的內(nèi)容
// 注意:不要把你的應(yīng)用的依賴放在這里盯蝴;
// 它們應(yīng)該放在各自模塊的build.gradle文件中
}
...
(2) 添加:ReactAndroid項(xiàng)目毅哗,在android/settings.gradle中添加:ReactAndroid項(xiàng)目。
...
//包含ReactAndroid工程
include ':ReactAndroid'
//指出ReactAndroid工程的地址
project(':ReactAndroid').projectDir = new File(rootProject.projectDir, '../node_modules/react-native/ReactAndroid')
...
(3) 修改你的android/app/build.gradle文件捧挺,使用:ReactAndroid替換預(yù)編譯庫虑绵。例如用compile project(':ReactAndroid'):替換compile 'com.facebook.react:react-native:+'
dependencies {
compile fileTree(dir: "libs", include: ["*.jar"])
compile "com.android.support:appcompat-v7:23.0.1"
compile project(':ReactAndroid') //添加React-native項(xiàng)目
//compile "com.facebook.react:react-native:+" //注釋掉原來的react-native引用
}
(4) 讓第三方模塊使用你的分支
如果你使用第三方的React Native模塊,你需要重寫它們的依賴以避免它們?nèi)匀淮虬俜降念A(yù)編譯庫闽烙。否則當(dāng)你編譯時(shí)會(huì)報(bào)錯(cuò)-Error: more than one library with package name 'com.facebook.react'.(錯(cuò)誤:有幾個(gè)重名的'com.facebook.react'的包)
修改你的android/app/build.gradle文件翅睛,添加如下內(nèi)容:
configurations.all {
exclude group: 'com.facebook.react', module: 'react-native'
}
編譯運(yùn)行
在Android Studio歡迎頁中選擇Import project,隨后選擇應(yīng)用所在的文件夾黑竞。
然后開始Run捕发,這個(gè)過程需要下載200多M的文件然后才開始編譯,編譯快的可能幾分鐘很魂,有時(shí)候甚至不一定成功扎酷。
在我編譯的時(shí)候查看Gradle Console的時(shí)候發(fā)現(xiàn)一直卡在downloadBoost這個(gè)task上,
:ReactAndroid:createNativeDepsDirectories UP-TO-DATE
:ReactAndroid:downloadBoost
Download http://mirror.nienbo.com/boost/boost_1_57_0.zip
查看ReactAndroid/build.gradle里面的內(nèi)容可以看到這個(gè)任務(wù)(如下)下載的是C++的boost庫遏匆,文件大小接近105M法挨,因此我們把 https://downloads.sourceforge.net/project/boost/boost/1.57.0/boost_1_57_0.zip 替換成 http://mirror.nienbo.com/boost/boost_1_57_0.zip 就會(huì)快很多谁榜。或者直接從 官網(wǎng)地址 下載并復(fù)制到ReactAndroid工程的build/downloads目錄下凡纳,這樣就會(huì)直接跳過downloadBoost這個(gè)task窃植,編譯速度就會(huì)快很多。
task downloadBoost(dependsOn: createNativeDepsDirectories, type: Download) {
src 'https://downloads.sourceforge.net/project/boost/boost/1.57.0/boost_1_57_0.zip'
onlyIfNewer true
overwrite false
dest new File(downloadsDir, 'boost_1_57_0.zip')
}
clean與build 問題
當(dāng)我們成功編譯運(yùn)行后荐糜,clean的時(shí)候會(huì)將我們之前下載的文件包括boost庫文件刪除掉巷怜,因此為了clean之后再次下載編譯so庫的問題,我們需要執(zhí)行以下三個(gè)步驟暴氏。
1.將ReactAndroid/build/react-ndk 文件夾移動(dòng)到ReactAndroid項(xiàng)目下也就是ReactAndroid/react-ndk目錄下丛版,這一個(gè)目錄是編譯生成的so文件。
2.將ReactAndroid/build.gradle里面的SourceSets.main里面的jniLibs.srcDir的目錄從"$buildDir/react-ndk/exported"改為"react-ndk/exported"偏序,這樣就編譯的時(shí)候就會(huì)去尋找ReactAndroid/react-ndk目錄的so文件。
sourceSets.main {
jni.srcDirs = []
jniLibs.srcDir "react-ndk/exported" //so庫目錄
res.srcDirs = ['src/main/res/devsupport', 'src/main/res/shell', 'src/main/res/views/modal']
java {
srcDirs = ['src/main/java', 'src/main/libraries/soloader/java', 'src/main/jni/first-party/fb/jni/java']
exclude 'com/facebook/react/processing'
exclude 'com/facebook/react/module/processing'
}
}
3.將ReactAndroid/build.gradle里面編譯so文件的task注釋掉胖替,并將clean依賴于cleanReactNdkLib的task也注視掉研儒,這樣clean的時(shí)候才不會(huì)出錯(cuò)。
//注釋掉下面兩個(gè)任務(wù)
/* tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn packageReactNdkLibs //開始編譯前先進(jìn)行ndk編譯
}
clean.dependsOn cleanReactNdkLib*/
這樣clean之后再次build就不會(huì)重新進(jìn)行ndk編譯so文件独令,縮短編譯的時(shí)間端朵。