本文主要是介绍Android Gradle基础介绍,Android面试送分题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
android { compileSdkVersion rootProject.ext.compileSdkVersion buildToolsVersion rootProject.ext.buildToolsVersion }
-
1
-
2
-
3
-
4
Android studio gradle Task
//构建 gradlew app:clean //移除所有的编译输出文件,比如apk gradlew app:build //构建 app module ,构建任务,相当于同时执行了check任务和assemble任务 //检测 gradlew app:check //执行lint检测编译。 //打包 gradlew app:assemble //可以编译出release包和debug包,可以使用gradlew assembleRelease或者gradlew assembleDebug来单独编译一种包 gradlew app:assembleRelease //app module 打 release 包 gradlew app:assembleDebug //app module 打 debug 包 //安装,卸载 gradlew app:installDebug //安装 app 的 debug 包到手机上 gradlew app:uninstallDebug //卸载手机上 app 的 debug 包 gradlew app:uninstallRelease //卸载手机上 app 的 release 包 gradlew app:uninstallAll //卸载手机上所有 app 的包
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
这些都是基本的命令,在实际项目中会根据不同的配置,会对这些task 设置不同的依赖。比如 默认的 assmeble 会依赖 assembleDebug 和assembleRelease,如果直接执行assmeble,最后会编译debug,和release 的所有版本出来。如果我们只需要编译debug 版本,我们可以运行assembleDebug。
除此之外还有一些常用的新增的其他命令,比如 install命令,会将编译后的apk 安装到连接的设备。
lint 检测
- 忽略编译器的 lint 检查
android { lintOptions { abortOnError false } }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
buildTypes 定义了编译类型
android{ buildTypes { release { minifyEnabled true //打开混淆 proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } debug { minifyEnabled false //关闭混淆 proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
productFlavors 多渠道打包
AndroidManifest.xml 里设置动态渠道变量
<meta-data android:name="UMENG_CHANNEL" android:value="${UMENG_CHANNEL_VALUE}" />
-
1
-
2
-
3
在 build.gradle 设置 productFlavors , 这里假定我们需要打包的渠道为酷安市场、360、小米、百度、豌豆荚。
android { productFlavors { kuan { manifestPlaceholders = [UMENG_CHANNEL_VALUE: "kuan"] } xiaomi { manifestPlaceholders = [UMENG_CHANNEL_VALUE: "xiaomi"] } qh360 { manifestPlaceholders = [UMENG_CHANNEL_VALUE: "qh360"] } baidu { manifestPlaceholders = [UMENG_CHANNEL_VALUE: "baidu"] } wandoujia { manifestPlaceholders = [UMENG_CHANNEL_VALUE: "wandoujia"] } } }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
或者批量修改
android { productFlavors { kuan {} xiaomi {} qh360 {} baidu {} wandoujia {} } productFlavors.all { flavor -> flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name] } }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
这样在打包的时候就可以选择渠道了
或者用命令打包 ,比如:
gradlew assembleWandoujiaRelease //豌豆荚 release 包 gradlew assembleWandoujiaDebug //豌豆荚 debug 包
-
1
-
2
-
3
-
4
多渠道设置包名
有时候我们需要分渠道设置 applicationId 、友盟的 appkey 、友盟渠道号。
productFlavors { google { applicationId "com.wifi.cool" manifestPlaceholders = [ UMENG_APPKEY_VALUE : "456789456789", UMENG_CHANNEL_VALUE: "google", ] } baidu{ applicationId 'com.wifi.hacker' manifestPlaceholders = [ UMENG_APPKEY_VALUE : "123456789789", UMENG_CHANNEL_VALUE : "baidu", ] } }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
Signing 签名
在 android 标签下添加 signingConfigs 标签,如下:
android { signingConfigs { config { keyAlias 'yiba' keyPassword '123456' storeFile file('C:/work/Key.jks') storePassword '1234567' } } }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
可以在 release 和 debug 包中定义签名,如下:
android { signingConfigs { config { keyAlias 'yiba' keyPassword '123456' storeFile file('C:/work/Key.jks') storePassword '1234567' } } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' signingConfig signingConfigs.config } debug { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' signingConfig signingConfigs.config } } }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
依赖管理
1、依赖 jcenter 包
每个库名称包含三个元素:组名:库名称:版本号
compile 'com.android.support:appcompat-v7:25.0.0'
- 1
2、依赖本地 module
compile project(':YibaAnalytics')
-
1
-
2
3、依赖 jar 包
-
1、把 jar 包放在 libs 目录下
-
2、在 build.gradle 中添加依赖
dependencies { compile files('libs/YibaAnalytics5.jar') }
-
1
-
2
-
3
4、依赖 aar 包
-
1、把 aar 包放到 libs 目录下
-
2、在 build.gradle 中添加依赖
repositories { flatDir { dirs 'libs' } } dependencies { compile(name:'YibaAnalytics-release', ext:'aar') }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
如图所示:
5、自定义依赖包目录
当我们的 aar 包需要被多个 module 依赖时,我们就不能把 aar 包放在单一的 module 中,我们可以在项目的根目录创建一个目录,比如叫 aar 目录,然后把我们的 aar 包放进去,如图所示:
在项目的根目录的 build.gradle 的 allprojects 标签下的 repositories 添加 :
flatDir { dirs '../aar' }
-
1
-
2
-
3
../aar
表示根目录下的 aar 文件夹。
如图所示:
然后就可以添加依赖了,如下所示:
compile(name:'YibaAnalytics-release', ext:'aar')
- 1
6、依赖配置
有些时候,你可能需要和sdk协调工作。为了能顺利编译你的代码,你需要添加SDK到你的编译环境。你不需要将sdk包含在你的APK中,因为它早已经存在于设备中,所以配置来啦,我们会有5个不同的配置:
-
compile
-
apk
-
provided
-
testCompile
-
androidTestCompile
compile是默认的那个,其含义是包含所有的依赖包,即在APK里,compile的依赖会存在。
apk的意思是apk中存在,但是不会加入编译中,这个貌似用的比较少。
provided的意思是提供编译支持,但是不会写入apk。
7、排除依赖兼容包
有时候我们在引入依赖包的时候,会额外的引入 v7, v4 的包,对我们的项目造成额外的负担,我们需要把这个兼容包排除,可以使用 exclude 就能做到。
compile('com.google.firebase:firebase-ads:11.0.4', { exclude group: 'com.android.support' //排除v7 , v4 包 })
-
1
-
2
-
3
native包(so包)
用c或者c++写的library会被叫做so包,Android插件默认情况下支持native包,你需要把.so文件放在对应的文件夹中:
注意
jniLibs 目录应该和 Java 目录在同一级
defaultConfig 详解
defaultConfig 对应的是 ProductFlavor 类。
resConfigs : 过滤语言
如果你的app中仅支持1,2种语言,但是可能引用的lib库包含多种其他语言的strings资源,这个时候我们可以通过resConfig指定我们需要的strings资源。
android { defaultConfig { applicationId "com.yiba.sharewe.lite.activity" minSdkVersion 14 targetSdkVersion 24 versionCode 46 versionName "1.74" resConfigs 'en', 'zh-rCN' ,'es' //本次打包,只把 en(英文)、zh-rCN(中文简体)、es(西班牙语)打进保内,其他语言忽略 } }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
resConfigs : 过滤 drawable文件夹的资源
一般情况下,我们打完包,res 下面的资源如图所示:
现在加上资源过滤规则:
android { defaultConfig { applicationId "com.wifi.analytics" minSdkVersion 9 targetSdkVersion 25 versionCode 1 versionName "1.0" resConfigs "hdpi" //打包的时候只保留 drawable-xhdpi 文件夹里面的资源 } }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
这次我们打包效果如下:
buildTypes 详解
官方文档
buildTypes{}对应的是 BuildType 类
继承关系
BuildType 继承 DefaultBuildType ; DefaultBuildType 继承 BaseConfigImpl ;
BaseConfigImpl --- DefaultBuildType --- BuildType
-
1
-
2
-
3
buildTypes的属性:
name:build type的名字 applicationIdSuffix:应用id后缀 versionNameSuffix:版本名称后缀 debuggable:是否生成一个debug的apk minifyEnabled:是否混淆 proguardFiles:混淆文件 signingConfig:签名配置 manifestPlaceholders:清单占位符 shrinkResources:是否去除未利用的资源,默认false,表示不去除。 zipAlignEnable:是否使用zipalign工具压缩。 multiDexEnabled:是否拆成多个Dex multiDexKeepFile:指定文本文件编译进主Dex文件中 multiDexKeepProguard:指定混淆文件编译进主Dex文件中
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
buildType的方法:
1.buildConfigField(type,name,value):添加一个变量生成BuildConfig类。 2.consumeProguardFile(proguardFile):添加一个混淆文件进arr包。 3.consumeProguardFile(proguardFiles):添加混淆文件进arr包。 4.externalNativeBuild(action):配置本地的build选项。 5.initWith:复制这个build类型的所有属性。 6.proguardFile(proguardFile):添加一个新的混淆配置文件。 7.proguradFiles(files):添加新的混淆文件 8.resValue(type,name,value):添加一个新的生成资源 9.setProguardFiles(proguardFileIterable):设置一个混淆配置文件。
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
initWith :复制属性
android { compileSdkVersion 25 buildToolsVersion "25.0.2" defaultConfig { applicationId "com.wifi.analytics" minSdkVersion 9 targetSdkVersion 25 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } debug { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } myType { initWith debug //完全复制 debug 的所有属性‘ minifyEnabled true //自定义打开混淆 } } }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
applicationIdSuffix 、versionNameSuffix :添加后缀
android { compileSdkVersion 25 buildToolsVersion "25.0.2" defaultConfig { applicationId "com.wifi.analytics" minSdkVersion 9 targetSdkVersion 25 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } debug { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' applicationIdSuffix "zhao" //applicationId 追加后缀名 zhao versionNameSuffix "debug" //versionName 追加后缀名 debug1.0 } }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
效果图,如下:
buildConfigField: 自定义属性
在 build.gradle 文件中定义 buildConfigField 属性
android { buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' buildConfigField "String", "API_ENV", "\"http://yiba.com\"" //自定义String属性 } debug { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' buildConfigField "String", "API_ENV", "\"http://yiba.com\"" //自定义String属性 } } }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
然后点击同步按钮,然后就可以在 build 目录看到 debug 和 release 信息。
debug 环境下的 BuildConfig 如下:
release 环境下的 BuildConfig 如下:
当然我们也可以在代码中获取自定义的值:
//获取变量值 String API = BuildConfig.API_ENV ;
-
1
-
2
-
3
上面演示了自定义 String 变量,也可以 自定义 int 、boolean
android { buildTypes { debug { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' buildConfigField "String", "API_ENV", "\"http://www.baidu.com\"" //自定义 String 值 buildConfigField "Boolean", "openLog", "true" //自定义 boolean 值 buildConfigField "int", "age", "10" //自定义 int 值 } } }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
Gradle 实现差异化构建
情景1
LeakCanary 是 square 公司出品的一个检测内存泄漏的开源库。
GitHub : https://github.com/square/leakcanary
我们一般这样集成
dependencies { compile 'com.squareup.leakcanary:leakcanary-android:1.5.2' }
-
1
-
2
-
3
然后我们在 Application 类中初始化:
public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); LeakCanary.install(this); } }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
但是这样集成有一个弊端,就是 debug 和 release 包都会把 LeakCanary 的源码打进去,如果我们在 release 包中不把 LeakCanary 源码打进去,怎么办? 还好 LeakCanary 给我们提供了一个方法,方法如下:
dependencies { //打 debug 包 debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.1' //打 release 包 releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.1' }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
leakcanary-android-no-op 是一个空壳,里面有2个空类,所以就可以避免把 LeakCanary 源码打进 release 包。但是这种方式有个缺陷,如果一些开源库没有提供 releaseCompile 库,那我们改怎么办了?下面的情景2 就会讲到解决方案。
情景2
Stetho 是 Faceboo k开源的Andorid调试工具。当你的应用集成Stetho时,开发者可以访问Chrome,在Chrome Developer Tools中查看应用布局,网络请求,sqlite,preference 等等。
官网:http://facebook.github.io/stetho/
从官网可以看到 stetho 没有提供 releaseCompile 包 , 情景1 的方案就不能用了。新的思路集成方案如下:
dependencies { debugCompile 'com.facebook.stetho:stetho:1.5.0' }
-
1
-
2
-
3
在 src 目录下创建 debug 目录、release 目录 ,然后分别在 debug 目录 和 release 目录 创建 java 目录 , 在 java 目录中创建包名,比如: com.app
, 如下图所示:
debug 目录下创建 SDKManage 类 ,如下 :
public class SDKManager { public static void init(Context context) { //初始化 Stetho Stetho.initializeWithDefaults(context); } }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
release 目录下创建 SDKManage 类 ,如下 :
public class SDKManager { public static void init(Context context) { //这是一个空方法,目的是不引入 Stetho 源码 } }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
在住项目中的 MyApplication 类,并且完成 Stetho 的初始化,如下:
public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); SDKManager.init(this); } }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
这样我们便完成了简单的差异化构建, 打出来的 release 包就没有 Stetho 源码。
SourceSet
SourceSet 简介
SourceSet 可以定义项目结构,也可以修改项目结构。Java插件默认实现了两个SourceSet,main 和 test。每个 SourceSet 都提供了一系列的属性,通过这些属性,可以定义该 SourceSet 所包含的源文件。比如,java.srcDirs,resources.srcDirs 。Java 插件中定义的其他任务,就根据 main 和 test 的这两个 SourceSet 的定义来寻找产品代码和测试代码等。
SourceSet 定义源码目录
在 Android 项目中,我们可以在 src/main/java
目录新建 Java 文件,如下图所示:
现在我们在 src 目录下,新建 test1 目录 ,发现不能在 test1 目录中新建 Java 文件,如下图所示:
为什么在 test1 目录不能新建 Java 文件,因为 Gradle 中 SourceSet 默认定义的源码文件路径是src/main/java
, 其他的文件下下面的源码我们自然无法访问。解决这个问题也很简单,我们需要在 SourceSet 中增加一个源码路径即可。如下所示:
android { sourceSets { main { java { srcDir 'src/test1' //指定源码目录 } } } }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
然后同步一下,就可以在 test1 目录中新建 Java 文件了。如下图所示:
当然我们也可以同时指定多个源码目录,比如同时指定 test1 , test2 , test3 为源码目录。
android { sourceSets { main { java { srcDir 'src/test1' //指定 test1 为源码目录 srcDir 'src/test2' //指定 test2 为源码目录 srcDir 'src/test3' //指定 test3 为源码目录 } } } }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
或者 这样写 :
android { sourceSets { main { java.srcDirs( 'src/test1' , 'src/test2' ,'src/test3' ) } } }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
效果如下图所示:
SourceSet 定义资源目录
定义 test1 目录 Java 源代码路径、res 资源目录。目录结构如下图所示:
android { sourceSets { main { java.srcDirs('src/test1/java') //定义java 源代码 res.srcDirs('src/test1/res') //定义资源目录(layout , drawable,values) } } }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
SourceSet 实现 layout 分包
对于一个大项目来说,页面太多,布局文件就很多,有时在众多布局文件中找某个模块的布局文件,很是痛苦,为了解决这个问题,我们可以在创建多个 layout 目录,不同模块的布局文件放在不同的 layout 目录中,这样查找起来,就容易很多。
例子:
比如我们的项目中,有两个模块分别为:登录、注册。
-
第一步:把项目中 layout 文件夹改名字为 layouts
-
第二步:在 layouts 目录下,分别创建 login 、register 目录 。
-
第三步:分别在 login 、register 目录下创建 layout 目录。注意这一步是必须的,否则会报错。
-
第四步:把 登录布局文件、注册布局文件 分别放在 第三步创建的对应的 layout 目录下。
效果图如下:
SourceSet 实现如下:
android { sourceSets { main { res.srcDirs 'src/main/res/layouts/login' //定义登录布局目录 res.srcDirs 'src/main/res/layouts/register' //定义注册布局目录 } } }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
SourceSet 定义 AndroidManifest 文件
指定 test1 目录下的 AndroidManifest 文件。项目结构如下图所示:
代码如下:
android { sourceSets { main { manifest.srcFile 'src/test1/AndroidManifest.xml' } } }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
在组件化开发中, 我们需要针对 debug 与 release 模式下, 指定不同的 Manifest 文件, 代码如下:
`android { def appDebug = false; buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android
《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享
.txt’), ‘proguard-rules.pro’ appDebug = false; } debug { minifyEnabled false proguardFiles getDefaultProguardFile(‘proguard-android.txt’), ‘proguard-rules.pro’ appDebug = false; } } sourceSets { main { if (appDebug) { manifest.srcFile ‘src/test1/AndroidManifest.xml’ } else { manifest.srcFile ‘src/main/AndroidManifest.xml’ } } } }`
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
SourceSet 定义 assets 目录
Android Studio 项目目录中,assets 默认目录如下:
如何重新定义 assets 目录 。在项目的根目录下创建 assets 目录,如下图所示:
sourceSets 定义代码如下:
android { sourceSets { main { assets.srcDirs = ['assets'] } } }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
SourceSet 定义其他资源
android { sourceSets { main { jniLibs.srcDirs //定义 jni 目录 aidl.srcDirs //定义 aidl 目录 } } }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
applicationVariants
定义 versionName 、VersionCode
在打包的时候分 debug 、release 版本 , 需要控制 versionName
android { applicationVariants.all { variant -> def flavor = variant.mergedFlavor def versionName = flavor.versionName if (variant.buildType.isDebuggable()) { versionName += "_debug" //debug 名字 } else { versionName += "_release" //release 名字 } flavor.versionName = versionName } }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
定义 APK 包的名字
apply plugin: 'com.android.application' android { defaultConfig { applicationId "android.plugin" minSdkVersion 14 targetSdkVersion 25 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } debug { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } //定义渠道 productFlavors { xiaomi { //小米 } wandoujia { // 豌豆荚 } } //打包命名 applicationVariants.all { variant -> variant.outputs.each { output -> //定义一个新的apk 名字。 // 新名字 = app 名字+ 渠道号 + 构建类型 + 版本号 + 当前构建时间 def apkName = "appName_${variant.flavorName}_${buildType.name}_v${variant.versionName}_${getTime()}.apk"; output.outputFile = new File(output.outputFile.parent, apkName); } } } //获取当前时间 def getTime() { String today = new Date().format('YY年MM月dd日HH时mm分') return today }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
34
-
35
-
36
-
37
-
38
-
39
-
40
-
41
-
42
-
43
-
44
-
45
-
46
-
47
-
48
-
49
-
50
-
51
-
52
-
53
-
54
这篇关于Android Gradle基础介绍,Android面试送分题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!