編輯:關於Android編程
一個Gradle項目的構建過程定義在build.gradle文件中,位於項目的根目錄下。
一個最簡單的Gradle純Java項目的build.gradle文件包含以下內容:
apply plugin: 'java'
這裡引入了Gradle的Java插件。這個插件提供了所有構建和測試Java應用程序所需要的東西。
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.11.1'
}
}
apply plugin: 'android'
android {
compileSdkVersion 19
buildToolsVersion 19.0.0
}
這裡包括了Android build file的3個主要部分:
上面提到的基本的構建文件需要一個默認的文件夾結構。Gradle遵循約定優先於配置的概念,在可能的情況盡可能提供合理的默認配置參數。
基本的項目開始於兩個名為“source sets”的組件,即main source code和test code。它們分別位於:
* src/main/
* src/androidTest/
裡面每一個存在的文件夾對應相應的源組件。
對於Java plugin和Android plugin來說,它們的Java源代碼和資源文件路徑如下:
* java/
* resources/
但對於Android plugin來說,它還擁有以下特有的文件和文件夾結構:
* AndroidManifest.xml
* res/
* assets/
* aidl/
* rs/
* jni/
注意:src/androidTest/AndroidManifest.xml是不需要的,它會自動被創建。
3.2.1 Configuring the Structure(配置項目結構)
當默認的項目結構不適用的時候,你可能需要去配置它。根據Gradle文檔,重新為Java項目配置sourceSets可以使用以下方法:
sourceSets {
main {
java {
srcDir 'src/java'
}
resources {
srcDir 'src/resources'
}
}
}
注意:srcDir將會被添加到指定的已存在的源文件夾中(這在Gradle文檔中沒有提到,但是實際上確實會這樣執行)。
sourceSets {
main.java.srcDirs = ['src/java']
main.resources.srcDirs = ['src/resources']
}
android {
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src']
resources.srcDirs = ['src']
aidl.srcDirs = ['src']
renderscript.srcDirs = ['src']
res.srcDirs = ['res']
assets.srcDirs = ['assets']
}
androidTest.setRoot('tests')
}
}
以上也是將舊構建系統項目遷移到新構建系統需要做的遷移工作。
添加一個插件到構建文件中將會自動創建一系列構建任務(build tasks)去執行(注:gradle屬於任務驅動型構建工具,它的構建過程是基於Task的)。Java plugin和Android plugin都會創建以下task:
* assemble:這個task將會組合項目的所有輸出。
* check:這個task將會執行所有檢查。
* build:這個task將會執行assemble和check兩個task的所有工作
* clean:這個task將會清空項目的輸出。
實際上assemble,check,build這三個task不做任何事情。它們只是一個Task標志,用來告訴android plugin添加實際需要執行的task去完成這些工作。
這就允許你去調用相同的task,而不需要考慮當前是什麼類型的項目,或者當前項目添加了什麼plugin。
例如,添加了findbugs plugin將會創建一個新的task並且讓check task依賴於這個新的task。當check task被調用的時候,這個新的task將會先被調用。
在命令行環境中,你可以執行以下命令來獲取更多高級別的task:
gradle tasks
gradle tasks --all
Java plugin主要創建了兩個task,依賴於main task(一個標識性的task):
* assemble
* jar:這個task創建所有輸出
* check
* test:這個task執行所有的測試。
jar task自身直接或者間接依賴於其他task:classes task將會被調用於編譯java源碼。
testClasses task用於編譯測試,但是它很少被調用,因為test task依賴於它(類似於classes task)。
通常情況下,你只需要調用到assemble和check,不需要其他task。
你可以在Gradle文檔中查看java plugin的全部task。
Android plugin使用相同的約定以兼容其他插件,並且附加了自己的標識性task,包括:
* assemble:這個task用於組合項目中的所有輸出。
* check:這個task用於執行所有檢查。
* connectedCheck:這個task將會在一個指定的設備或者模擬器上執行檢查,它們可以同時在所有連接的設備上執行。
* deviceCheck:通過APIs連接遠程設備來執行檢查,這是在CL服務器上使用的。
* build:這個task執行assemble和check的所有工作。
* clean:這個task清空項目的所有輸出。
這些新的標識性task是必須的,以保證能夠在沒有設備連接的情況下執行定期檢查。
注意build task不依賴於deviceCheck或者connectedCheck。
一個Android項目至少擁有兩個輸出:debug APK(調試版APK)和release APK(發布版APK)。每一個輸出都擁有自己的標識性task以便能夠單獨構建它們。
* assemble:
* assembleDebug
* assembleRelease
它們都依賴於其它一些tasks以完成構建一個APK需要多個步驟。其中assemble task依賴於這兩個task,所以執行assemble將會同時構建出兩個APK。
小提示:gradle在命令行終端上支持駱駝命名法的task簡稱,例如,執行gradle aR命令等同於執行gradle assembleRelease。
check task也擁有自己的依賴:
* check:
* lint
* connectedCheck:
* connectedAndroidTest
* connectedUiAutomatorTest(目前還沒有應用到)
* deviceCheck: 這個test依賴於test創建時,其它實現測試擴展點的插件。
最後,只要task能夠被安裝(那些要求簽名的task),android plugin就會為所有構建類型(debug,release,test)安裝或者卸載。
Android plugin提供了大量DSL用於直接從構建系統定制大部分事情。
通過SDL可以配置一下manifest選項:
* minSdkVersion
* targetSdkVersion
* versionName
* packageName
* package Name for the test application
* Instrumentation test runner
例如:
android {
compileSdkVersion 19
buildToolsVersion 19.0.0
defaultConfig {
versionCode 12
versionName 2.0
minSdkVersion 16
targetSdkVersion 16
}
}
def computeVersionName() {
...
}
android {
compileSdkVersion 19
buildToolsVersion 19.0.0
defaultConfig {
versionCode 12
versionName computeVersionName()
minSdkVersion 16
targetSdkVersion 16
}
}
如果一個屬性沒有使用DSL進行設置,一些默認的屬性值將會被使用。以下表格是可能使用到的值:
Property Name Default value in DSL object Default value versionCode -1 value from manifest if present versionName null value from manifest if present minSdkVersion -1 value from manifest if present targetSdkVersion -1 value from manifest if present packageName packageName value from manifest if present testPackageName null app package name + “.test” testInstrumentationRunner null android.test.InstrumentationTestRunner signingConfig null null proguardFile N/A (set only) N/A (set only) proguardFiles N/A (set only) N/A (set only)
如果你在構建腳本中使用自定義代碼邏輯請求這些屬性,那麼第二列的值將非常重要。例如,你可能會寫:
if (android.defaultConfig.testInstrumentationRunner == null) {
// assign a better default...
}
如果這個值一直保持null,那麼在構建執行期間將會實際替換成第三列的默認值。但是在DSL元素中並沒有包含這個默認值,所以,你無法查詢到這個值。
android {
buildTypes {
debug {
applicationIdSuffix .debug
}
jnidebug.initWith(buildTypes.debug)
jnidebug {
packageNameSuffix .jnidebug
jnidebugBuild true
}
}
}
以下是一些可能使用到的屬性和默認值:
Property name Default values for debug Default values for release / other debuggable debuggable false jniDebugBuild false false renderscriptDebugBuild false false renderscriptOptimLevel 3 3 packageNameSuffix null null versionNameSuffix null null signingConfig android.signingConfigs.debug null zipAlign false true runProguard false false proguardFile N/A (set only) N/A (set only) proguardFiles N/A (set only) N/A (set only)
src//
這意味著BuildType名稱不能是main或者androidTest(因為這兩個是由plugin強制實現的),並且他們互相之間都必須是唯一的。
android {
sourceSets.jnidebug.setRoot('foo/jnidebug')
}
android {
signingConfigs {
debug {
storeFile file(debug.keystore)
}
myConfig {
storeFile file(other.keystore)
storePassword android
keyAlias androiddebugkey
keyPassword android
}
}
buildTypes {
foo {
debuggable true
jniDebugBuild true
signingConfig signingConfigs.myConfig
}
}
}
以上代碼片段修改debug keystory的路徑到項目的根目錄下。在這個例子中,這將自動影響其他使用到debug構建類型的構建類型。
android {
buildTypes {
release {
runProguard true
proguardFile getDefaultProguardFile('proguard-android.txt')
}
}
productFlavors {
flavor1 {
}
flavor2 {
proguardFile 'some-other-rules.txt'
}
}
}
android 內存洩漏分析技巧
java虛擬機運行一般都有一個內存界限,超過這個界限,就會報outofmemory。這個時候一般都是存在內存洩漏。解決內存洩漏問題,竊以為分為兩個步驟:分析應用程序是否真
Android屏幕適配之布局設置(二)
書接上回,我們已經了解了一些關於適配的一些相關概念,接下來我們會了解一下,在設置布局時我們應該注意的地方。盡量不去設定具體的尺寸值。為了確保布局適應各種尺寸的屏幕,在保證
自定義View之MenuItemView
著手開發一款應用的時候,設置或者菜單頁面是可能需要的,但是,那重復的布局會很令人苦惱。新手可能會一項項的重復繪制,有經驗的你或許會用到include,或者用到組合控件。除
Android 異步消息處理機制(Handler 、 Looper 、MessageQueue)源碼解析
1、Handler的由來當程序第一次啟動的時候,Android會同時啟動一條主線程( Main Thread)來負責處理與UI相關的事件,我們叫做UI線程。Android