gradle编译打包
‘壹’ Shell脚本自动编译打包Gradle项目并docker部署
需要用到2个文件,项目的build.gradle文件和自动化shell脚本(这里我们命名为auto.sh)
一、修改build.gradle文件
新增task配置节,注意build.gradle和Dockerfile在同一目录下
二、新增auto.sh
这几天工作上遇到一个问题,三方的jar包在liunx下解压不了,用gradle又能正常编译,我们的apk是在liunx下用mk进行编译的,编译的过程中需要对jar包进行解压,这样就导致编译失败。
错误信息如下:以后再遇到这个错误,可能就jar包的问题。
FAILED: /bin/bash -c "(mkdir -p out/target/common/obj/java_LIBRARIES/xxx-sdk_intermediates/classes.jack.tmpjill.res ) && (unzip -qo /home/x/xx/xxx/APK92_GNBJ_EDO/code/libs/xxx-sdk-java20171027120314.jar -d out/target/common/obj/JAVA_LIBRARIES/xxx-sdk_intermediates/classes.jack.tmpjill.res ) && (find out/target/common/obj/JAVA_LIBRARIES/xxx-sdk_intermediates/classes.jack.tmpjill.res -iname \"*.class\" -delete ) && (JACK_VERSION=3.36.CANDIDATE out/host/linux-x86/bin/jack @build/core/jack-default.args --verbose error -D jack.import.resource.policy=keep-first -D jack.import.type.policy=keep-first -D jack.android.min-api-level=1 --import /home/x/xx/xxx/APK92_GNBJ_EDO/code/libs/xxx-sdk-java20171027120314.jar --import-resource out/target/common/obj/JAVA_LIBRARIES/xxx-sdk_intermediates/classes.jack.tmpjill.res --output-jack out/target/common/obj/JAVA_LIBRARIES/xxx-sdk_intermediates/classes.jack ) && (rm -rf out/target/common/obj/JAVA_LIBRARIES/xxx-sdk_intermediates/classes.jack.tmpjill.res )" warning: stripped absolute path spec from / mapname: conversion of failed ninja: build stopped: subcommand failed. build/core/ninja.mk:148: recipe for target 'ninja_wrapper' failed
解决方法:对jar包源码重新打包
解压jar包源码,注意,是带源码的jar包,如果是编译过的jar,是不能重新打包的。
步骤:
1.新建build.gradle文件,因为gradle会默认找到当前目录下的build.gradle下的文件去执行;
2.在终端执行gradle unzip,执行这个task
以下命令将这个目录 app/libs/xxx-sdk-java20171027120314.jar 下的jar包解压到了 unpacked/dist 目录。
解压之后的源码就是文件夹,重新打包的时候需要注意,包名和源码的路径名一致。现在利用Android studio进行打包。
步骤:
1.新建lib mole,选择Android Libeary/Java Library;
2.注意修改包名与jar包路径相同,eg:jar包解压之后的路径 dist/com/example/api ,那么为了确保新生成的jar包里的Java文件import路径相同,mole的包名也要命名为 com.example.api ;
3.将解压之后的源码java文件复制到lib model中;
4.在 app mole 下添加 lib mole 依赖。这是一种取巧的方法,当你添加了lib mole依赖之后,项目会重新rebuild,这个过程会将mole依赖编译成jar包,存放在lib mole的 build/libs 目录下,由于Android Studio版本不同,这个目录可能有有所不同,但是都在build目录下,找新的jar包就可以了。
这一部可能会报jar包找不到,或者lib mole中的import失败,可能是因为lib mole依赖的jar包没导入,导入之后在lib mole的build.gradle里配置一下就可以了。
这个时候,其实直接用这个jar包也可以了,如果向修改jar包名字,可以执行下面的gradle命令:
想了解更多可以参考 这里
然后在项目里测试一下jar包就可以了。
重新打包之后就可以在liunx下解压了,正常编译通过。
最后记录一下mk编译的一个错误 # [ERROR: Dex writing phase: classes.dex has too many IDs. Try using multi-dex](https://stackoverflow.com/questions/45472852/error-dex-writing-phase-classes-dex-has-too-many-ids-try-using-multi-dex) 在stackoverflow上找到了解决方法。
在mk文件中添加
参考:
https://stackoverflow.com/questions/39457116/gradle-build-hanging-when-jackoptions-is-enabled-for-java-1-8
https://stackoverflow.com/questions/45472852/error-dex-writing-phase-classes-dex-has-too-many-ids-try-using-multi-dex
‘叁’ Gradle编译-APK编译过程
在早期的Android设备中(Android5.0以下)都是使用的Dalvik虚拟机,Dalvik支持经过转换的.dex文件。.dex格式是专为Dalvik设计的一种适合内存和处理器速度有限的系统。
但是在Android5.0,google用ART全面取代的Dalvik。Android7.0中又添加了JIT编译器,使得Android性能也有不少提升。
上图为从Android源文件开始,最终到APK的过程。
下面博客文章详细介绍了dalvik虚拟机,可供参考学习。
https://www.cnblogs.com/lao-liang/p/5111399.html
dvm(art)和jvm属于不同的虚拟机平台,不同平台要求执行的文件类型也就不一样
dvm(art)--.dex文件
jvm--.class文件
在编译和生成上
java source --.class文件 ---jvm执行
java source --.class文件 ---.dex文件 --- dvm执行
Android Runtime (ART) 是 Android 上的应用和部分系统服务使用的托管式运行时。ART 及其前身 Dalvik 最初是专为 Android 项目打造的。作为运行时的 ART 可执行 Dalvik 可执行文件并遵循 Dex 字节码规范。
ART 和 Dalvik 是运行 Dex 字节码的兼容运行时,因此针对 Dalvik 开发的应用也能在 ART 环境中运作。不过,Dalvik 采用的一些技术并不适用于 ART。
ART的功能
1.预先 (AOT) 编译
使用ART编译器时,应用程序在安装期间就已经把dex字节码翻译并存储在设备上,运行时,只需要执行这些翻译好的就可以了,因此执行速度也快了不少。
2.垃圾回收方面的优化
3.开发和调试方面的优化
构建流程涉及许多将项目转换成 Android 应用软件包 (APK) 的工具和流程。构建流程非常灵活,因此了解它的一些底层工作原理会很有帮助。
‘肆’ gradle是什么呢
Gradle是一个构建工具。它是用来帮助我们构建app的,构建包括编译、打包等过程。我们可以为Gradle指定构建规则,然后它就会根据我们的命令自动为我们构建app。AndroidStudio中默认就使用Gradle来完成应用的构建。有些同学可能会有疑问:”我用AS不记得给Gradle指定过什么构建规则呀,最后不还是能搞出来个apk。

