博客主页

这篇主要讲Java Gradle插件、Android Gradle插件以及自定义插件等

Gradle插件

Gradle内置了很多插件,其中Android Gradle插件就是基于内置的Java插件实现的。

应用一个插件

插件的应用都是通过Projectapply方法完成的,而插件又分为二进制插件和脚本插件。

应用插件方法

二进制插件就是实现了org.gradle.api.Plugin接口的插件,可以有plugin id,如java插件。二进制插件一般都是打包在一个jar独立发布

// 'java'就是Java插件的plugin id,是唯一的
// 它对应得到类型是org.gradle.api.plugins.JavaPlugin
apply plugin: 'java'

// 也可以通过该类型应用这个插件,包org.gradle.api.plugins是默认导入的,可以去掉
apply plugin: JavaPlugin

应用脚本插件其实就是把这个脚本加载进来,与二进制插件不同的是,脚本插件使用from关键字,后面跟一个脚本文件,可以是本地的,也可以是网络,如果是网络要使用HTTP URL。
更重要的是,脚本文件是模块化的基础。

// 在build.gradle文件中引用脚本文件
apply from: 'config/project.config.gradle'

// project.config.gradle脚本文件
ext {
    // android sdk version
    // 使用如下:
    // def versions = rootProject.ext.versions
    // compileSdkVersion versions.compileSdkVersion
    // buildToolsVersion versions.buildToolsVersion
    versions = [
            compileSdkVersion: 26,
            minSdkVersion    : 19,
            targetSdkVersion : 26,
            versionCode      : 182,
            versionName      : '1.8.2',
    ]

    // dependencies
    // 使用如下:
    // def dependencies = rootProject.ext.dependencies
    // compile dependencies.support.design
    dependencies = [
            support     : [
                    appcompat : "com.android.support:appcompat-v7:26.1.0",
                    constraint: "com.android.support.constraint:constraint-layout:1.1.3",
                    design    : "com.android.support:design:26.1.0"
            ],
            gson        : "com.google.code.gson:gson:2.8.5"
    ]
}

Project中的apply有3个重载方法可以应用插件

void apply(Closure closure);
void apply(Action<? super ObjectConfigurationAction> action);
void apply(Map<String, ?> options);

应用第三方发布的插件

第三方发布的二进制插件,需要在buildscript {}中配置classpath才能使用,跟Gradle提供的内置插件不一样。而Android Gradle插件就是第三方插件,需要配置,如果不配置,就会提示找不到这个插件。

buildscript {
    repositories {
        jcenter()
    }

    dependencies {
        // 配置插件
        classpath 'com.android.tools.build:gradle:3.0.1'
    }
}

配置好第三方插件后,就可以应用插件了

apply plugin: 'com.android.application'
Grade社区提供了好多插件,可以在下面地址找到.
https://plugins.gradle.org/

自定义插件

我们可以根据自己的实际业务自定义一些插件,来辅助项目构建。

自定义插件需要实现Plugin接口,这个接口只有apply一个方法,该方法配置阶段调用,我们可以在该方法中创建任务,创建方法等。

仅自己项目使用自定义插件

如果自定义的插件只在自己的项目使用,可以简单的定义在build脚本文件里

// build.gradle文件中

// 应用自定义的插件
apply plugin: CustomPlugin

// 
class CustomPlugin implements Plugin<Project> {
    @Override
    void apply(Project project) {
        println "我是自定义插件."
        project.task('customPluginTask') {
            println "我是自定义任务.."
            doLast {
                println "这是一个通过自定义插件方式创建任务."
            }
        }
    }
}

或者新建buildSrc,目录结构如下:

只需要在build.gradle脚本中应用就OK了

// 注意包名需要加上
apply plugin: com.example.gradle.plugins.MyCustomPlugin

自定义插件供其他项目使用

但是如果想开发一个独立的插件供其他的项目使用,怎么做呢?这需要单独创建一个Groovy工程开发自定义插件:

首先按照下如图建立groovy目录后,自定义一个MyPlugin插件类,包名可以任意,如:com.custom.gradle.plugins

然后实现插件类,自定义插件MyPlugin,实现Plugin接口

package com.custom.gradle.plugins

import org.gradle.api.Plugin
import org.gradle.api.Project
// 自定义插件,需要实现Plugin接口
class MyPlugin implements Plugin<Project> {

    @Override
    void apply(Project project) {
        project.task('myCustomPluginTask') {
            doLast {
                println "这个在myPlugin中自定义插件的方式创建任务."
            }
        }
    }

}

