使用Gradle構建Android程序
使用Gradle構建Android程序by Rinvay.T
Android Studio正式版早已經發布了,默認使用Gradle構建,GitHub上80%的Android項目也都是使用Gradle構建的,我們還有什么理由不使用Gradle呢?
環境要求
- JDK 下載地址
- Android SDK 下載地址
- Gradle 下載地址1下載地址2 </ul>
給一個國內的下載地址:AndroidDevTools
開始(改造Eclipse項目)
eclipse可以直接用adt導出為gradle項目,android studio直接創建gradle項目。但是,我們還是有必要了解下手動改造,這讓我們更清楚每個文件的作用。
獨立項目構建
在我的另一篇博客Gradle插件用戶指南(譯)中,3.1節可以看到,
一個最簡單的build.gradle文件是這樣的:
buildscript { repositories { jcenter() }dependencies { classpath 'com.android.tools.build:gradle:1.1.0' }
}
apply plugin: 'com.android.application'
android { compileSdkVersion 19 buildToolsVersion "22.0.1" }</pre>
這里,要求項目目錄結構是gradle的默認目錄:
project-root |-src |-main |-java |-res |-drawable |-layout |-values |-AndroidManifest.xml如果是eclipse下的項目,需要配置下項目目錄,修改后的build.gradle文件是這樣的:
buildscript { repositories { jcenter() }dependencies { classpath 'com.android.tools.build:gradle:1.1.0' }
}
apply plugin: 'com.android.application'
android { compileSdkVersion 19 buildToolsVersion "22.0.1"
sourceSets { main{ manifest.srcFile 'AndroidManifest.xml' java.srcDirs = ['src'] aidl.srcDirs = ['src'] renderscript.srcDirs = ['src'] res.srcDirs = ['res'] assets.srcDirs = ['assets'] jniLibs.srcDirs = ['libs'] } } dependencies { compile fileTree(dir:'libs', include:['*.jar']) }
}</pre>
把這個build.gradle拷貝到項目根目錄下,就可以使用gradle來構建你的app了。
打開終端/命令行,切換到項目根目錄,運行gradle assemble,在main-project/build/outputs/apk下就可以看到生成的apk文件
Note:
要注意原項目的依賴,比如 ApiDemos ,是依賴support-v4的,要添加到dependencies中。compile 'com.android.support:support-v4:19.0.0'多項目構建
如果程序是由多個子工程構成的話,上面的build.gradle文件就不夠用了。
假設你的項目目錄是這樣的
root |-main-project |-library-project1 |-library-project2并且,依賴關系如下:
main-project -> library-project1 library-project1 -> library-project2那么,Gradle構建文件應該包含以下幾個文件:
settings.gradle build.gradle main-project/build.gradle library-project1/build.gradle library-project2/build.gradle文件位置是這樣:
root |-main-project |- ... |-build.gradle |-library-project1 |- ... |-build.gradle |-library-project2 |- ... |-build.gradle |-build.gradle |-settings.gradle文件內容如下:
-
settings.gradle:
include ':main-project','library-project1','library-project2'
</li> </ul>settings.gradle聲明了程序包含的子項目,如果子項目時包含在三級子目錄下,例如root/library/library-project1,那么聲明是這樣的:
':library:library-project1'
-
build.gradle:
buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:1.0.0' } }
根目錄下的buidle.gradle聲明了項目的編譯環境,指定了Android Gradle插件的版本。和上一個章節,那個單一的build.gradle的前半部分內容是一樣的。
</li> -
main-project/build.gradle:
apply plugin: 'com.android.application'
android { compileSdkVersion 19 buildToolsVersion "22.0.1"
sourceSets { main{ manifest.srcFile 'AndroidManifest.xml' java.srcDirs = ['src'] aidl.srcDirs = ['src'] renderscript.srcDirs = ['src'] res.srcDirs = ['res'] assets.srcDirs = ['assets'] jniLibs.srcDirs = ['libs'] } } dependencies { compile fileTree(dir:'libs', include:['*.jar']) compile project(':library-project1') }
}</pre></li> </ul>
這個build.gradle的內容與上一章節build.gradle的后半部分基本一致,只是多了一個庫項目依賴的聲明。
這里假設目錄結構和eclipse下的android項目目錄結構是一樣的,如果實際目錄和gradle的默認目錄結構一樣,可以去掉sourceSets{...}部分-
library-project1/build.gradle和main-project/build.gradle基本一致,只有兩個地方不一樣。
- apply plugin: 'com.android.application'改成apply plugin: 'com.android.library'
- compile project(':library-project1')改成compile project(':library-project2') </ul> </li>
-
library-project1/build.gradle和library-project2/build.gradle基本一致,只有一個地方不一樣。
- 去掉compile project(':library-project2') </ul> </li> </ul>
至此,多項目的工程完成了gradle改造,可以在項目根目錄下運行gradle assemble進行構建了。
構建的其他細節,請參考我的另一篇博客Gradle插件用戶指南(譯)。
gradle wrapper
和Eclipse導出或者Android Studio創建的項目相比,我們改造完的項目還差了幾個文件。
在項目根目錄下,運行終端命令gradle wrapper,就會生成下面幾個文件:project-root |-gradle |-wrapper |-gradle-wrapper.jar |-gradle-wrapper.properties |-gradlew |-gradlew.bat
gradlew,gradlew.bat是支持多平臺的gradle運行命令,如果運行時,發現系統沒有對應版本的gradle,會通過gradle-wrapper.jar下載gradle-wrapper.properties中指定的gradle版本。這樣的話,任何人獲取代碼后,不用安裝gradle,就可以構建工程。
生成的gradle-wrapper.properties文件中指定的版本,就是運行gradle wrapper命令時的gradle版本。
通過gradlew,可以執行gradle構建任務,例如:
./gradlew assemble
使用Android Studio
Android Studio創建的項目默認使用Gradle構建,并且目錄結構也是Gradle默認的。
使用Android Studio 創建 Android 項目
這個很簡單,新建項目,按照引導一步一步往下走就行了。
新建項目的結構如下:
project-root |-app |-src |-androidTest |-main |-java |-res |-AndroidManifest.xml |-build.gradle |-gradle |-wrapper |-gradle-wrapper.jar |-gradle-wrapper.properties |-build.gradle |-gradle.properties |-gradlew |-gradlew.bat |-local.properties |-settings.gradle
app
是項目代碼和資源目錄gradlew,gradlew.bat,gradle/wrapper
上一章節已經介紹過了build.gradle,settings.gradle
上一章節已經介紹過了gradle.properties
gradle運行的參數local.properties
本地環境參數,例如android sdk路徑:sdk.dir導入Gradle項目到Android Studio
對于非Android Studio項目,完成gradle改造后,可以導入到Android Studio中。
File -> Open... 或者Android Studio啟動頁的 Open an existing Android Studio project
直接選擇打開項目根目錄下的settings.gradle(如果沒有的話,打開build.gradle)文件,或者setting.gradle文件的父目錄,結果如下圖:
如果運行過前面的gradle wrapper命令的話(或者是由eclipse導出的gradle項目),目錄下有wrapper文件夾,Use default gradle wrapper(recommanded)選項就是可選的,否則只能選擇Use local gradle distribution。
混淆與簽名
請看我另一篇博客 Gradle插件用戶指南(譯) 3.4.3節和3.4.4節
構建多渠道包
動態替換AndroidManifest.xml中的文本
以友盟為例,是通過在AndroidManifest.xml中添加meta-data標簽來區分渠道:
<meta-data android:name="UMENG_CHANNEL" android:value="official" />
不同的value值對應不同的渠道。
android gradle plugin從0.13.0版本開始,productFlavor開始支持manifestPlaceHolder,我們使用這個就可以實現友盟的多渠道打包。
-
修改AndroidManifest.xml,添加placeHolder變量
<meta-data android:name="UMENG_CHANNEL" android:value="${channel_param}" />
</li> -
配置build.gradle文件
android { ... defaultConfig { ... manifestPlaceholders = [channel_param: "official"] }
productFlavors { channel1 { ... } ... channelN { ... } } productFlavors.all { flavor -> flavor.manifestPlaceholders = [channel_param: name] }
}</pre>
productFlavors.all是合并的寫法,也可以分開寫:
channel1 { manifestPlaceholder = [channel_param:name] }
</li> </ol>再進一步,國內的應用商店可以說數以百計,如果每個都在build.gradle文件里寫一個flavor,那么build.gradle文件就會變得冗長。
我們把渠道號寫到一個單獨的文件里channels.txt,內容如下:channel-360 channel-baidu
然后在build.gradle里定義函數flavors(),作用就是根據channels.txt里的內容動態創建productFlavor,然后在build.gradle中調用這個函數,優化后的結果是這樣:
android { ... defaultConfig { ... manifestPlaceholders = [channel_param: "official"] }
flavors()
}
def flavors() { def path = './channels.txt' //channels.txt的路徑 file(path).eachLine { line -> if(!line.startsWith("http://")) { //動態創建productFlavor android.productFlavors.create(line, { manifestPlaceholders = [channel_param: name] })
} }
}</pre>
在Android Studio中,點擊Sync Project with Gradle Files,就可以在Gradle窗口中看到相應的渠道構建任務了.
</span>
來自:http://rinvay.github.io/android/2015/04/09/Build-Android-with-Gradle/
-
-