每次吃一點Androidのbuild.gradle詳細配置說明

目錄:
1、build.gradle(app)實例說明
2、對照說明
--2.1. apply plugin
--2.2. manifestPlaceholders
--2.3. dataBinding
--2.4. sourceSets
--2.5. productFlavors
--2.6. applicationVariants.all
--2.7. aapt重疊包配置
3、打印配置信息
4、此外【自定義config.gradle】
5、參考資料

Android小仙

1. build.gradle(app)實例說明

apply plugin: 'com.android.application'  // 使用android app插件

android {
    compileSdkVersion 22 // 編譯的SDK版本
    buildToolsVersion "25.0.0" // 編譯工具的版本
    // 默認的基本配置
    defaultConfig {
        applicationId "com.conquer.elspet.conqueryo" // 應用的包名
        minSdkVersion 15 // 支持的SDK最低版本
        targetSdkVersion 22 // 目標SDK版本
        versionCode 1 // 版本號
        versionName "1.0" // 版本名稱

        // manifestPlaceholders可以替換AndroidManifest中的標簽
        // 也可以放在buildTypes中對調試和發布做不同的配置
        manifestPlaceholders = [CHANNEL_ID: "_test"] 
    }
    // 調試/打包的簽名配置
    // 重要:::signingConfigs一定要放在調用之前,也就是要在buildTypes之前定義好
    signingConfigs {
        debug {
        // 可以跟release配置一樣,這樣調試微信登錄這樣的就可以直接調試測試了
        }
        release {
            storePassword 'conqueryo'
            storeFile file('../keystore/conquer.keystore')
            keyPassword 'conqueryo'
            keyAlias 'conquer'
        }
    }
    // 設置重疊包機制,實現資源合并,謹慎使用,如果有圖片有問題會報錯
    // 若出錯,可設置:
    // aaptOptions.cruncherEnabled = false;
    // aaptOptions.useNewCruncher = false;
    aaptOptions {
        additionalParameters '-S',
                '/ConquerYoFolder/ConquerYo/app/src/main/res2',
                '-S',
                '/ConquerYoFolder/ConquerYo/app/src/main/res3',
                '--auto-add-overlay'
        noCompress 'foo', 'bar'
        ignoreAssetsPattern '!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~'
    }

    // 發布和調試時的配置
    buildTypes {
        debug {
            debuggable true
            minifyEnabled false
            signingConfig signingConfigs.release
            //  signingConfig signingConfigs.debug
        }
        release {
            debuggable false
            minifyEnabled false
            shrinkResources false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.release
        }
    }
    // 關閉DataBinding功能
    dataBinding {
        enabled = false
    }
    sourceSets {
        main {
            jniLibs.srcDir 'libs'
        }
    }
    productFlavors {
        _test {}
        qh360 {}
        baidu {}
        yingyongbao {}
        wandj {}
        xiaomi {}
    }

    productFlavors.all { flavor ->
        flavor.manifestPlaceholders = [CHANNEL_ID: name]
    }

    //給生成的apk文件重命名,
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            def outputFile = output.outputFile
            if (outputFile != null && outputFile.name.endsWith('.apk')) {
                def fileName = outputFile.name.replace(".apk", "-${defaultConfig.versionName}.apk")
                output.outputFile = new File(outputFile.parent, fileName)
            }
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile project(':emojicon')
    compile project(':jRecyclerView')
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:22.+'
    compile 'com.android.support:design:22+'
    compile 'com.android.support:cardview-v7:22.+'
    compile 'com.android.support:support-v4:22.+'
    compile 'com.jakewharton:butterknife:7.0.1'
    compile 'com.squareup.okhttp3:okhttp:3.2.0'
    compile 'com.google.code.gson:gson:2.6.2'
    compile 'com.squareup.retrofit2:retrofit:2.0.0-beta4'
    compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4'
    compile 'jp.wasabeef:glide-transformations:2.0.0'
    compile 'com.yqritc:recyclerview-flexibledivider:1.2.9'
    compile 'com.nineoldandroids:library:2.4.0'
    compile 'com.qiniu:qiniu-android-sdk:7.1.0'
    compile 'pl.droidsonroids.gif:android-gif-drawable:1.1.+'
    compile 'org.greenrobot:eventbus:3.0.0'
}

2. 配置說明

2.1. apply plugin

聲明該module中使用的插件。那么有哪些插件可以使用???

比較常見的插件:

  • com.android.application :安卓應用插件
  • com.android.library:安卓庫插件,注意不能與安卓應用插件同時使用

其他插件:

  • me.tatarka.retrolambda:使用Lambda表達式的插件
  • android-apt:處理注釋的插件工具
    我們在使用ButterKnife做依賴注入的時候,就需要使用到處理注釋的插件工具:com.neenbedankt.android-apt
  • 其他還沒發現或使用到,后續補充------

2.2. manifestPlaceholders