而每个插件都有一个唯一的plugin id,需要我们自定义。
Gradle是通过META-INF里的properties文件来查找对应插件实现类的。
我这里定义的plugin id是com.custom.plugin.myplugin,然后在src/main/resources/META-INF/gradle-plugins/目录中新建一个名字为plugin id的properties文件,如com.custom.plugin.myplugin.properties,文件内容如下:

// key为implementation-class,value就是自定义的插件实现类
implementation-class=com.custom.gradle.plugins.MyPlugin

在build.gradle文件中配置自定义插件所需的依赖:

// 应用groovy插件
apply plugin: 'groovy'

dependencies {
    implementation gradleApi()
    implementation localGroovy()
    compileOnly 'com.android.tools.build:gradle:3.4.2'
}

repositories {
    mavenCentral()
}

sourceSets {
    main {
        groovy {
            srcDir 'src/main/groovy'
        }

        resources {
            srcDir 'src/main/resources'
        }
    }
}

打包到本地的Maven仓库

打包到本地的Maven仓库(仅仅为了测试自定义插件),最终打包上传到远程Maven仓库

// 应用maven插件
apply plugin: 'maven'

//配置分组group和版本version
group = 'com.custom.plugin'
version = '1.0.1'

uploadArchives {
    repositories {
        mavenDeployer {
            //提交到远程服务器:
            // repository(url: "http://www.xxx.com/repos") {
            //    authentication(userName: "admin", password: "admin")
            // }
            //本地的Maven地址设置为D:/repos
            repository(url: uri('D:/repos'))
        }
    }
}

执行gradlew uploadArchives命令后,就是上传到本地的repos仓库,如下图所示:

其他项目使用自定义插件

在Root Project中的build.gradle文件中配置

buildscript {
    repositories {
        maven { // 配置自定义插件本地Maven仓库地址
            url uri('D:/repos')
        }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.4.2'
        // 配置自定义的插件 group:com.custom.plugin, name:myPlugin,version:1.0.1
        // 简写格式:  group:name:version
        classpath 'com.custom.plugin:myPlugin:1.0.1'

       // 标准的写法,上面简写格式,使用 冒号 分隔group,name,version
       // classpath group: 'com.custom.plugin', name: 'myPlugin', version: '1.0.2'
    }
}

在Sub Project中build.gradle文件中应用plugin id

// com.custom.plugin.myplugin是plugin id
// plugin id为resources/META-INF/gradle-plugins/com.custom.plugin.myplugin.properties文件名
apply plugin: 'com.custom.plugin.myplugin'

Android Gradle插件

Android插件就是Gradle的一个第三方插件,基于Gradle构建的。

Android Gradle插件根据Android工程属性分3类:

  1. App应用工程,可生成一个APK应用,插件id: com.android.application
  2. Library库工程,可生成AAR包,包含资源信息,插件id: com.android.library
  3. Test测试工程,插件id: com.android.test

应用Android Gradle插件

Android Gradle是托管在jcenter上,在根工程的build.gradle中要先配置依赖classpath

