登录

去注册

登录

注册

去登录

注册

每日一问 Gradle 构建过程中,我们可以做哪些事?

xiaoyang   3小时前   收藏

描述下Gradle 构建过程中的核心任务,以及我们能做哪些事干涉整个过程,例如:

第一类: 通过配置影响 task,例如:混淆,BuildConfig 等;
第二类:我们可以add一些 listener,插入一些 task 等;

对于第一类,回答我们可以配置什么,有何作用;

对于第二类,回答我们可以怎么干,有何使用场景;

4

抛砖引玉

构建过程

下面几步是从网上搜索到

  1. 使用aapt工具将res资源文件生成R.java文件
  2. 使用aidl工具将aidl文件生成对应java文件
  3. 使用javac命令编译工程源代码和上面两步生成的文件,生成class文件
  4. 通过dex工具将class文件和第三方jar包打成dex文件
  5. 用aapt工具将res下的资源文件编译成二进制文件,然后将其和上一步中的dex文件以及assets中的文件通过apkbuilder工具打包成apk文件
  6. 通过jarsigner对apk进行签名
  7. 利用zipalign工具对apk进行字节对齐优化操作

    可以配置什么

    比如下面这个配置
buildTypes {
        //正式
        release {
            buildConfigField "boolean", "IS_DEBUG", "false"
            buildConfigField "String", "BASE_URL", getUrl(2)
            //混淆
            minifyEnabled true
            //Zipalign优化
            zipAlignEnabled true
            // 移除无用的resource文件
            shrinkResources false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }

        //仿真
        pre {
            buildConfigField "boolean", "IS_DEBUG", "false"
            buildConfigField "String", "BASE_URL", getUrl(1)
            //混淆
            minifyEnabled false
            //Zipalign优化
            zipAlignEnabled true
            // 移除无用的resource文件
            shrinkResources false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }

        //测试
        debug {
            buildConfigField "boolean", "IS_DEBUG", "true"
            buildConfigField "String", "BASE_URL", getUrl(0)
            //混淆
            minifyEnabled false
            //Zipalign优化
            zipAlignEnabled true
            // 移除无用的resource文件
            shrinkResources false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

//读取项目中的url.properties配置文件
static String getUrl(int status) {
    File propFile = new File('url.properties')//这个文件不可写注释
    if (propFile.exists()) {
        Properties props = new Properties()
        props.load(new FileInputStream(propFile))
        switch (status) {
            case 0:
                return String.valueOf(props['TEST_URL'])  //测试
            case 1:
                return String.valueOf(props['PREVIEW_URL'])//仿真
            case 2:
                return String.valueOf(props['RELEASE_URL'])//线上
            default:
                return String.valueOf(props['RELEASE_URL'])//线上
        }
    }
    return 2//线上
}

url.properties中定义不同版本的url

//测试
TEST_URL="xxx"
//预览
PREVIEW_URL="xxx"
//线上
RELEASE_URL="xxx"

以前我们项目中区分是不是打线上的包,或者通过判断是不是debug版本来关闭log打印的功能,一般都是在一个常量类中保存,打包的时候改对应的地方,缺点有时候可能会忘记修改。使用上面的配置就可以不用修改自动打包成对应的包了。

  1. 通过第一个buildConfigField参数,可以控制是不是debug版本
  2. 第二个buildConfigField 可以获取对应版本的url的信息。url信息在url.properties文件中配置
  3. 后面还可以开启混淆,对齐操作和移除无用的资源文件来优化apk的大小,

可以怎么干

可以在第3步和第4步之间干点事情,就是编译时插桩。可以实现统计埋点,bug追踪等功能,比如今年微信开源的无反射插件化框架Shasow也用了这块的技术。

Google官方在Adnroid Gradle1.5.0版本提供了Transform API,允许第三方Plugin在打包dex文件之前的编译过程中操作.class文件

所以可以通过Transform API拿到class文件,然后通过ASM或者别的AOP框架,动态的在class文件中插入代码或者生成新的class文件。

回复
1

第一类

针对第一类,其实module中的build.gradle中很多配置可以影响到task,比如以下

  • buildTypes中debug/release中增加自定义buildConfig字段。会影响GenerateBuildConfig生成的BuildConfig文件内容
  • flavorDimensions和productFlavors的配置,影响AppPlugin生成的task列表

第二类

可以自定义Plugin,自定义Task,并依赖assembleRelease这个task,实现快速多渠道打包。比如:Walle

回复

删除留言

确认删除留言,会导致相关评论丢失?

取消 确定