我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Gradle编译打包Android apk详细介绍

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Gradle编译打包Android apk详细介绍

Gradle编译打包Android apk详细介绍

理解Gradle构建过程,解读Android Gradle插件的配置

阅读本文一定是要使用过Gradle生成apk,文中不会讲如何安装运行Gradle,如有需要可先看文末的参考文章。

APK包是一个ZIP压缩包,从Java源代码、资源文件到生成这个APK,经过了编译打包一系列特定的过程,SDK文档(/docs/tools/building/index.html)中找到。而这一系列特定的过程,重复繁琐,构建工具(build tool)就是来流程化这些过程,解放你的双手。Ant作为apk早期的构建工具,构建过程显得很直观,像配置;Gradle可以方便地配置,但更像脚本,可以编程。

理解Gradle构建

1.简单理解构建工具

从一个程序员的角度,你该如何编写代码来自动化你的apk生成过程呢?首先得知道你需要的SDK、NDK在什么位置,Android工程有几个库工程,它们的Java源代码、资源文件分别有哪些?命令行的输入参数肯定无法满足需求,那自然而然想到配置文件。因此你的自动化工具就是解析这些配置文件,按照生成apk文件要求执行的程序。Gradle就是这样的工具程序,配置文件就是你常见的settings.gradle,build.gradle,不过他还提供了更多的功能,如依赖管理,流程控制,还有插件机制来定制你的生成过程。

Gradle的编程语言是Groovy,其需要的配置文件支持Groovy。Groovy语言像Java一样是基于JVM的,而且能够很好的支持Java,因此可以用Java代码编写扩展插件,像普通编程一样来写配置文件,而不用像Ant一样用xml来编写配置逻辑。

2.Groovy

Groovy的语法,把自己的代码缩略的看上去像脚本,本人也只是看了一点点文档,列出我们常用的介绍一下:
首先Groovy是面向对象的动态语言
(1)语句的末尾可省略分号
(2)变量定义可以用def,也可以直接使用
(3)函数定义可以用def,也可以不用(有返回值声明也可)

  函数可省略参数类型
  函数调用可省略括号

来看个例子:


println 'Hello'                  
int power(int n) { 2**n }             
println "2^6==${power(6)}" 

第一行输出字符串Hello,第二行定义一个函数,第三行输出函数调用值,双引号中间的${}可被解析成表达式运行。

(4)List和Map类型

List实现就是Java的java.util.ArrayList,变量由[]包围,用逗号分隔,比如


def heterogeneous = [1, "a", true] //其元素可以是任何对象 

Map的实现是java.util.LinkedHashMap,也是由[]包围,用逗号分隔,其中的键值对是key:value形式,如:


def colors = [red: '#FF0000', green: '#00FF00', blue: '#0000FF']   
assert colors['red'] == '#FF0000' //取值可以[key]或者.key的形式 
assert colors.green == '#00FF00'  

(5)闭包(Closures)

闭包我的理解类似C里的函数指针,或者说函数对象,可以像函数一样调用的对象
{ [closureParameters -> ] statements }
例子


def testClosure = {int arg1, String arg2 ->//def可省略,参数可省略,默认有it,当只有->表示没有参数 
 println "arg2:${arg2}" //执行的代码,返回值是最后一句,也可以用return 
} 
调用: 
testClosure(1,'2') 
testClosure.call(1,'2') 

3.Gradle

接着说自动化工具,编程语言有了,那实现一系列特定过程生成apk,就看如何实现了。Gradle里有Project,表示一个待编译打包处理的工程,可以生成apk,可以生成Jar,Project中可以包含多个Project;每个Project由很多的Task构成,可以理解为不同的过程;每个Task里又是有不同的Action,和一系列要执行的操作(或者说你写的要执行的语句)。Project中的Task的执行顺序,则是由其dependsOn来控制的。
Gradle执行时是以task为单位执行,在命令行中以gradle task来执行,这一过程的生命周期分为三个阶段(官方使用手册中也有详细介绍The Build Lifecycle):

(1)初始化阶段

判断包含哪些工程,创建对应的Project实例,可以看到最新执行的是在settings.gradle中的语句

(2)配置阶段

创建不同的Task(Task可以动态生成),并根据Task之间的dependsOn,确定Task的执行顺序,或者禁用某些Task。此阶段完成后,Task之间的依赖关系也就确定下来。

(3)执行阶段

在配置完成后,按照依赖关系,按顺序执行。

需要注意的是通常在Task中的语句,都是在配置阶段执行的,而doFirst,doLast这类Action是在执行阶段中的。因此会出现你的依赖关系中没有的Task中语句也被执行了的问题

如下例子,打印出的task内容是不一样的


task printTasksName { 
 tasks.all {//all是一个方法,参数可以是闭包,函数的元括号可以省略 
 println "show tasks in Configuration:${it.name}" //it是闭包的默认参数 
 } 
 doFirst { 
 tasks.all { 
 println "show tasks in Execution:${it.name}" 
 } 
 } 
} 

