如何在编译期处理AndroidStudio工程

1,037 阅读2分钟

前言

平时发release包时,我们通常需要对现有工程的java、assets、res、manifest等资源进行处理,例如修改java类、修改manifest、压缩图片资源等。那么如何做,才能在编译期就能解决这类问题。 目前实现方式有很多,例如依赖外部脚本,如python、c++、shell作为核心脚本文件,再通过编写gradle命令函数串起核心执行文件,但这首先需要解决编译期拦截的问题,例如java文件javac变成class文件,针对class文件进行修改。现介绍一种比较好的方式,就是编写AndroidStudio插件,让Android工程在编译期,做一些动态替换、修改、自动生成代码等相关的事

AndroidStudio中新建groovy工程

1)选择AndroidStudio工程

2)新建New Module ,创建groovy插件工程,选择任意类型,推荐Java or Kotlin Library

3)删除无用信息,main目录下新建groovy文件夹,用来保存插件代码,main目录下新建resources->META-INF->gradle-plugins->xxx.properties 注: 其中xxx.properties可以随意取名,但是最后使用时会使用该名称,例如定义com.donews.packnewpkgs.properties文件,使用则是apply plugin:'com.donews.packnewpkgs'

4)build.gradle文件中加入以下节点,固定写法

plugins {
    id 'groovy'
    id 'maven'
}
dependencies {
    implementation gradleApi()
    implementation localGroovy()
}

5)新建入口类xxxx.groovy,然后在properties文件中指定,该类必须继承org.gradle.api.Plugin ,类似运行当前类的Main函数

implementation-class=com.donews.script.groovy.MainPlugin

6)配置对外引入仓库,编写build.gradle文件,增加下面节点

uploadArchives {
    //groovy工程代码输出指定仓库
     repositories.mavenDeployer {
        repository(url: uri('../repositories'))//存放路径
        pom.groupId = "com.donews"//工程组的标识,一般为公司名称
        pom.artifactId = "packapkScript"//工程的标识,一般为项目名称
        pom.version = "0.0.1"//版本号
    }
}

7)运行upload-uploadArchives命令,生成本地插件仓库

8)根目录build.gradle配置dependencies节点,配置刚刚生成的插件

repositories {
        google()
        jcenter()
        //配置本地仓库
        maven{
            url uri('repositories')
        }
    }
dependencies {
        classpath "com.android.tools.build:gradle:4.1.2"
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath "com.donews:packapkScript:0.0.1"
    }

8)具体工程中使用自己编写的gradle插件

plugins {
    id 'com.android.application'
    id 'kotlin-android'
    //加入自己编写的插件,此处对应插件properties命名
    id 'com.donews.packapk'
}

以上为固定套路,编译plugin业务主要从继承的org.gradle.api.Plugin入口函数apply开始,常用编译期的业务一般有asm对字节码处理,apt生成更多的代码等等,下次实验会主要一方面查阅编译期回调Project对象的核心api,以及asm操作类库修改.class文件和其它一些常规实验