用Gradle 構建你的android程序

Gradle 構建你的android程序

android gradle 的插件終於把混淆代碼的task集成進去了,加上最近,android studio 用的是gradle 來構建項目, 下定決心把android gralde 構建項目的用戶指南全部看完, 讓不會用gradle 的人也用gradle構建android項目,讓打包(注意,打包和構建是兩碼事)多版本android不再痛苦最後,題外話:珍惜生命,遠離ant....

Android Tools 主頁 ,大概是今年2月份發佈 adt21.1 的時候,忽然在主頁發現了New Build System 原來是可以用gradle 來構建android項目,至於gradle 是什麼(既然點擊進來看了應該都知道了吧然後,又看了一下RoadMap 那時候,還並不支持Proguard 打包,於是就沒看了

最近,android studio 發佈,終於gradle 0.4 也跟着出來了,於是,先把gradle 學了一遍,然後把Gradle Plugin User Guide 也認真閱讀了一下,根據我的個人體驗,如果你對gradle 毫無瞭解就去看Gradle Plugin User Guide 可能很多地方都一頭霧水,但是並不妨礙你用gradle 打包android 應用,只是,出現問題,你就可能很頭疼不過,本篇博文就是讓不會gradle 也能用上 gradle 打包android 程序,因爲,我也不懂gradle,所以,我把我碰到的問題的解決方案都一一列出

順便貼上官方爲什麼使用gradle 的理由

  • Domain Specific Language (DSL) to describe and manipulate the build logic

  • Build files are Groovy based and allow mixing of declarative elements through the DSL and using code to manipulate the DSL elements to provide custom logic.

  • Built-in dependency management through Maven and/or Ivy.

  • Very flexible. Allows using best practices but doesn’t force its own way of doing things.

  • Plugins can expose their own DSL and their own API for build files to use.

  • Good Tooling API allowing IDE integration

首先我們學習幾個gradle 的腳本語法,掌握了這幾個語法,你就能非常簡單的用gradle構建打包android項目了 首先,我們來看下一個最簡單androidbuild.gradle

build.gradle
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
	
buildscript {
       
	 repositories {
            mavenCentral()
        }

        dependencies {
            classpath 'com.android.tools.build:gradle:0.4'
        }
    }

    apply plugin: 'android'

    android {
        compileSdkVersion 17
    }

英語的介紹都來自與 gradle官方文檔, 主要後邊的中文不是翻譯,是補充介紹

buildscript{}

Configures the build script classpath for this project. 說白了就是設置腳本的運行環境

repositories{}

Returns a handler to create repositories which are used for retrieving dependencies and uploading artifacts produced by the project. 大意就是支持java 依賴庫管理(maven/ivy),用於項目的依賴。這也是gradle 強力的地方

dependencies{}

The dependency handler of this project. The returned dependency handler instance can be used for adding new dependencies. For accessing already declared dependencies, the configurations can be used. 依賴包的定義。支持maven/ivy,遠程,本地庫,也支持單文件,如果前面定義了repositories{}maven 庫,使用maven的依賴(我沒接觸過ivy)的時候只需要按照用類似於com.android.tools.build:gradle:0.4,gradle 就會自動的往遠程庫下載相應的依賴

apply plugin:

聲明構建的項目類型,這裏當然是android了

android{}

設置編譯android項目的參數,接下來,我們的構建android項目的所有配置都在這裏完成

首先,你要安裝Gradle 1.6 並且,寫進系統的環境變量裏面,所有的命令都是默認你已經配好了gradle 的環境。而且,已經已經升級了android sdk 22

要用gradle構建你的有兩種方式:(build.gradle 放到項目目錄下

  1. 利用adt 22導出 build.gradle.

  2. 複製別人寫好的build.gradle 文件.

  3. 根據gradle 規則,手寫android 的build.gradle 文件

個人推薦1,2 方法。。

一個android build.gradle 最基本基本文件

build.gradle
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
buildscript {

    repositories {
        mavenCentral()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:0.4'
    }
}

apply plugin: 'android'

dependencies {
}

android {

    compileSdkVersion 17
    buildToolsVersion "17"

    defaultConfig {
        minSdkVersion 8
        targetSdkVersion 17
    }
    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            resources.srcDirs = ['src']
            aidl.srcDirs = ['src']
            renderscript.srcDirs = ['src']
            res.srcDirs = ['res']
            assets.srcDirs = ['assets']
        }

        instrumentTest.setRoot('tests')
    }
}

接着在命令行cd 到項目目錄下

例如: cd e:\workplace\andoridGradle

如果你是第一次使用gradle 構建android項目建議你先使用gradle clean 把android gradle 插件,還有相關依賴包下載下來並且對環境進行初始化,如果出錯了,一般可能是下載超時,試多幾次即可,最後你會看到如下提示:BUILD SUCCESSFUL

The TaskContainer.add() method has been deprecated and is scheduled to be remove d in Gradle 2.0. Please use the create() method instead.