gradle构建工具多项目管理
实际使用中,往往需要管理的都不是单单一个项目,maven使用依赖,继承,组成的概念,在父模块指定自己的子模块,并且准备一些各个子模块公用的资源,配置信息等等。将打包的模块与实现具体功能的模块分开的做法来管理多个项目。Gradle在这一方面做得更加清楚。
‘伍’ Gradle--多环境编译打包
前段时间产品经理提了个需求,测试环境,预发布环境,生产环境编译下的app需要在同一步手机同时存在,实现是可以的,但是得有三个环境下的不同applicationId,网络地图key,域名,桌面logo,刚开始是想需要什么环境就换什么类型,很麻烦,每次都要换一次重新编译,我就在想有什么便捷的方法一键设置更换,gradle其中的Flavors功能可以实现我想要的。
这个是主项目中build.gradle中的配置,有三个环境我命名为 xiaoming_test,xiaoming_ready,xiaoming_proct,并有不同的applicationId,BAIDU_MAP_KEY,HTTP_HEAD,HTTP_HEAD_JAVA,app_icon,(解释一下,有两条域名是因为后面后台是用java开发而做的区分),到这里应该大家有疑问,举个栗子,我们一般开发的第三方key是在mainifests进行注册申请的,而我们gradle如何去引用资源的。这里有两种引用方式,直接引用,自定义引用。
引用logo在application的icon属性命名为app_icon,$表示引用这个命名,对应的是gradle的配置。
在mainifests自定义为HTTP_HEAD,value值通过${HTTP_HEAD}引用,getHttpHead()获取自定义注册的域名值。从而实现每次请求对应的域名,只需在gradle里设置。
只需打开studio的BuildVariarts设置,选择需要的环境即可重新编译不同的apk,方便快捷的做到一键设置快速打包。
‘陆’ Gradle 命令
gradle -v //版本号
gradle clean //清除build文件夹
gradle build //检查依赖并打包
gradle assembleDebug //编译打包Debug包
gradle assembleRelease //编译打包Release包
gradle installRelease //打包并安装Release包
gradle unstallRelease //卸载Release包
gradle dependencies //查看依赖图表
gradle clean build -x test //跳过测试编译
gradle --profile build //分析构建任务
gradle build --dry-run //编译并不执行任务
gradle install //安置项目jar包到本地Maven仓库
gradle tasks //查看Gradle任务
gradle tasks --all //查看所有Gradle任务
gradle build --daemon //使用Gradle守护程序(Daemon)
gradle build --offline //用离线模式运行
gradle clean build --refresh-dependencies //刷新Gradle依赖缓存
‘柒’ 如何使用gradle构建工具打包groovy脚本成jar文件
准备工作安装 gradle, groovy。
要使用gradle的groovy plugin 来打包groovy 脚本,项目结构。
目录 含义
src/main/java Java 代码
src/main/resources Java需要的资源文件
src/main/groovy Groovy代码,也可以包含Java代码
src/test/java Java 测试代码
src/test/resources 测试需要的资源文件
src/test/groovy Groovy测试需要的资源文件
src/sourceSet/java Java代码源
src/sourceSet/resources 资源文件源
src/sourceSet/groovy Groovy代码源
我们只需要编译打包groovy脚本 所以只需要创建 src/main/groovy目录结构。例子:
gradle_groovy_archive项目 结构是:
gradle_groovy_archive
创建helloWorld.groovy脚本,代码如下:
package hello
println 'Gradle compile groovy'
创建Gradle构建文件:
apply plugin: 'groovy'
apply plugin: 'maven'
group = 'com.hello'
archiveBaseName = 'hello'
version = '0.1-SNAPSHOT'
defaultTasks 'clean', 'jar'
configurations {
deployerJars
}
repositories {
mavenCentral()
}
dependencies {
//使用本地groovy环境
groovy localGroovy()
//groovy group: 'org.codehaus.groovy', name: 'groovy', version: '1.8.6'
compile fileTree( dir: 'lib', include: ['*.jar'])
deployerJars 'org.apache.maven.wagon:wagon-webdav-jackrabbit:1.0-beta-7'
}
sourceSets {
main {
groovy {
srcDir 'src/main/groovy'
}
}
}
uploadArchives {
repositories.mavenDeployer {
uniqueVersion = false
configuration = configurations.deployerJars
repository(id : repositoryId, url : repositoryUrl) {
authentication (userName : 'deployment', password : 'deployment')
proxy()
}
}
}
创建构建文件属性文件:
//根据不同情况修改
repositoryId=ND
repositoryUrl=ND
systemProp.http.proxyHost=ND
systemProp.http.proxyPort=8080
systemProp.http.proxyUser=ND
systemProp.http.proxyPassword=ND
在命令行中 敲 gradle 运行,会自动运行 defaultTasks,clean 和 jar,会把 所有groovy下的脚本打成jar包。
‘捌’ Gradle如何只编译而不打包资源
gradle tasks
看看哪个task是你要的
‘玖’ Android gradle 打包错误A problem occurred configuring project ':app'.
因为项目为插件工程,每次编译需要使用“./gradlew pushPlugin”自动push到壳工程,但是...我的不行,就不行...
错误如下:
一脸懵逼,完全看不懂....
按照提示尝试找找错误原因,然后一顿操作,猛如虎:
./gradlew --stacktrace
./gradlew --info
./gradlew --scan
...
这个错误感觉有点意思,可能是病灶的根源,仔细一看,确实,经过几分钟仔细研究,终于知道了:
解决方案:
1、我首先去把as的jre配置地方改成系统的,发现,改不了,放弃...
2.as不让改,还不能改自己的么,改本地的环境变量,把java_home的jre换成as的jre地址,
结果,编译的特别丝滑...
问题解决了,但是总觉得怪怪了,因为本地jre环境被改了,不舒服,哈哈,原因很简单啊,本地jdk以后升级就不行了,第二种方法只是暂时解决了,并不完美,所以还得再想想...
终极解决:
编写了一个脚本文件,主要作用有俩个,第一是临时替换本地jre的地址,指向到as的。第二是直接编译,然后push;
脚本如下:
ps:把地址换成自己as的jre地址就可以,注意分隔符的方向
运行编译,完美编译, 丝滑 ...
