美文网首页
Android之Gradle<第六篇>:Android Grad

Android之Gradle<第六篇>:Android Grad

作者: NoBugException | 来源:发表于2020-09-26 23:41 被阅读0次

    我们需要知道所以Android插件,其实就是利用Gradle构建的插件。

    [Android Gradle 插件分类]

    (1)App插件: com.android.application
    (2)Library插件:com.android.library
    (3)Test插件:com.android.test

    [Android插件何依赖在哪里引用]

    (1)Android插件引用如何引用

    在Android项目根目录下的build.gradle下找到如下代码:

    buildscript {
    
        repositories { // 下载插件用到的仓库
            google() // 仓库1
            jcenter() // 仓库2
            customName() // 仓库3
        }
    
        dependencies { // 引用各种插件
            // android Gradle 插件引用
            classpath 'com.android.tools.build:gradle:3.6.3'
            // 其它插件
            classpath 'xxx.xxx.xxx:1.0.1'
        }
    }
    

    具体说明请看注释。

    (2)各Project下的依赖引用方式(这里的Project其实就是Module)

    每个Project中都存在独立的build.gradle文件,随便选择一个Project,贴下如下代码:

    dependencies {
        implementation fileTree(dir: 'libs', include: ['*.jar'])
    
        implementation 'androidx.appcompat:appcompat:1.2.0'
        implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
        testImplementation 'junit:junit:4.12'
        androidTestImplementation 'androidx.test.ext:junit:1.1.2'
        androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
    }
    

    dependencies函数下定义了一系列的依赖,这些依赖也是从仓库中下载的,那么,在Andoid工程中,除了要引用Android插件的远程仓库之外,还需要引用各Project引用依赖的远程仓库。

    在Android工程根目录下的build.gradle文件中,还存在这样的代码:

    allprojects {
        repositories {
            google()
            jcenter()
        }
    }
    

    allprojects函数下引用了所有Project依赖的仓库。

    [插件如何应用到某个Project中]

    在某个Project中的build.gradle文件下应用插件,代码如下:

    apply plugin: 'pluginID'
    

    [包名]

    通常情况下,应用的包名由applicationId指定,它在主Project的build.gradle文件下的
    defaultConfig函数中被定义,applicationId是ProjectFlavor的一个属性,如图:

    图片.png

    如果不设置applicationId,那么应用的包名由AndroidManifest.xml文件中manifest标签下的package字段来指定,如图:

    图片.png

    [签名]

    使用signingConfigs方法,完成签名配置,本文不做详细介绍。

    [构建的应用类型]

    应用的类型由buildTypes函数定义,默认情况下,有两种类型,分别是debugrelease,也就是说,即使没有buildTypes函数,Project也默认存在两种类型,当然,如果需要,还可以新增任意类型,如图新增了custom类型:

    图片.png 图片.png

    buildTypes常常和productFlavors一起使用,比如:

    图片.png 图片.png

    那么,在Build Variants中的显示就会变化,如图:

    图片.png

    productFlavors是Gradle非常重要的知识,当项目存在多个特性时,以前的做法是拉取其它分支,在某各固定的仓库分支中实现对应的特性,productFlavors的出现可以避免频繁的切换分支。
    productFlavors将在下一章单独讲解。

    在某类型中,可以使用如下属性:

    • applicationIdSuffix:applicationId的后缀;
    • debuggable:是否生成一个可供调试的apk;
    • jniDebuggable:是否生成一个可以调试jni的apk;
    • minifyEnabled:是否启动Proguard混淆;
    • multiDexEnabled:是否启动自动拆分多个Dex的功能;
    • proguardFile:Proguard混淆的配置文件(只能配置一个);
    • proguardFiles:Proguard混淆的配置文件(可以同时配置多个);
    • shrinkResources:是否自动清理未使用的资源,默认为false;
    • signingConfig:签名配置;

    [使用混淆]

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

    看如上代码,默认情况下,minifyEnabled的值是false,即不启用混淆,想要使用混淆,这个参数必须设置为true;
    其次,就是混淆文件了,可以使用proguardFile指定某个混淆文件,但只能指定一个文件;
    使用proguardFiles可以指定多个文件,如上代码指定了两个文件,分别是“getDefaultProguardFile('proguard-android-optimize.txt')”和“proguard-rules.pro”,后者在项目中就可以找到,前者在Android SDK目录,具体路径是:\tools\proguard\proguard-android-optimize.txt,这个目录下还有一个混淆文件proguard-android.txtproguard-android.txt是优化前的,proguard-android-optimize.txt是优化后的。

    [zipalign优化]

    zipalign是Android提供的一个整理优化apk的工具,它能提高系统和应用的运行效率,更快地读写apk中的资源,降低内存的使用,所以对于要帆布的App,在发布之前一定要使用zipalign进行优化,具体使用如下:

    图片.png

    在Android工程中,只需要将zipAlignEnabled 属性设置为true即可。

    [如何修改自动生成apk的名称]

    图片.png

    如图所示,Android工程默认打包的名称是app-debug.apk,这样的命名方式只能区分安装包是debug还是release,如果项目加入了多渠道打包的功能,举例如下:

    //多渠道
    productFlavors {
        xiaomi{
        }
        vivo{
        }
        oppo{
        }
    }
    

    显然,在多渠道打包的项目中,我们需要重新定制一个安装包的命名方式,这样才能区分安装包属于哪个渠道。

    代码如下:

    android.applicationVariants.all { variant ->
        variant.outputs.all {
            outputFileName = "${variant.name}_v${variant.versionName}.apk"
        }
    }
    

    最终生成apk的路径、名称见下图:

    图片.png

    [版本号的管理]

    通常情况下,Android项目的版本号是在主模块下的build.gradle中定义的,代码如下:

    defaultConfig {
        applicationId "com.example.m"
        minSdkVersion 19
        targetSdkVersion 29
        versionCode 1
        versionName "1.0.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
    

    versionCode:版本号
    versionName:版本名称

    对于用户而言,只有versionName可见,所以对用户而言,versionName就是版本号。

    随着项目业务的迭代,模块越来越多,导致很难找到主Module;在组件化架构的项目中,任何Module都可能是一个主Module,每个组件都会定义版本号,如果需要修改版本号,需要修改所有组件中的版本,并且版本号保持一致,这种情况下,将版本号统一管理是必要的。
    [方法一] 将版本号定义在根目录下的build.gradle文件中,添加一些列的版本信息

    ext {
        minSdkVersion = 19
        targetSdkVersion = 29
        compileSdkVersion = 29
        buildToolsVersion = "29.0.3"
        versionCode = 1
        versionName = "1.0"
    }
    

    这些属性已经成为了公共信息,可以直接被调用。

    在对应的Module中可以引用这些参数,代码如下:

    compileSdkVersion rootProject.ext.compileSdkVersion
    buildToolsVersion rootProject.ext.buildToolsVersion
    
    defaultConfig {
        applicationId "com.example.m"
        minSdkVersion rootProject.ext.minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion
        versionCode rootProject.ext.versionCode
        versionName rootProject.ext.versionName
    }
    

    [方法二] 将配置信息单独写在一个文件中

    在项目的根目录下,创建文件config.gradle,文件中的内容如下:

    ext {
        appMinSdkVersion = 19
        appTargetSdkVersion = 29
        appCompileSdkVersion = 29
        appBuildToolsVersion = "29.0.3"
        appVersionCode = 1
        appVersionName = "1.0"
    }
    

    在Module下引用这个文件

    apply from: '../config.gradle'
    

    在Module下使用:

    compileSdkVersion appCompileSdkVersion
    buildToolsVersion appBuildToolsVersion
    
    defaultConfig {
        applicationId "com.example.m"
        minSdkVersion appMinSdkVersion
        targetSdkVersion appTargetSdkVersion
        versionCode appVersionCode
        versionName appVersionName
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
    

    [如何隐藏签名信息]

    有时候,为了开发方便,我们会将App的打包签名会放在个人计算机本地,如果多人开发可能还会将签名放到项目中,其实这样是不对的。

    签名的信息是非常重要的,需要进行保密,所以采用的方案是:将release的签名放在服务器,将debug的签名放在项目中,并且服务器的签名信息必须保密,代码如下:

    android {
        compileSdkVersion 23
        buildToolsVersion "23.0.1"
    
        signingConfigs {
            def appStoreFile = System.getenv("STORE_FILE")
            def appStorePassword = System.getenv("STORE_PASSWORD")
            def appKeyAlias = System.getenv("KEY_ALIAS")
            def appKeyPassword = System.getenv("KEY_PASSWORD")
    
            //当不能从环境变量里获取签名信息的时候,就使用项目中自带的debug签名
            if(!appStoreFile||!appStorePassword||!appKeyAlias||!appKeyPassword){
                appStoreFile = "debug.keystore"
                appStorePassword = "android"
                appKeyAlias = "androiddebugkey"
                appKeyPassword = "android"
            }
            release {
                storeFile file(appStoreFile)
                storePassword appStorePassword
                keyAlias appKeyAlias
                keyPassword appKeyPassword
            }
        }
    }
    

    [动态配置AndroidManifest文件]

    在AndroidManifest中定义变量AMAP_KEY

    <meta-data
        android:name="com.amap.api.v2.apikey"
        android:value="${AMAP_KEY}" />
    

    然后在build.gradle中添加如下代码:

    buildTypes {
        debug {
            manifestPlaceholders.put("AMAP_KEY", "111111111111111111")
        }
        release {
            manifestPlaceholders.put("AMAP_KEY", "2222222222222222222")
        }
    }
    

    Android Gradle提供了manifestPlaceholders占位符,在打包的过程中,可以替换AndroidManifest中的变量。

    [自定义BuildConfig参数]

    项目打包之后,在build文件夹中会自动生成BuildConfig配置文件,如下:

    图片.png

    这些属性都是些项目中的获取的,所以我们可以使用那些属性,如下图:

    图片.png

    但是,如果可以动态的在BuildConfig文件中添加属性就更加灵活了,使用Android Gradle的buildConfigField字段可以动态的在BuildConfig中添加属性,代码如下:

    //多渠道
    productFlavors {
        xiaomi{
            buildConfigField 'String', 'URL', '"https://www.xiaomi.com"'
            buildConfigField 'String', 'USERNAME', '"xiaomi"'
        }
    
        vivo{
            buildConfigField 'String', 'URL', '"https://www.vivo.com"'
            buildConfigField 'String', 'USERNAME', '"vivo"'
        }
    
        oppo{
            buildConfigField 'String', 'URL', '"https://www.oppo.com"'
            buildConfigField 'String', 'USERNAME', '"oppo"'
        }
    }
    

    根据不同的Flavor,BuildConfig属性值也会不同,最新生成的BuildConfig属性如下(就拿xiaomi举例):

    图片.png

    [自定义resValue]

    在Android工程的res/values文件夹下定义了各种资源,然而Android Gradle可以做到动态自定资源,看下代码:

    productFlavors {
        xiaomi{
            resValue 'string', 'who', 'xiaomi'
        }
    
        vivo{
            resValue 'string', 'who', 'vivo'
        }
    
        oppo{
            resValue 'string', 'who', 'oppo'
        }
    }
    

    编译之后,我们可以在/build/generated/res/resValues/xiaomi/debug/values/gradleResValues.xml文件下找到对应的资源

    图片.png

    Android Gradle的resValue方法,后面传递三个参数,分别是:Type、Name、Value,正好与资源定义格式对应,根据类似的做法,resValue还可以定义其它类型的资源。

    [dex选项配置]

    dexOptions {
        incremental true // 是否启动dx的增量模式,默认为false。增量模式速度更快,但目前有很多限制,慎用
        javaMaxHeapSize '4g' // 执行dx命令时,分配的最大堆内存,主要是为了解决执行dx内存不够的问题
        jumboMode true // 是否开启jumbo模式,如果函数超过65535个,那么就需要强制开启jumbo模式才可以构建成功
        preDexLibraries true // 是否预执行dex Libraries库工程,开启后会大大提高增量构建的速度,但是会影响clean构建的速度,默认开启。如果使用dx的--multi-dex选项生成多个dex,需要设置为false
        threadCount 2 // 执行dx使用的线程数量
    }
    

    [函数突破65535个的解决方案]

    当Android工程中的函数总数超过65535个时,打包构建会失败,这时需要dex分包处理,解决方案如下:

    【第一步】 开启MultiDex

    图片.png

    【第二步】 Android 5.0只有一个Dex,为了兼容5.0,还需要做下一步处理

    集成MultiDexApplication

    import androidx.multidex.MultiDexApplication;
    
    public class MyApplication extends MultiDexApplication {
    
    
    }
    

    或者添加MultiDex.install(this);

    import androidx.multidex.MultiDex;
    
    public class MyApplication extends Application {
    
        @Override
        protected void attachBaseContext(Context base) {
            super.attachBaseContext(base);
            MultiDex.install(this);
        }
    
    }
    

    [本章完...]

    相关文章

      网友评论

          本文标题:Android之Gradle<第六篇>:Android Grad

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