4.Gradle插件和Androd插件
在提供了基本的流程控制之后,接下来是具体的要做什么,构建什么。Gradle提供了针对语言的插件如java,groovy等负责编译,集成插件如application,war等生成java可执行程序,web程序的WAR文件。Android根据APK生成的过程,编写了自己的插件,其中也使用了java插件。

(1)自定义插件的插件名称在resources/META-INF/gradle-plugins

在resources/META-INF/gradle-plugins目录下有后缀为properties文件,该文件的命名就是你在build.gradle中使用插件的名字,里面声明了该插件的实现类。在Android插件的源码中可以看到android.properties和com.android.application.properties中两个插件名称,因此在build.gradle中,应用工程使用Android插件需要apply plugin: 'android'(已是deprecated)或者apply plugin: 'com.android.application'

(2)Android插件中application的实现类是AppPlugin,继承自com.android.build.gradle.BasePlugin ,调用apply方法,相应的configureProject(),解析local.properties,获得sdk位置,创建AndroidBuilder,应用JavaBasePlugin,而后createExtension() 关联BuildType,ProductFlavor,SigningConfig,最后createTasks(),完成各个Task的创建

5.DSL(Domain Specific Language)

DSL我翻译成领域专用语言,就是在这里预先规定好的规则,或者说是行话。在Gradle的DSL中一般常见的类型,一种是类型(Type)有Project、Task等,给他们定义了不同的操作和用法,一种是语句块(build script block或configuration block)如build.gradle中常见的buildscript { },allprojects { }。Android中也定义了非常多语句块,如buildTypes { },sourceSets { }。

Android Gradle插件配置

有了上述概念,再看android应用中的build.gradle,其实文中也只能讲一些,但是更多的可以自己查看Android插件的DSL


apply plugin: 'com.android.application' // 使用Android插件,非库工程,生成的是apk 
dependencies { 
 compile 'com.android.support:multidex:1.0.1' 
 compile fileTree(dir: 'libs', include: '*.jar') 
 compile project(':库工程1') // 代码、资源包含在主程序apk中的 
 provided project(':库工程1') // 只参与编译,不输出到目标apk中 
} 
// Android插件DSL中的AppExtension类型 
android { 
 compileSdkVersion rootProject.ext.compileSdkVersion // 多工程时配置统一的属性 
 buildToolsVersion rootProject.ext.buildToolsVersion 
 // lint检查,避免lint检测到不符合条件退出编译 
 lintOptions { 
 abortOnError false 
 } 
 // gradle编译会默认合并库工程的manifest到主工程,如果主程序和库工程的包名不一致会有问题 
 enforceUniquePackageName = false 
 // 所有的 product flavors继承 
 defaultConfig { 
 applicationId "cn.arainfo" 
 minSdkVersion 14 
 targetSdkVersion 10 
// multiDexEnabled true 
 dexOptions { 
 javaMaxHeapSize "2g" 
 jumboMode true 
 } 
 } 
 // 此处由于工程是从Eclipse导入,所有路径都进行了声明 
 sourceSets { 
 main { 
 manifest.class="lazy" data-srcFile 'AndroidManifest.xml' 
 java.class="lazy" data-srcDirs = ['class="lazy" data-src'] 
 resources.class="lazy" data-srcDirs = ['class="lazy" data-src'] 
 aidl.class="lazy" data-srcDirs = ['class="lazy" data-src'] 
 renderscript.class="lazy" data-srcDirs = ['class="lazy" data-src'] 
 res.class="lazy" data-srcDirs = ['res'] 
 assets.class="lazy" data-srcDirs = ['assets'] 
 } 
 debug.setRoot('build-types/debug') 
 release.setRoot('build-types/release') 
 } 
 // 编译类型,指定release的proguard配置文件 
 buildTypes { 
 release { 
 minifyEnabled true 
 proguardFile 'proguard.flags' 
 } 
 } 
} 
afterEvaluate { 
 println "afterEvaluate set project dependsOn..." 
 project(':主程序工程').tasks.getByName("assembleDebug").dependsOn ":子程序工程:assembleDebug" 
 if (project.hasProperty('TestRelease')) { 
 project(':主程序工程').tasks.getByName("assembleRelease").dependsOn ":子程序工程:assembleRelease" 
 } 
} 

说明几处

(1)如在根目录的build.gradle中声明公用属性


ext {
 compileSdkVersion = 21
 buildToolsVersion = '25.0.0'
 isOnWindows = Os.isFamily(Os.FAMILY_WINDOWS)
}

(2)buildTypes { },productFlavors{ },signingConfigs { }