manifestPlaceholders 可以用來替換androidmanifest文件中的標簽,可作為快速渠道打包替換渠道名的一種方式,也可以自定義標簽用來替換需要的文本,多作為不同環境不同key的修改。
我們在使用第三方SDK的時候,常常有區分debug_key和release_key,測試的時候用debug_key,發布的時候用release_key,抓狂的是每次測試跟發布狀態切換的時候常常忘記切換這兩個配置,導致出錯。有了manifestPlaceholders,就不用再為這等小問題煩惱了。
以前:
*** 【AndroidManifest: 】***

<!-- 融云 -->
        <!-- 開發環境  -->
        <meta-data
            android:name="RONG_CLOUD_APP_KEY"
            android:value="vnrofffffffuzo" /> 
        <!-- 測試環境   然后轉測試的時候將上段注釋,下段解掉注釋-->
        <!--<meta-data
            android:name="RONG_CLOUD_APP_KEY"
            android:value="k51hfffffff1bh5b" /> -->

現在:【一勞永逸,不用再注釋來注釋去了~~~】
*** 【AndroidManifest: 】***

<!-- 融云 -->
        <meta-data
            android:name="RONG_CLOUD_APP_KEY"
            android:value="${rong_cloud_app_key}" />

*** 【build.gradle(app): 】***

    buildTypes {
        debug {
            manifestPlaceholders = [rong_cloud_app_key  : "k51hfffffff1bh5b"]
        }
        release {
            manifestPlaceholders = [rong_cloud_app_key  : "vnrofffffffuzo"]
        }
    }

2.3. dataBinding

DataBinding是谷歌于15年推出的數據綁定框架。取代findViewById(),解耦。
使用說明:
2.3.1. build.gradle中的配置

android {
    ....
    dataBinding {
        enabled = true
    }
}

2.3.2. 數據實體類User:

package com.conquer.elspet.conqueryo.mvp.model.entity;

/**
 * User Entity
 */
public class User {
    private String name;
    private String sex;

    public User(String name, String sex) {
        this.name = name; // 名字
        this.sex= sex; // 性別
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setSex(String sex) {
        this.sex= sex;
    }

    public String getName() {
        return this.name;
    }

    public String getSex() {
        return this.sex;
    }
}

2.3.3. layout中:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>
        <variable
            name="user"
            type="com.conquer.elspet.conqueryo.mvp.model.entity.User" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.name}" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.sex}" />
    </LinearLayout>
</layout>

2.3.4. 在Activity中

public class UserInfoActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_user_info);
        User user = new User("LisaTheCat", "female");
        binding.setUser(user);
    }
}

參考資料:Android數據綁定框架DataBinding,堪稱解決界面邏輯的黑科技

2.4. sourceSets

資源目錄指向配置,可以指定哪些源文件(或文件夾下的源文件)要被編譯,哪些源文件要被排除。手動配置項目的目錄結構

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']
            jniLibs.srcDirs = ['libs']
        }
    }
}

2.5. productFlavors

利用productFlavors可以定義不同產品(apk)的特性,不同的產品可以定義不同的包名、使用不同的資源庫、使用不同的代碼、不同的渠道號、不同的資源文件等等。

    productFlavors{
        // 產品A(名字為:productA)
        productA{
            // 配置產品A獨立的包名,獨立的版本號,渠道名
            applicationId "com.crazyman.product.a"
            versionName "version-a-1.0"
            manifestPlaceholders.put("UMENG_CHANNEL_VALUE", "productA")
        }
        // 產品B(名字為:productB)
        productB{
            // 配置產品B獨立的包名,獨立的版本號,渠道名
            applicationId "com.crazyman.product.b"
            versionName "version-b-1.0"
            manifestPlaceholders.put("UMENG_CHANNEL_VALUE", "productB")
        }
    }

2.6. applicationVariants.all

applicationVariants.all:應用插件的所有變量
libraryVariants:庫插件的所有變量
testVariants:適用庫插件和應用插件的所有變量
可以做一些配置。比如下面一段配置就是設置打包apk的apk名稱:

//給生成的apk文件重命名,
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            def outputFile = output.outputFile
            if (outputFile != null && outputFile.name.endsWith('.apk')) {
                def fileName = outputFile.name.replace(".apk", "-${defaultConfig.versionName}.apk")
                output.outputFile = new File(outputFile.parent, fileName)
            }
        }
    }

假設在不配置的情況下打包出來的apk文件為:app-debug.apk,那么加上該配置后改為:app-debug-1.0.apk
假設我們還增加了不同產品的配置:

    productFlavors {
        baidu {}
        xiaomi{}
    }

那么到時候我們打包出來的就是:
app-baidu-debug-1.0.apk
app-xiaomi-debug-1.0.apk

2.7. aapt重疊包配置

aaptOptions可以對項目中相同資源進行合并。
在工程目錄的main文件夾下新建兩個文件res2/values/stringsres3/values/strings,如下圖:


res2/values/strings.xml文件里面:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="aapt_test_string">aapt_test_string_in_res2</string>
</resources>

res3/values/strings.xml文件里面:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="aapt_test_string">aapt_test_string_in_res3</string>
</resources>

