本文共 10311 字,大约阅读时间需要 34 分钟。
转自
http://blog.csdn.net/crazy1235/article/details/50465885
Google I/O 2013大会上发布了AS,如今已经发展到2.0-beta版本。相信已经大部分人做Android开发的都已经由Eclipse IDE转为AS IDE。
随着AS版本的更迭,也带来不少为为开发者提供便利的工具。比如这篇blog所描述的:
本人从AS1.2版本开始使用,如今也用了大半年了。现将使用过程中的一些经验分享给大家。
gradle的基本配置
apply plugin: 'com.android.application'android { compileSdkVersion 23 buildToolsVersion "23.0.2" defaultConfig { applicationId "com.jacksen.multichannel" minSdkVersion 14 targetSdkVersion 23 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } }}dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:23.1.1' compile 'com.android.support:design:23.1.1'}
- 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
上面的就是一个项目gradle的基本配置。
apply plugin: 'com.android.application'
表示该module是一个app module,应用了com.android.application插件,也就是主程序。如果是一个第三方library,则应该是app plugin: ‘com.android.library’
buildTypes { } 表示构建类型。包括release和debug两种。可以在这里面配置启用混淆、zipAlign、签名信息等。
dependencies { } 里面是项目的依赖信息,包括jar包和第三方库等信息。
ApplicationId与PackageName的区别:
此前使用eclipse进行开发的时候,应用程序的包名是由manifest文件的package属性决定的:
"http://schemas.android.com/apk/res/android" package= "com.xxx.xxxx" android:versionCode= "1" android:versionName= "1.0" >
然而在使用gradle构建的时候却多了一个applicationId。通常gradle中的applicationId和Manifest中的package是一样的。其实可以使二者一致。
官方解释说是:applicationId是你的应用在商店的唯一标识。而package是引用资源的路径名,也就是R文件的包名。
上面我们说到二者可以不一致,我们可以通过对不同的Flavor设置不同的applicationId,从而可以导出不同“包名”的apk,而不需要修改其他的代码。后面会仔细说明。
gradle的签名配置
关于签名的概念不懂得,可以参考这篇blog:
我们通常运行项目都是使用debug的签名。不过有些使用到第三方sdk的时候,需要用到正式版的签名,通过打包正式签名的方式又不好调试。不过我们可以在gradle里面配置正式版的签名。
android { signingConfigs { config_release { keyAlias 'releaseKey' keyPassword '123456' storePassword '123456' storeFile file('key/releaseKey.jks') } config_debug { keyAlias 'debugKey' keyPassword '123456' storePassword '123456' storeFile file('key/debugKey.jks') } } .....}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
这里配置了两个签名。jsk都放在app下面的key文件夹中。所以使用的是相对路径。
之前有人问我是怎么知道keyAlias 、keyPassword这些语法的。其实在项目的【Project Structure】中都可以找到。
配置buildTypes
一般在buildTypes{ }里面配置两个(release和debug):
buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' shrinkResources true //移除无效的resource文件,必须允许ProGuard才能生效 zipAlignEnabled true buildConfigField "boolean", "APP_TYPE", "true" manifestPlaceholders = [APP_NAME: "@string/app_name_release"] signingConfig signingConfigs.config } debug { buildConfigField "boolean", "APP_TYPE", "false"// manifestPlaceholders = [APP_NAME: "@string/app_name_debug"] applicationIdSuffix 'debug' } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
这里可配置的信息很多,比如:是否可以是debug模式、签名配置、混淆文件等。
配置productFlavor
多渠道打包,关键就在于定义多个productFlavor。
在一个flavor里面可配置的信息很多。
productFlavors { flavor_release { buildConfigField "boolean", "APP_TYPE", "false" applicationId 'com.jacksen.multichannel.release' signingConfig signingConfigs.config_release minSdkVersion 9 targetSdkVersion 15 versionCode 2 versionName '2.0.1' } flavor_debug { minSdkVersion 10 applicationId 'com.jacksen.multichannel.debug' signingConfig signingConfigs.config_debug versionCode 5 versionName '5.0' } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
最主要的是可以在这里配置applicationId,就是我们上面一开始说的打包多个不同“包名”的apk。
这样有一个应用场景就是,我们一般通过debug版本进行测试之后,在进行release版本的测试。不过同一个applicationId的apk在一个测试机上只能存在一个。现在我们通过配置多个flavor对应多个applicationId,就可以在测试机上运行测试版和正式版两个apk了。
productFlavors{ } 与 buildTypes{ }里面的配置是多对多的关系。
比如:
buildTypes { release {...} debug {...}}productFlavors { flavor_1 {...} flavor_2 {...}}
此时的配置可以打包出四个apk,分别是:
我们在使用as的打包工具时,可以选择打包某一个Build type的某一个或多个Flavors:
如果在gradle里面配置了签名信息,那么在【Generate Signed APK】的第一步填写的签名信息是以在gradle里面配置并引用的为准。
我们还可以借助gradlew命令来打包:
比如打包flavor_1对应的release和debug版本:
打包flavor_2对应的release版本:
实际上,我们不用再记住这些命令。AS里面的gradle插件就可以实现。
在AS的右侧会有【Gradle】tab页面。打开之后,先刷新一下。会看到如下图示:
通过双击右边的命令打包不同的版本。
除了build下面的命令,还有其他的命令,大家都可以尝试一下,根据名字应该就能知道什么意思,这里不多介绍了。
manifest占位符
在打包多个版本的时候,会遇到修改应用名称等需求。不同的flavor有要求不通的名称。此时可以在Manifest文件中使用占位符,然后在build.gradle中替换占位符就行了。
首先定义占位符:
application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="${APP_NAME}" android:supportsRtl="true" android:theme="@style/AppTheme"> name= ".LoginActivity" android:label= "${APP_NAME}"> name= "android.intent.action.MAIN" /> name= "android.intent.category.LAUNCHER" /> application>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
在build.gradle中替换:
buildTypes { release { manifestPlaceholders = [APP_NAME: "@string/app_name1"] } debug { manifestPlaceholders = [APP_NAME: "@string/app_name1"] } }
productFlavors { flavor_1 { manifestPlaceholders = [APP_NAME: "@string/app_name1"] } flavor_2 { manifestPlaceholders = [APP_NAME: "@string/app_name2"] } }
如果在productFlavors和buildTypes里面都进行了替换,那么是以productFlavors里面的为准。
如果不区分productFlavors和buildTypes的话,也可以在defaultConfig里进行替换:
defaultConfig { manifestPlaceholders = [APP_NAME: "@string/app_name_release"] }
其实defaultConfig也是productFlavors的一个子集。
添加自定义字段
Gradle在generateSources阶段为每一个flavor生成两个BuildConfig.java文件(对应在release和debug文件夹下)。
BuildConfig类默认会提供一些常量字段。
public final class BuildConfig { public static final boolean DEBUG = Boolean.parseBoolean("true"); public static final String APPLICATION_ID = "com.jacksen.multichannel"; public static final String BUILD_TYPE = "debug"; public static final String FLAVOR = ""; public static final int VERSION_CODE = 1; public static final String VERSION_NAME = "1.0";}
虽然通过上面的操作,我们可以同时打包出一个debug版本和一个release版本。但是我们还需要运行的时候有不同的表现。比如,release版本不显示一些控件。
令人惊奇的是,我们可以通过buildConfigField在gradle里面自定义一些字段。
buildConfigField "String", "APP_TYPE", "debug"
我们可以查看buildConfigField的源码:
/** * Adds a new field to the generated BuildConfig class. * * The field is generated as: <type> <name> = <value>;
* *
This means each of these must have valid Java content. If the type is a String, then the * value should include quotes. * * @param type the type of the field * @param name the name of the field * @param value the value of the field */ public void buildConfigField( @NonNull String type, @NonNull String name, @NonNull String value) { ClassField alreadyPresent = getBuildConfigFields().get(name); if (alreadyPresent != null) { logger.info( "BuildType(${getName()}): buildConfigField '$name' value is being replaced: ${alreadyPresent.value} -> $value"); } addBuildConfigField(AndroidBuilder.createClassField(type, name, value)); }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
注释写的很详细。该方法就是添加一个field到BuildConfig类中。三个参数都是不可为空的。
添加完毕之后,就可以在代码中使用了:
textView.setText("BuildConfig.APP_TYPE : " + BuildConfig.APP_TYPE)
自定义导出APK的名称
我直接上代码吧。
/*applicationVariants.all { variant -> variant.outputs.each { output -> def outputFile = output.outputFile if (outputFile != null && outputFile.name.endsWith('.apk')) {// def fileName = outputFile.name.replace(".apk", "-${defaultConfig.versionName}.apk") def apkType = "" if (variant.flavorName.equals("releaseFlavor")){ apkType = "release" }else if(variant.flavorName.equals("debugFlavor")){ apkType = "debug" } def fileName = new File(output.outputFile.getParent(), "app-" + apkType + "-${variant.versionName}.apk")// output.outputFile = new File(outputFile.parent, fileName) output.outputFile = fileName } } }*/ applicationVariants.all { variant -> variant.outputs.each { output -> def outputFile = output.outputFile if (outputFile != null && outputFile.name.endsWith('.apk')) { def fileName = outputFile.name.replace(".apk", "-${defaultConfig.versionCode}-${defaultConfig.versionName}.apk") output.outputFile = new File(outputFile.parent, fileName) } } }
- 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
这里有两种方式,大家运行一下测试一下就明白了。
以上就是我对gradle的一些认识~~~
Demo下载
欢迎star~~
参考:
此篇blog到此结束~
感谢大家支持!如有错误,请指出~
谢谢~