上述三个语句块,类型是NamedDomainObjectContainer<T>,其中T是BuildType ProductFlavor SigningConfig,而buildTypes { },productFlavors{ }中增加新的类型,会对应有新的Task生成,规则为assemble[flavor][buildType],因此当compileSdkVersion较低,又用了MultiDex时,还想用InstantRun,就可以创建一个新的buildType,只在测试时使用

(3)afterEvaluate语句块

Android的Gradle插件版本在2.2.0时,Task的创建已经在afterEvaluate,因此,如果想继续使用tasks.getByName("assembleDebug"),必须要将自己的语句写到afterEvaluate { }语句块中

总结:

越写越心虚,零零碎碎的内容非常多,按照自己的理解贯穿下来,涵盖了部分内容,基本可以理解build.gradle。但是语句块如buildTypes { }和BuildType如何关联起来(或者说如何解析出来并创建对象)的,并没有很好的理解。
如果有时间可以好好看下《深入理解Android(一):Gradle详解》,一般的问题,比如多渠道打包productFlavors怎么配置啊,自己通过查Android的DSL就能解决。

参考文档:

1.Groovy官方文档
2.Gradle用户手册
3.Gradle的DSL
4.Android插件的DSL
5.深入理解Android(一):Gradle详解

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

您可能感兴趣的文章:Linux命令行下编译Android NDK的示例代码Studio 编译报错:compileSdkVersion ''android-24'' requires JDK 1.8 or later to compile.的解决办法Ubantu16.04进行Android 8.0源码编译的流程Android Studio中通过CMake使用NDK并编译自定义库和添加预编译库Android反编译程序整理详解android开发实践之ndk编译命令简单示例完美解决Android Studio集成crashlytics后无法编译的问题Android应用程序(APK)的编译打包过程下载、编译、运行android 7.1系统详解(ubuntu 16.0.4)Android编译的注意事项


免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Gradle编译打包Android apk详细介绍

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Gradle编译打包Android apk详细介绍

Gradle编译打包Android apk详细介绍 理解Gradle构建过程,解读Android Gradle插件的配置阅读本文一定是要使用过Gradle生成apk,文中不会讲如何安装运行Gradle,如有需要可先看文末的参考文章。 APK
2022-06-06

使用android-apktool来逆向(反编译)APK包方法介绍

谷歌官方提供了apktool可以逆向已经发布出去的APK应用,即反编译已经打包成功的APK文件,使用它可以将其反编译成非常接近打包前的原始格式,对于APK来说,可以具体的逆向AndroidManifest.xml、资源文件resources
2022-06-06

Android aapt自动打包工具详细介绍

Android aapt自动打包工具 概念 在Android.mk中有LOCAL_AAPT_FLAGS配置项,在gradle中也有aaptOptions,那么aapt到底是干什么的呢? aapt即Android Asset Packagin
2022-06-06

Android应用程序(APK)的编译打包过程

流程图: 我们重点关心的是(1)这个过程的输入是什么?(2)这个过程的输出是什么?(3)这个过程使用了什么工具?至于使用什么参数,可以自己去看对应命令的帮助文件,或者在网上搜索,这不是本文的重点。 aapt-> aidl -> java
2022-06-06

Android开发apk反编译和二次打包教程

作为Android开发者,工作中少不了要反编译别人的apk,当然主要目的还是为了学习到更多,取彼之长,补己之短。今天就来总结一下Android反编译和二次打包的一些知识。首先声明本文的目的是为了通过例子讲解反编译和二次打包的原理和方法,继而
2022-06-06

Android APK文件结构 完整打包编译的流程 APK安装过程 详解

Android apk文件结构 打包编译的流程Android官网 配置构建 流程Configure your buildThe build processAPK文件结构assetsreslibMETA-INFAndroidManifest.
2022-06-06

Android 使用jarsigner给apk签名的方法详细介绍

Android 使用jarsigner给apk签名的方法详细介绍 工作中APP功能完成以后往往需要往应用商店提交一些内容,如商店中存在本公司别的人员提交的APP,往往需要进行认领,应用商店会让开发者下载空的APK,然后使用自己APP的签名文
2022-06-06

阿里云Linux服务器编译器详细介绍

编译器是一种将高级语言源代码编译成机器语言的程序。它是软件开发过程中的重要工具,它可以将源代码转换成机器可以理解的二进制代码。阿里云Linux服务器中的编译器种类繁多,包括GCC、Clang、MIPS编译器等。本文将详细介绍阿里云Linux服务器中的编译器。一、GCC编译器GCC是GNUCompilerColle
阿里云Linux服务器编译器详细介绍
2023-11-01

Android笔记之:App自动化之使用Ant编译项目多渠道打包的使用详解

随着工程越来越复杂,项目越来越多,以及平台的迁移(我最近就迁了2回),还有各大市场的发布,自动化编译android项目的需求越来越强烈,后面如果考虑做持续集成的话,会更加强烈。 经过不断的尝试,在ubuntu环境下,以花界为例,我将一
2022-06-06

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录