Gradle for Android学习笔记(二)

Gradle for Android学习笔记(二)

Gradle之管理多个Module编译

在一个工程项目中,我们可能会有多个Module,如:多个app,library。

我们来看下一个最简单的多个Module的build文件结构。

image

如果我们的app项目中依赖多个lib,这样在项目中显示的会有点乱,我们可以通过一个目录管理它们,如:

image

1.在setting.gradle文件中:

include ':app',':libraries:library1',':libraries:library2'

2.在app项目的build.gradle文件中:

dependencies{
    compile project(':libraries:library1')
}
Integrating Android Wear(整合穿戴设备)

如果你的app项目需要支持可穿戴设备,你可能需要在项目中添加一个Android Wear module。

在Android Wear项目中的build.gradle文件中

dependencies{
     compile fileTree(dir: 'libs', include: ['*.jar'])    
     compile 'com.google.android.support:wearable:1.1.0'    
     compile 'com.google.android.gms:play-services-wearable:6.5.87' 
}


在app项目中的build.gradle文件中

dependencies{
    wearApp project(":wear")    //wear是Android Wear项目的名称
}

这个wearApp的配置确保是Android Wear的module的apk文件,添加到最终的Android app项目的打包的APK中。


快速编译多个module

在Project工程的gradle.properties文件中

org.gradle.parallel = true  //加快编译,其实这个配置默认被注释的,只要打开注释就好

Gradle会尝试根据CPU核数选择正确的线程数量。为了防止可能出现的问题,从同一个模块并行执行两个任务,每一个线程拥有一个完整的模块。


Module coupling(Module耦合)

在一个项目中有多个Module,我们可以把一些共有的配置抽取出来,放到root Project工程的build.gradle文件中allprojects{}中,如:

allprojects{
    apply plugin:'com.android.application'

    android{
        compileSdkVersion 24
        buildToolsVersion "24.0.0"
    }
}

或者是使用ext{}的方式(详情见上篇)时,

如果这是你使用gradle.properties文件中的配置,如:

org.gradle.parallel=true

就会导致编译失败,原因是org.gradle.parallel=true会对每一个build任务采用一个线程执行(根据CPU的核心线程数分配),所以需要保持每个Module中的build任务独立,采用allproperties和ext{}方式在build的时候任务是耦合的。


多任务Tasks执行的顺序

定义2个任务task1和task2

task task1<<{
    println 'task1'
}

task task2<<{
    println 'task2'
}
  • mustRunAfter
task2.runMustAfter task1    //task2执行在task1后面

执行命令:
gradlew task2 task1 


log打印结果:

:task1
task1
:task2
task2
  • dependsOn
task2.dependsOn(task1) 或者 task2.dependOn task1  //task2任务依赖于task1,执行task2就会先执行task1

执行命令
gradlew task2


log打印结果:
:task1
task1
:task2
task2

自定义任务保护签名信息的私密性

我们在设置签名配置的时候,一般是通过明码写入在build.gradle文件中的。
如果拿到build.gradle文件就会暴露我们的keypassword等私密信息。

我们可以通过将这些私密信息写到一个private.properties文件中,通过load这个文件中的配置来设置keypassword等私密信息。

1.在Project的根目录下,创建一个private.properties文件,并写好配置信息。
如:

release.password = newpassword

2.在Module中的build.gradle文件中创建一个任务

task getReleasePassword<<{
    def password=""

    if(rootProject.file('private.properties').exists()){
        Properties properties = new Properties();
        properties.load(rootProject.file('private.properties').newDataInputStream())    //加载文件

        password = properties.getProperty('release.password')   //获取配置文件中的release.password的值,复制给password变量
    }   
}

3.做一个判断,只针对release版本

task.whenTaskAdded{theTask->
    if(theTask.name.equals("packageRelease")){
        theTask.dependsOn "getReleasePassword"
    }
}

4.在buildTypes{}中的release{}配置中使用签名配置

android.signingConfig.release.storePassword = password
android.signingConfig.release.keyPassword = password

Automatically renaming APKs(自动重命名apk)
android.applicationVariants.all{variant ->
    variant.output.each{output ->
        def file = output.outputFile

        if (outputFile != null && outputFile.name.endsWith('.apk')) {
            output.outputFile = new File(file.parent,file.name.replace(".apk","-${variant.versionName}.apk"))
        }       
    }
}

减小APK文件体积
  • ProGuard

    混淆工具,通过minifyEnabled设置true,开启混淆。ProGuard混淆工具修改类名和字段名保护apk的安全,同时也会压缩apk的体积。

    android{
        buildTypes{
            release{
                minifyEnabled = true
                ...
            }
        }
    }
    
  • Shrinking resources

    去除没有使用过的resource,通过shrinkResource设置true。它可以在混淆的时候知道哪些resource使用了,如果resource没有使用,会在混淆时过滤。

    android{
        buildTypes{
            release{
                ...
                shrinkResource = true
            }
        }
    }
    
  • Manual shrinking:

    如果你的app中仅支持1,2种语言,但是可能引用的lib库包含多种其他语言的strings资源,这个时候我们可以通过resConfig指定我们需要的strings资源。

        android{
            defaultConfig{
                resConfigs 'en','cn'
            }
        }

    同样我们可以指定我们需要支持的某些设备屏幕尺寸。如:

        android{
            defaultConfig{
                resConfigs "hdpi","xhdpi","xxhdpi","xxxhdpi"
            }
        }

    这样就可以过滤一些不要的资源。


