学无止境,有一技旁身,至少不至于孤陋寡闻。
随着我们工作阅历的提升,除了基本的业务开发,也需要提升我们自身在开发效能方面的一些储备与笔记。
Android开发日常之gradle
Android开发日常之adb
Android开发日常之git
Android开发日常之shell alias
在Android开发中在项目根目录、app或者其他module中我们都能看到build.gradle
这个文件,我们也知道Android项目的编译和运行都是通过gradle来实现,需要引入第三方库时就找到对应项目的build.gradle
中按照集成文档修修改改引入即可,有可能也不会过多的去关注,这里简单介绍下关于在Android开发中gradle的使用。
-
调整gradle的编译参数(gradle.properties文件中配置)
内存配置:org.gradle.jvmargs=-Xmx4096m -XX:MaxPermSize=1024m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
- 堆的内存分配用-Xms和-Xmx
- Xms分配堆最小内存,默认为物理内存的1/64;
- Xmx分配最大内存,默认为物理内存的1/4。
- 非堆内存分配用-XX:PermSize和-XX:MaxPermSize
- XX:PermSize分配非堆最小内存,默认为物理内存的1/64;
- XX:MaxPermSize分配最大内存,默认为物理内存的1/4。
守护进程
org.gradle.daemon=true
并行编译
org.gradle.parallel=true
开启缓存
android.enableBuildCache=true
开启孵化模式
org.gradle.configureondemand=true
更多配置信息,移步Gradle官方文档 - 堆的内存分配用-Xms和-Xmx
-
推荐引用固定版本依赖库
dependencies { compile 'com.google.code.gson:gson:2.2.1' //推荐写法 // compile 'com.google.code.gson:gson:2.+' // 不推荐写法 }
虽然带+号的引用可以保证库是最新的,但更新的新库有没有更改库逻辑而带来的bug是未知的。
-
module、jar及aar的依赖方式
implementation project(':commonlibrary') implementation files('libs/alipaysdk.jar') implementation(name: 'xpay-1.0.1', ext: 'aar')
- module生成jar
def ccLibName = 'cc-1.0.1.jar' task makeJar(type: Copy) { //删除存在的 delete 'build/libs/'+ccLibName //设置拷贝的文件 from('build/intermediates/packaged-classes/release/') //打进jar包后的文件目录 into('build/libs/') //将classes.jar放入build/libs/目录下 //include ,exclude参数来设置过滤 include('classes.jar') rename ('classes.jar',ccLibName) } makeJar.dependsOn(build)
- module生成aar(默认编译会生成aar,此处更改aar生成名称)
buildTypes { release { ... ... android.libraryVariants.all { variant -> if(variant.name.equalsIgnoreCase("release")) { variant.outputs.all { output -> def f = output.outputFileName if (f != null && f.endsWith('.aar')) { def fileName = "cc-v${defaultConfig.versionName}.aar" output.outputFileName = fileName } } } } } }
- module生成jar
-
用exclude关键字解决依赖库冲突问题
如我们在Android项目中集成某个第三方库时,可能第三方库也会引入某个本地已经引入的库,所以就会存在引入多版本的依赖库。- 移除整个组织的库
compile ('com.facebook.fresco:animated-webp:0.13.0') { exclude group: 'com.android.support' // 仅仅写组织名称 }
- 精确移除某个指定库
compile('com.android.support:appcompat-v7:23.2.0') { exclude group: 'com.android.support', module: 'support-annotations' // 写全称 exclude group: 'com.android.support', module: 'support-compat' exclude group: 'com.android.support', module: 'support-v4' exclude group: 'com.android.support', module: 'support-vector-drawable' }
如何产看项目中的第三方库的依赖关系?
执行以下命令行:(如何你想查看某个module的依赖关系,此处的app使用你的module名来替换即可
)-
Windows:
gradlew :app:dependencies > dependencis.txt
-
MAC:
./gradlew :app:dependencies > dependencis.txt
- 移除整个组织的库
-
设置java版本
- 如果是在某个module中设置,那么就在对应module的build.gradle文件中配置:
android { compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } }
- 如果想要做全局配置,那么就在根目录的build.gradle中配置:
allprojects { repositories { jcenter() } tasks.withType(JavaCompile) { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } }
- 如果是在某个module中设置,那么就在对应module的build.gradle文件中配置:
-
在build.gradle中设置productFlavors
android { productFlavors { baidu { manifestPlaceholders = [UMENG_CHANNEL_VALUE: "baidu"] } xiaomi { manifestPlaceholders = [UMENG_CHANNEL_VALUE: "xiaomi"] } } }
-
assemble是Gradle中的编译打包命令
- 打包baidu渠道的release版本
gradlew assembleBaiduRelease
- 打包baidu渠道的debug版本
gradlew assembleBaiduDebug
- 生成baidu渠道的Release和Debug版本
gradlew assembleBaidu
- 打包全部渠道Release版本
gradlew assembleRelease
- 打包baidu渠道的release版本
-
为各渠道设置各自的配置信息
android { productFlavors { baidu { applicationId "com.liujc.demo.baidu" manifestPlaceholders = [UMENG_CHANNEL_VALUE: "baidu", APP_NAME : "app应用01", //app名称 ] buildConfigField "String", "API_APP_ID", "\"10001\"" } xiaomi { applicationId "com.liujc.demo.xiaomi" manifestPlaceholders = [UMENG_CHANNEL_VALUE: "xiaomi", APP_NAME : "app应用02", //app名称 ] buildConfigField "String", "API_APP_ID", "\"10002\"" } } }
如何使用?
如上的applicationId
和manifestPlaceholders
中信息在AndroidManifest
中使用如下:android:label="${APP_NAME}" <uses-permission android:name="${applicationId}.permission.JPUSH_MESSAGE" />
而
buildConfigField
中的参数在代码中使用BuildConfig.API_APP_ID
。 -
Android Studio 为多渠道执行自定义名称打包命令:
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' applicationVariants.all { variant -> variant.outputs.each { output -> def outputFile = output.outputFile if (outputFile != null && outputFile.name.endsWith('.apk')) { // 计划输出apk名称为App_V1.0.0_baidu.apk def fileName = "App_V${variant.productFlavors.versionName}_${variant.productFlavors.name}.apk" output.outputFile = new File(outputFile.parent, fileName) } } }
下面是多渠道配置:
android { productFlavors { baidu { applicationId "com.liujc.demo.baidu" versionCode 1 versionName "1.0.0" manifestPlaceholders = [UMENG_CHANNEL_VALUE: "baidu", APP_NAME : "app应用01", //app名称 ] buildConfigField "String", "API_APP_ID", "\"10001\"" } xiaomi { versionCode 2 versionName "1.0.1" applicationId "com.liujc.demo.xiaomi" manifestPlaceholders = [UMENG_CHANNEL_VALUE: "xiaomi", APP_NAME : "app应用02", //app名称 ] buildConfigField "String", "API_APP_ID", "\"10002\"" } } }
打包成功后你会发现包名为:
App_V[1.0.0]_[baidu].apk
,这不是我想要的啊,怎么都多了个中括号呢,修改打包代码:proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' applicationVariants.all { variant -> variant.outputs.each { output -> def outputFile = output.outputFile if (outputFile != null && outputFile.name.endsWith('.apk')) { // 计划输出apk名称为App_V1.0.0_baidu.apk def fileName = "App_V${variant.productFlavors[0].versionName}_${variant.productFlavors[0].name}.apk" output.outputFile = new File(outputFile.parent, fileName) } } }
再重新打包,成功后发现包名为:
App_V1.0.0_baidu.apk
OK了。 -
打包时相关属性介绍
name:build type的名字
applicationIdSuffix:应用id后缀
versionNameSuffix:版本名称后缀
debuggable:是否生成一个debug的apk
minifyEnabled:是否混淆
proguardFiles:混淆文件
signingConfig:签名配置
manifestPlaceholders:清单占位符
shrinkResources:是否去除未利用的资源,默认false,表示不去除。
zipAlignEnable:是否使用zipalign工具压缩。
multiDexEnabled:是否拆成多个Dex
multiDexKeepFile:指定文本文件编译进主Dex文件中
multiDexKeepProguard:指定混淆文件编译进主Dex文件中
以下开发中开发中常用的gradle命令
生成Android项目的依赖文件并导出
gradlew :app:dependencies > dependencis.txt
查看编译日志详细信息
gradlew compileDebugSource --stacktrace -info
输出项目debug编译日志
gradlew assembleDebug --info>log2.txt
获取构建报告,以HTML的形式展示。
gradle build -profile
gradle build -x lint
在Task Execution(任务执行)中去掉lint任务,节省Gradle构建时间。
Tips:使用Android Studio任务栏直接点击运行按钮是不能去掉lint任务的,所以为了方便构建后安装应用,可以使用gradle installDebug -x lint
命令。-
Clean命令
mac: ./gradlew clean build --info > cleanlog.log windows: gradlew.bat clean build --info > cleanlog.log
使用help
./gradlew --help
-
build 某个指定 module
AS 推荐的结构是multiple project
结构,即一个 project 下,管理多个 module,如果每次都要 build 全部的 project 的话,有点浪费时间,则可以使用-p module
参数,其中 module 是你要 build 的 module:$ ./gradlew -p app clean build $ ./gradlew -p app/app_module assembledebug
-
明确指定不执行某个 task
Gradle 的命令存在依赖,例如 build task,是依赖于一系列的其他的 task,如果想要指定不执行某个 task,则可以使用-x task
参数,其中 task 是要忽略的那个,这个参数可以传递多次。$ ./gradlew build -x test -x lint
-
执行多模块任务
当你在工程根目录下通过命令行窗口运行任务时,Gradle会找出所有模块中的同名任务,并运行它们。比如,你有一个app模块和一个Android Wear模块,运行./gradlew assembleDebug
将会为app模块和Android Wear模块都构建一个debug版本。如果你切换到模块的目录下,Gradle将只会运行该模块的任务,即使你在工程根目录中运行Gradle Wrapper。比如,在Android Wear模块的目录运行./gradlew assembleDebug
,只会构建Android Wear模块。切换目录的方式来运行模块的任务是比较繁琐的。另一个方式是可以使用模块名称来预处理任务名称,使运行任务只在那个模块上运行。比如只想构建Android Wear模块,可以使用如下命令:
./gradlew :wear:assembleDebug ./gradlew -p app/app_module assembledebug