美文网首页程序员Android知识Studio
每次吃一点Androidのbuild.gradle详细配置说明

每次吃一点Androidのbuild.gradle详细配置说明

作者: 耑意儿 | 来源:发表于2017-04-20 15:21 被阅读1081次
    目录:
    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のbuild.gradle详细配置说明

        本文链接:https://www.haomeiwen.com/subject/xpikzttx.html