然后在Activity中使用,例如點擊Button,顯示SnackBar:

Snackbar.make(button, getResources().getString(R.string.aapt_test_string), Snackbar.LENGTH_LONG)
                    .setAction("Action", null).show();

然后報錯了,額呵呵O(∩_∩)O~!!!


該aaptOptions出場了,在build.gradle(app)中添加:

    aaptOptions {
        additionalParameters '-S',
                '/ConquerYoFolder/ConquerYo/app/src/main/res2',
                '-S',
                '/ConquerYoFolder/ConquerYo/app/src/main/res3',
                '--auto-add-overlay'
        noCompress 'foo', 'bar'  // foo和bar相當于現實當中的無名氏,常被作為偽變量使用
        ignoreAssetsPattern '!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~'
    }

上述代碼配置意在將res3合并到res2中,res3會被覆蓋掉,最后點擊button,SnackBar顯示的是:aapt_test_string_in_res2,假設將這配置中的res2跟res3的位置替換一下,那么顯示的將變成:aapt_test_string_in_res3
再進一步:在build.gradle(app)中繼續添加:

    android.sourceSets {
               main.res.srcDirs = ['src/main/res', 'src/main/res3']
    }

aaptOptions的配置依舊同上,這個時候再點擊button時,顯示的就不是aapt_test_string_in_res2了,因為res3已經優先跟res合并了。
然而,我遇到了另一個不明之處:
我在布局文件中引用了aapt_test_string,索引不到該字符串:


<a>前提:</a>【沒有配置:main.res.srcDirs = ['src/main/res', 'src/main/res3']
運行可以運行,內容也可以展示,但是點擊原來那個button,卻沒有顯示SnackBar的內容了。如有知道的伙伴,求指教!!!
參考資料:編譯時替換資源 - Android重疊包與資源合并一見

3. 打印配置信息

比如有這樣一個meta-data:

 <meta-data
            android:name="RONG_CLOUD_APP_KEY"
            android:value="${rong_cloud_app_key}" />

我們可以在程序入口打印日志來統覽所有配置信息,下面是打印其中一個配置:

String rongyun_appkey;
        try {
            ApplicationInfo appInfo = getPackageManager()
                    .getApplicationInfo(getPackageName(),
                            PackageManager.GET_META_DATA);

            rongyun_appkey= appInfo.metaData.getString("RONG_CLOUD_APP_KEY");

            Logger.d("rongyun_appkey=" + rongyun_appkey);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }

4. 此外【自定義config.gradle】

如果項目中涉及的module比較多,每個Module都需要做build.gradle的配置,牽一發而動全身,假設有個第三方庫的版本要修改,可能要到每個build.gradle文件中做修改。這個時候我們可以通過在根目錄下自定義一個配置文件,假設命名為:config.gradle,然后在里面做一些配置,讓其他每個模塊的build.gradle都來引用這里面的配置就好了。
config.gradle

ext {
    android = [compileSdkVersion       : 25,
               buildToolsVersion       : "25.0.2",
               minSdkVersion           : 15,
               targetSdkVersion        : 25,
               versionCode             : 1,
               versionName             : "1.0.1",
               androidSupportSdkVersion: "25.1.1",
               retrofitSdkVersion      : "2.1.0",
    ]
    dependencies = [
            "support-v4"               : "com.android.support:support-v4:${android["androidSupportSdkVersion"]}",
            "cardview-v7"              : "com.android.support:cardview-v7:${android["androidSupportSdkVersion"]}",
            "retrofit"                 : "com.squareup.retrofit2:retrofit:${android["retrofitSdkVersion"]}",
            "gson"                     : "com.google.code.gson:gson:2.7",
    ]
}

如上,本配置文件中引用,dependencies引用android:${android["引用的標簽名"]}
build.gradle(app)

android {
        // 編譯的SDK版本:
       compileSdkVersion rootProject.ext.android["compileSdkVersion"]
}

如上,子module的build.gradle中引用,rootProject.ext.android["引用的標簽名"]

5. 參考資料

Android Gradle manifestPlaceholders 的妙用
Gradle for Android 第一篇( 從 Gradle 和 AS 開始 )【詳細說明了哦~~~】

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,466評論 25 708
  • 1.介紹 如果你正在查閱build.gradle文件的所有可選項,請點擊這里進行查閱:DSL參考 1.1新構建系統...
    Chuckiefan閱讀 12,179評論 8 72
  • 這一章主要針對項目中可以用到的一些實用功能來介紹Android Gradle,比如如何隱藏我們的證書文件,降低風險...
    acc8226閱讀 7,694評論 3 25
  • 轉至:http://blog.csdn.net/heqiangflytosky/article/details/5...
    kkgo閱讀 2,933評論 0 1
  • 我們手牽手 雪中漫步 幻想就這樣白了頭 歌廳盡嚎 我們嚎的好漢歌 斷斷續續 因為我好開心 一直笑 而你在笑我 商鋪...
    羅若閱讀 205評論 1 3