:clean UP-TO-DATE

BUILD SUCCESSFUL

Total time: 7.847 secs

完成以上的步驟,就可以正式使用gralde 構建你的android項目了

然後使用gradle build 就完成了android 項目的構建了如果,你是照着以上步驟走的話,你將會想項目目錄裏面看到一個build 的目錄,裏面就是用gradle 構建android項目的全部例如了,結構目錄看附錄

最終打包的apk 就在build/apk 目錄下了然後,你會發現,兩個apk 一個是 [項目名]-debug-unaligned [項目名]-release-unsigned

如果以上內容你都掌握的話,接下來就將詳細說說如何利用gralde 打包android apk

上面說了一大堆東西,其實並不吸引人去使用gradle,如果只是構建項目的話,adt不是更合適嗎?如果,你看完以下內容還是這麼覺得的話,你就沒必要折騰gradle了。。

看附錄 默認輸出 release apk 是沒有簽名的,那麼我們需要簽名的很簡單,只需要在android{}裏面補充加上加上即可完整build.gradle 請點擊我的gist

build.gradle
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
signingConfigs {
   myConfig{
     storeFile file("gradle.keystore")
    	storePassword "gradle"
    	keyAlias "gradle"
    	keyPassword "gradle"
    }
}
    
   buildTypes{
     release {
    	signingConfig  signingConfigs.myConfig
     } 
   }
 
然後,運行gradle cleangradle build ,這次在build/apk 你看到了多了一個[項目名]-release-unaligned, 從字面上面我就可以知道,這個只是沒有進行zipAlign 優化的版本而已而[項目名]-release 就是我們簽名,並且zipAlign 的apk包了. ###打混淆包### 只需要在原來的基礎上加上,完整的proguad.gradle 代碼
build.gradle
1
2
3
4
5
6
7
8
buildTypes{
   release {
   signingConfig  signingConfigs.myConfig
     runProguard true
     proguardFile 'proguard-android.txt'
   }
}


gradle clean

gradle build

現在來解釋一下上一節的問題,apk目錄下的兩個apk 的含義

爲什麼產生了兩個apk?

默認的android gralde 插件定義了兩種apk 的類型debug, release,這兩種類型的詳細對比看附錄

這個是android gralde 插件 buildTypes{} 方法產生的,默認配置好了兩個默認模板,當然你也可以修改,前面我們就是在修改默認的release 的配置,讓輸出release類型的的apk,具有簽名和混淆

對於多渠道包,android 插件提供了一個名爲Product Flavor{} 的配置,用於進行多渠道打包

例如,我的android應用有海外版,和國內版本,而且這兩個版本的包名是不一樣的!!(我就舉兩個市場的例子安裝這個思路,你要打包100個不同的市場只是幾行代碼的事情)。

你只需要在android{} 補充上

build.gradle
1
2
3
4
5
6
7
8
productFlavors {
	playstore {
			packageName='com.youxiachai.androidgradle.playstore'
	}
	hiapk {
			packageName='com.youxiachai.androidgradle.amazonappstore'
	}
}

然後gradle clean,gradle build,在build/apk 下面你會看到一堆的包,命名格式[項目名]-[渠道名]-release

僅此而已?

Product Flavor{} 不只是能改包名那麼簡單,還能夠對編譯的源碼目錄進行切換

什麼意思? 不知道各位有沒有用過友盟做用戶統計,如果,你用的是分發渠道分析,你需要修改AndroidManifest.xml 添加上 <meta-data android:value="hiapk" android:name="UMENG_CHANNEL"/>

如果,你很多渠道,,然後你就會很痛苦,現在用gradle 就非常舒服,你只需要在android.sourceSets指定我們的渠道名就行,android gradle 插件,會自動打包!!!例如

build.gradle
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
sourceSets {
    main {
        manifest.srcFile 'AndroidManifest.xml'
        java.srcDirs = ['src']
        resources.srcDirs = ['src']
        aidl.srcDirs = ['src']
        renderscript.srcDirs = ['src']
        res.srcDirs = ['res']
        assets.srcDirs = ['assets']
    }
        
    hiapk {
      	manifest.srcFile 'hiapk/AndroidManifest.xml'
    }    	
       	playstore {
       		manifest.srcFile 'hiapk/AndroidManifest.xml'
    }
       
	instrumentTest.setRoot('tests')
        
}
然後運行gradle clean,gradle build,省下的時間去喝杯咖啡,睡個覺什麼的都好 ###外部依賴### android gradle 對於外部jar 包的應用支持maven/ivy 管理的包,也支持指定具體文件,前面已經在上文說過上面演示的完整 build.gradle gist 裏面也有寫你需要加上如下代碼即可:
build.gradle
1
2
3
dependencies {
	compile files('libs/android-support-v4.jar')
}