Speeding up builds(加快编译速度)
  • Gradle properties

    通过设置Gradle的属性配置的方式(在Project工程下的gardle.properties文件中配置相应的属性),如:

    org.gradle.parallel = true
    

    parallel build是通过CPU的核心线程数来给每一个工程合理的分配一个独立的线程进行编译。

    org.gradle.daemon = true

    在Android Studio,Gradle daemnon 是默认true的。它的意思是,你第一次编译后,下一次编译就会更快一些。如果你使用命令行编译,deamon值是不可用的,除非你设置org.gradle.daemon属性true。

    org.gradle.jvmargs = -Xms256m -Xmx1024m

    jvmargs给JVM内存池设置不同的内存值。

    Xms:设置初始的内存值,256m代表内存大小。

    Xmx:设置最大的内存值,1024m代表内存大小。

    org.gradle.configureondemand = true

    configureondemand:如果设置为true,在运行配置信息之前,Gradle会试着算出modules中的configuration那些改变了,哪些没有改变。

    它会试着跳过modules中不执行的tasks,限制一些是小的configguration。

    如果你的项目中有多个module,这个属性对你来说是比较有用的。

  • Profiling

    如果你想找到build慢的原因,你可以给Gradletask 添加一个–profile标签,当你执行task时,Gradle会创建一个Profiling报告,告诉你build的那个部分最耗时。这个报告以html格式保存在build/reports/profile目录。

  • Jack and Jill(不推荐使用)

    • Jack(Java Android Compiler Kit)

      Jack是一个新的Android编译工具,可以直接将Java源码直接编译成dex文件格式。他有自己的.jack库。

    • Jill(Java Intermediate Library Linker)

      Jill是一个可以将.aar或.jar文件转成.jack库工具。

    这2个工具提高了编译时间,简化了编译过程,但是不推荐使用。

    Jack的使用

    android{
        defaultConfig{
            useJack = true
        }
    }
    
    或者
    
    android{
        productFlavors{
    
            store1{
                useJack = false
            }
    
            store2{
                useJack = true
            }
        }
    }
    

Ignoring Lint

当我们执行release编译时,Lint在编译的时候可能会找到一些错误,会导致Gradle编译失败,Gradle可以忽略Lint错误,阻止中断编译过程,如:

android{
    lintOptions{
        abortOnError false  //默认true,false表示错误不中断编译
    }
}

Gradle 运行Ant任务

Gradle是直接支持运行一个标准的Ant

task archive<<{
    ant.echo 'Ant is acthiving......'

    ant.zip(destfile:'archive.zip'){
        fileset(dir:'zipme')
    }

}

这个task使用了2个Ant任务,echo和zip。

导入Ant脚本

如果你创建了一个Ant脚本,你可以使用ant.importBuild导入编译配置。所有的Ant targets会自动转成Gradle的task。

例如:

Ant的编译文件build.xml

<project>
    <target name="hello">
        <echo>Hello Ant</echo>
    </target>
<project>

你可以导入Gradle编译中:

ant.importBuild 'build.xml'

执行命令与结果:

gradlew hello

打印结果:
:hello
[ant:hello] Hello Ant

Ant task和Gradle task一起使用

hello{
     println 'Hello, Ant. It\'s me, Gradle' 
}

执行 gradlew hello


打印结果如下:

:hello
[ant:hello] Hello Ant
Hello, Ant. It's me, Gradle

Gradle task依赖Ant task,如:

task hi(dependsOn:hello)<<{
    println 'Hi'
}


执行gradlew hi

打印结果

:hello 
[ant:echo] Hello Ant 
Hello Gradle 
:hi 
Hi 

Ant task依赖Gradle task,如:

<target name="hello" depends="hi">   
    <echo>Hello Ant</echo> 
</target> 


执行gradlew hello

打印结果:
:hi 
Hi 

:hello 
[ant:echo] Hello Ant 
Hello Gradle 

如果你的Ant编译文件中,包含比较多的task,为了避免覆盖,可能需要重命名,如:

ant.importBuild('build.xml'){antTargatName->
    'ant-' + antTargetName
}

如果你的ant task重命名了,注意在与Gradle task相互依赖时,需要将ant task名字改过来。不然会报UnKnownTaskExecption。

Ant Properties

Ant还可以通过build.xml在Gradle中定义属性,如:

<target name="appVersion">
    <echo>${version}</echo>
</target>

在Gradle中定义version的属性

ant.version = '1.0'

或者

ant.properties['version'] = '1.0'

执行命令:

gradlew appVersion


执行结果:

:appVersion
[ant:echo] 1.0

Split Apk

设备是允许通过屏幕密度(density)或者是ABI(application binary interface)来拆分apk的。

  • 通过density进行split apk
android{
    split{
        density{
            enabled true
            exclude 'ldpi','mdpi'
            compatibleScreen 'normal','large','xlarge'
        }
    }
}
生成结果:
app-hdpi-release.apk
app-universal-release.apk
app-xhdpi-release.apk
app-xxhdpi-release.apk
app-xxxhdpi-release.apk
  • 通过ABI进行split apk
android{
    split{
        abi{
            enabled true
            include 'armeabi','x86','mips'
            universaiApk true
        }
    }
}

Gradle for Android 下载链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值