// 根工程build.gradle
buildscript {
    repositories {
        jcenter()
    }

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

配置好后,在子工程的build.gradle就可以应用插件了,其实android {}是Android插件提供的一个扩展类型。

// 子工程build.gradle
apply plugin: 'com.android.application'

android {
  compileSdkVersion 23
}

Android Gradle工程

Android Gradle插件继承Java插件,需要在settings.gradle中配置子工程。

Android Gradle工程的配置,都是在android {},这是唯一的一个入口。可以对Android Gradle工程自定义配置,它的具体实现是com.android.build.gradle.AppExtension,是Project的一个扩展。

compileSdkVersion

配置Android SDK的版本,该配置的原型是:

public void compileSdkVersion(int apiLevel) {
   compileSdkVersion("android-" + apiLevel);
}

除了上面方法外,还提供了set方法,可以当做android的一个属性使用

android.compileSdkVersion = 23

buildToolsVersion

buildToolsVersion "23.0.1" 表示Android构建工具版本。可以直接通过 buildToolsVersion 方法赋值,也可以通过android.buildToolsVersion 这个属性赋值。

defaultConfig

defaultConfig是默认的配置,它是一个ProductFlavor。ProductFlavor允许根据不同的情况生成多个不同的APK包,比如多渠道打包。如果不针对自定义的ProductFlavor单独配置,会为这个ProductFlavor使用默认的defaultConfig配置。

android{
   defaultConfig {
        // 是一个属性,指定包名,没有指定从AndroidManifest.xml文件中读取
        applicationId "com.kerwin"
        // 是一个方法,配置最低支持的Android系统版本
        minSdkVersion 19
        // 是一个方法,配置基于哪个Android版本开发,没有配置从AndroidManifest.xml文件中读取
        targetSdkVersion 26
        // 是一个属性,配置App应用的内部版本号,一般控制App升级,建议配置
        versionCode 100
        // 是一个属性,配置App应用的版本名称,可查看App是哪一个版本,外部使用
        versionName "1.0.0"

       //是一个属性,默认是:applicationId  + ".test"
       testApplicationId "com.kerwin.test"
       // 配置单元测试时使用的Runner,默认:android.test.InstrumentationTestRunner
       testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
  }
}

buildTypes

buildTypes是一个NamedDomainObjectContainer类型,是一个域对象。可以在buildTypes {} 中增加多个需要构建的类型,如:release,debug
release就是Gradle自动创建的一个对应的BuildType

buildTypes {
    release {
         // 是否为该构建类型启用混淆,true:启用
         minifyEnabled true
         // 当启动混淆时,所使用的proguard的配置文件,proguardFiles 接受可变参数
         // getDefaultProguardFile方法 获取Android SDK目录下默认的配置文件
         // 路径:android-sdk\tools\proguard\proguard-android.txt
         proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard/proguard-rules.pro'
   }
}

signingConfigs配置签名信息

配置签名信息,对生成的APK签名。

  android{
       // 是一个方法,其类型NamedDomainObjectContainer,debug 和 release 定义的是一个SigningConfig
       // 一个SigningConfig就是一个签名配置
       signingConfigs {
            def signingConfig = rootProject.ext.signingConfigs
            def debugSigningConfig = signingConfig.debug
            // debug配置,一般debug模式是已经配置好的。debug证书位于:${HOME}\.android\debug.keystore
            debug {
                // 签名文件
                storeFile file(debugSigningConfig.storeFile)
                // 签名证书文件密码
                storePassword debugSigningConfig.storePassword
                // 签名证书中密钥别名
                keyAlias debugSigningConfig.keyAlias
                // 签名证书中密钥的密码
                keyPassword debugSigningConfig.keyPassword
            }

            // release 配置
            release {
                storeFile file(jenkinsProperties['KEY_STORE'])
                storePassword jenkinsProperties['KEY_STOREPWD']
                keyAlias jenkinsProperties['KEY_ALIAS']
                keyPassword jenkinsProperties['KEY_ALIASPWD']
            }
        }
  }

可以在defaultConfig中默认的签名配置,也可以在构建类型分别配置签名信息。

android {
   buildTypes {
       release {
           // signingConfigs是Android对象实例的一个属性,对应是getSigningConfigs(),release是创建的签名配置名称
           signingConfig signingConfigs.release
       }
      
       debug {
           signingConfig signingConfigs.debug
       }
   }
}

buildTypes构建类型

buildTypes也是Android的一个方法,接受参数是域对象NamedDomainObjectContainer,每添加一个都是BuildType类型,如debug

android {
   buildTypes {
       debug {
           // 是一个属性,配置基于applicationId 的后缀。配置后,debug版本包名为applicationId.debug
           applicationIdSuffix ".debug"
           // 是一个属性,配置是否生成一个可供调试的apk
           debuggable true
           // 是一个属性,配置是否生成一个可供调试JNI代码的apk
           jniDebuggable true
           // 是一个属性,是否开启混淆
           minifyEnabled true
           // 是一个属性,是否启用自动拆分多个dex的功能
           multiDexEnabled true
           // 是一个属性,配置签名配置
           signingConfig signingConfigs.release
           // 是一个方法,配置多个混淆文件
           proguardFiles getDefaultProguardFile('proguard-android.txt'),
                        'proguard/proguard-rules.pro'
           // 是一个属性,配置是否自动清理未使用的资源,默认false
           shrinkResources true
           // 是一个属性,zipalign是Android提供的一个整理优化apk文件工具。
           // 可以提高应用运行效率,更快读写apk中资源,降低内存使用
           zipAlignEnabled true
       }
   }
}

如果我的文章对您有帮助,不妨点个赞鼓励一下(^_^)


小兵兵同学
56 声望23 粉丝

Android技术分享平台,每个工作日都有优质技术文章分享。从技术角度,分享生活工作的点滴。