Android Studio中gradle的一些玩法

零次冪發表於2017-02-10

前言

有一些人反映在github上下載的專案或者作為module匯入你的專案中,執行不起來。或者幾經折騰才勉強執行起來,不知道你有沒有這種感覺,如果你有這種困惑不妨繼續閱讀下文,相信本文能幫到你。我一直認為從github或者網上搜尋到自己需要的案例,下載下來並且能快速執行起來是作為一個Android開發者最基本的能力要求,可能挖的坑多了以後,已經懂得去處理了吧。只能說github上的專案除了一些專案本身提交不完整,實在是缺三拉四的,其餘百分之九十九點九都是可以正常執行的。在如何快速執行一個github的demo之前,先來講解下Android Studio中gradle的一些玩法。

Android Studio專案中兩種gradle檔案

1.根目錄的build.gradle

新建一個Android Studio專案,根目錄會自動生成一個build.gradle檔案,主要是配置一些外掛和預設的依賴類庫的倉庫。

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.2.3'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}複製程式碼

2.module中的根目錄的build.gradle

Android Studio這個IDE不同於eclipse,eclipse啟動開啟的是工作空間,一個工作空間下可以包括零個多個工程專案。而Android Studio則是單個工程專案啟動,一個工程專案中包括一個或多個module,其中有一個build.gradle檔案中頭部為apply plugin: 'com.android.application'標識的為應用程式module,其餘以apply plugin: 'com.android.library'標識為Android Library。在編譯的時候,所有module的build.gradle依賴的類庫都會合併為一個。

主程式的build.gradle檔案

apply plugin: 'com.android.application'//作為主程式的標識