至此,對於用android gradle 構建android應用程序,打包android 程序,所需要的所有知識,在以上已經說明,只要你是認真看上面文章的,對於,如何打依賴於android library project 的包,可以看附錄提供的那個德國人寫的例子,而對於build.gradle 裏面的代碼你需要把0.2, 改爲0.4即可。至於用gradle 運行android test case部分的教程,個人感覺寫了也白寫(我寫過關於andorid 測試相關的文章,也錄製過視頻,所以有這個感覺),估計不會有人關注,所以,如果你對用gradle 進行android test的話,可以看附錄裏面提供的官方gradle手冊

對於這部分內容,你讀與不讀,並不影響你使用gradle 打包android 項目至於讀了的好處就是你能夠更好的使用gradle。

  • 完整的Gradle Plugin User Guide 其中裏面有個錯誤是compile files('libs/android-support-v4.jar') 不是compile file('libs/android-support-v4.jar') 教程是基於android gradle0.3 ,在0.4中只是多了混淆打包,這塊已經在文中補充了。

  • 一個德國人寫的Android-Gradle-Examples

  • dependencies{}更多的介紹

  • debug, release,這兩種類型的默認配置如下:

    Property name Default values for debug Default values for release / other
    debuggable true false
    jniDebugBuild false false
    renderscriptDebugBuild false false
    renderscriptOptimLevel 3 3
    packageNameSuffix null null
    versionNameSuffix null null
    signingConfig android.signingConfigs.debug null
    zipAlign false true
  • defaultConfig {} 配置參數列表

    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 null value from manifest if present
    testPackageName null app package name + “.test”
    testInstrumentationRunner null android.test.InstrumentationTestRunner
    signingConfig null null
    runProguard false false
    proguardFile  'proguard-android.txt' or 'proguard-android-optimize.txt'  'proguard-android.txt' or 'proguard-android-optimize.txt'
  • build 結構目錄

    tree
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    
    build/
    ├── apk
    ├── assets
    │   ├── debug
    │   └── release
    ├── classes
    │   ├── debug
    │   │   └── com
    │   │       └── example
    │   │           └── gradle
    │   └── release
    │       └── com
    │           └── example
    │               └── gradle
    ├── dependency-cache
    │   ├── debug
    │   └── release
    ├── incremental
    │   ├── aidl
    │   │   ├── debug
    │   │   └── release
    │   ├── dex
    │   │   ├── debug
    │   │   └── release
    │   ├── mergeAssets
    │   │   ├── debug
    │   │   └── release
    │   └── mergeResources
    │       ├── debug
    │       └── release
    ├── libs
    ├── manifests
    │   ├── debug
    │   └── release
    ├── res
    │   ├── all
    │   │   ├── debug
    │   │   │   ├── drawable-hdpi
    │   │   │   ├── drawable-mdpi
    │   │   │   ├── drawable-xhdpi
    │   │   │   ├── drawable-xxhdpi
    │   │   │   ├── layout
    │   │   │   ├── menu
    │   │   │   ├── values
    │   │   │   ├── values-sw720dp-land
    │   │   │   ├── values-v11
    │   │   │   └── values-v14
    │   │   └── release
    │   │       ├── drawable-hdpi
    │   │       ├── drawable-mdpi
    │   │       ├── drawable-xhdpi
    │   │       ├── drawable-xxhdpi
    │   │       ├── layout
    │   │       ├── menu
    │   │       ├── values
    │   │       ├── values-sw720dp-land
    │   │       ├── values-v11
    │   │       └── values-v14
    │   └── rs
    │       ├── debug
    │       └── release
    ├── source
    │   ├── aidl
    │   │   ├── debug
    │   │   └── release
    │   ├── buildConfig
    │   │   ├── debug
    │   │   │   └── com
    │   │   │       └── example
    │   │   │           └── gradle
    │   │   └── release
    │   │       └── com
    │   │           └── example
    │   │               └── gradle
    │   ├── r
    │   │   ├── debug
    │   │   │   └── com
    │   │   │       └── example
    │   │   │           └── gradle
    │   │   └── release
    │   │       └── com
    │   │           └── example
    │   │               └── gradle
    │   └── rs
    │       ├── debug
    │       └── release
    └── symbols
        ├── debug
        └── release
    88 directories
    

吐槽一下。用ant腳本的(也許你沒有接觸過。)。在以前你用ant 腳本打包apk的時候需要打包不同包名,你需要用ant 讀取AndroidManifest.xml 然後又正則匹配替換裏面packagename 參數雖然描述得過程很簡單,你真去寫的時候你就蛋疼了(對於一個ant外行人來說,個人感覺ant的學習曲線太陡峭了,如果是兩年前的我,可能還寫得出這樣的ant腳本(當年費了很大的功夫學習了一個多星期),不過,因爲很少用到(後來知道maven了果斷放棄了ant,爲什麼不在android使用maven? 因爲,android 的maven 插件式非官方的,而且現在看來maven 的xml實在很複雜,看起來就頭疼))*

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章