android {
    compileSdkVersion 24//當前向前相容sdk的版本
    buildToolsVersion "24.0.3"//構建工具的版本
    defaultConfig {
        applicationId "com.dou361.demogradle"//應用程式的id,在市場上使用的包名
        minSdkVersion 15//最小sdk版本支援
        targetSdkVersion 24//目標sdk版本
        versionCode 1//應用程式版本號
        versionName "1.0"//應用程式版本名稱
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false//混淆是否開啟
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {//依賴外部的類庫
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:24.2.1'
    testCompile 'junit:junit:4.12'
}複製程式碼

sdk版本設定規則

minSdkVersion <= targetSdkVersion <= compileSdkVersion
minSdkVersion <= buildToolsVersion <= compileSdkVersion複製程式碼

Android Library中的build.gradle檔案

apply plugin: 'com.android.library'

android {
    compileSdkVersion 24
    buildToolsVersion "24.0.3"

    defaultConfig {
        minSdkVersion 15
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:24.2.1'
    testCompile 'junit:junit:4.12'
}複製程式碼

gradle的一些玩法

1.全域性變數的使用

不知道你有沒有注意到,在多個module的情況下,不同module的build.gradle檔案中有部分配置項類似,或者依賴的類庫,有部分是相同的,在維護上不是很方便,這個時候就可以考慮統一配置。在專案根目錄的build.gradle檔案中新增以下程式碼和android{}同級

ext {
    //全域性變數控制,可在module中的build.gradle檔案通過rootProject.ext.xxx開頭來使用
    compileSdkVersion = 24
    buildToolsVersion = '24.0.3'
    supportVersion = '24.2.1'
    //主程式版本
    targetSdkVersion = 24
    minSdkVersion = 15
    versionCode = 1
    versionName = "v1.0.0"
    //library版本
    jjdxm_minSdkVersion = 9
    jjdxm_versionCode = 1
    jjdxm_versionName = "v1.0.0"
    jjdxm_v4 = 'com.android.support:support-v4:'+supportVersion
    jjdxm_v7 = 'com.android.support:appcompat-v7:'+supportVersion
    jjdxm_design = 'com.android.support:design:'+supportVersion
    jjdxm_cardview = 'com.android.support:cardview:'+supportVersion
    jjdxm_recyclerview = 'com.android.support:recyclerview-v7:'+supportVersion
}複製程式碼

全域性變數控制,可在module中的build.gradle檔案通過rootProject.ext.xxx開頭來使用,在所有module的build.gradle檔案中配置以上變數,以後在維護專案的時候,只需要在根目錄這個檔案中修改對應的配置項即可是不是很簡單,可能當前你還覺得這樣配置很麻煩,在使用AS過程中相信大家都遇到過架包衝突的情況,例如主程式中依賴了com.android.support:appcompat-v7:23.3.0,而其他module中依賴com.android.support:appcompat-v7:24.2.1的版本,這個時候就會引起衝突,而通過上面的全域性配置,只需要在所有的module中配置上rootProject.ext.jjdxm_v7就都統一了不僅解決了衝突問題,而且可以隨意切換不同版本的v7類庫。

2.配置打包用的簽名

主要有接過分享或者授權登入功能的都應該知道,像微信或者微博的分享和授權登入提供sdk,只有在指定的簽名下才能生效,而我們平時開發都習慣使用預設的androidkeystore打包簽名,這個時候想要測試分享或者登入功能就需要手動去打包指定keystore的簽名。非常影響開發效率,這個時候可以通過配置gradle,根據release或者是debug打包指定的簽名。

專案根目錄新建一個簽名用到的密碼管理檔案signing.properties

signing.alias=dou361            #release
signing.password=dou361            #release
signing.jjdxm_alias=dou361        #debug
signing.jjdxm_password=dou361    #debug複製程式碼

在主程式build.gradle的apply plugin: 'com.android.application'下面新增

Properties props = new Properties()
props.load(new FileInputStream(file(rootProject.file("signing.properties"))))複製程式碼

在android{}節點裡面新增

signingConfigs {
    release {
        keyAlias props['signing.alias']
        keyPassword props['signing.password']
        storeFile file(rootProject.file("debug.keystore"))
        storePassword props['signing.password']
    }

    debug {
        keyAlias props['signing.jjdxm_alias']
        keyPassword props['signing.jjdxm_password']
        storeFile file(rootProject.file("debug.keystore"))
        storePassword props['signing.jjdxm_password']
    }
}
buildTypes {
    debug {
        signingConfig signingConfigs.debug
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }

    release {
        signingConfig signingConfigs.release
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}複製程式碼

最後所有檔案如下
根目錄build.gradle

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.2.3'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

ext {
    //全域性變數控制,可在module中的build.gradle檔案通過rootProject.ext.xxx開頭來使用
    compileSdkVersion = 24
    buildToolsVersion = '24.0.3'
    supportVersion = '24.2.1'
    //主程式版本
    targetSdkVersion = 24
    minSdkVersion = 15
    versionCode = 1
    versionName = "v1.0.0"
    //library版本
    jjdxm_minSdkVersion = 9
    jjdxm_versionCode = 1
    jjdxm_versionName = "v1.0.0"
    jjdxm_v4 = 'com.android.support:support-v4:'+supportVersion
    jjdxm_v7 = 'com.android.support:appcompat-v7:'+supportVersion
    jjdxm_design = 'com.android.support:design:'+supportVersion
    jjdxm_cardview = 'com.android.support:cardview:'+supportVersion
    jjdxm_recyclerview = 'com.android.support:recyclerview-v7:'+supportVersion
}

task clean(type: Delete) {
    delete rootProject.buildDir
}複製程式碼

主程式的build.gradle

apply plugin: 'com.android.application'

Properties props = new Properties()
props.load(new FileInputStream(file(rootProject.file("signing.properties"))))

android {
    signingConfigs {
        release {
            keyAlias props['signing.alias']
            keyPassword props['signing.password']
            storeFile file(rootProject.file("debug.keystore"))
            storePassword props['signing.password']
        }

        debug {
            keyAlias props['signing.jjdxm_alias']
            keyPassword props['signing.jjdxm_password']
            storeFile file(rootProject.file("debug.keystore"))
            storePassword props['signing.jjdxm_password']
        }
    }
    compileSdkVersion rootProject.ext.compileSdkVersion
    buildToolsVersion rootProject.ext.buildToolsVersion

    defaultConfig {
        applicationId "com.dou361.demogradle"
        minSdkVersion rootProject.ext.minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion
        versionCode rootProject.ext.versionCode
        versionName rootProject.ext.versionName
        multiDexEnabled true
        ndk {
            // 指定要ndk需要相容的架構(這樣其他依賴包裡mips,x86,armeabi,arm-v8之類的so會被過濾掉)
            abiFilters "armeabi-v7a", "armeabi"
        }
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        debug {
            signingConfig signingConfigs.debug
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }

        release {
            signingConfig signingConfigs.release
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

repositories { flatDir { dirs 'libs' } }

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    testCompile 'junit:junit:4.12'
    compile rootProject.ext.jjdxm_v7
    compile rootProject.ext.jjdxm_design
}複製程式碼

其他module的build.gradle

apply plugin: 'com.android.library'

android {
    compileSdkVersion rootProject.ext.compileSdkVersion
    buildToolsVersion rootProject.ext.buildToolsVersion

    defaultConfig {
        minSdkVersion rootProject.ext.jjdxm_minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion
        versionCode rootProject.ext.jjdxm_versionCode
        versionName rootProject.ext.jjdxm_versionName

        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    testCompile 'junit:junit:4.12'
    compile rootProject.ext.jjdxm_v7
    compile rootProject.ext.jjdxm_design
}複製程式碼

keystore密碼管理檔案signing.properties

signing.alias=dou361
signing.password=dou361
signing.jjdxm_alias=dou361
signing.jjdxm_password=dou361複製程式碼

github上專案下載執行

之所以先介紹gradle的一些配置,是因為一個AS專案的啟動基本上都是在根據gradle檔案裡面的配置去聯網同步內容下來的。先了解gradle的一些配置和具體的用法以後會比較容易理解。其中類庫內容同步失敗、架包衝突、sdk版本等問題都可能會導致專案執行不起來。所以從github上面下載下來的專案,不要著急立馬開啟專案,要是網路不好你會發現一隻卡在同步中的介面,這個是因為不同開發者環境不盡相同導致的。

既然開發環境不同,那就可以考慮修改為自己已有的環境,可以省去大部分聯網同步操作,在網路差的情況是很明智的一個舉動,主要有以下幾個步驟:

1.先修改根目錄的build.gradle配置

根目錄裡面無非就一個gradle版本的差異,修改為你當前已有的版本,例如下載的demo是

classpath 'com.android.tools.build:gradle:2.2.3'複製程式碼

版本號2.2.3,而你的環境只有2.1.0的,那就可以修改為

classpath 'com.android.tools.build:gradle:2.1.0'複製程式碼

版本跨越不大的情況下,可以採用以上做法,如果有部分方法不可用,則還是建議聯網下載,一勞永逸。

2.module目錄中的build.gradle配置

大部分module都會依賴到v4 v7等一些support家族的類庫,這個時候有兩種情況會導致出問題,一是module之間的v4包版本號不一致,二是v4版本你的環境沒有。
針對第一種情況,匯入別人的module到你的專案中經常會遇到,解決辦法是參考上面的配置全域性的依賴或者移除重複的;
針對第二種情況,開啟別人的專案經常會遇到,解決辦法是修為你環境已有的版本或者聯網同步下載。

修改完所有module的build.gradle檔案以後,這個時候在開啟專案,有個別不存在類庫會同步去下載,完成以後基本上都是可以執行起來的。

相關文章