hands on the gradle
TRANSCRIPT
Good to be programmer…
Build problems (before Gradle)
● Several weakly compatible versions of building
● Difficult dependency management
● Hard to generate several variants of the application
What is gradle?• Ant makes you reinvent the wheel every time
• Ant build scripts can get hard to maintain very quickly
• Maven does not care about your project, you must make sure
that your project works well with Maven – it enforces
convention
• You must do everything “The Maven Way” or implement
custom plugins
• Gradle combines the power and flexibility of Ant with
dependency management of Ivy and conventions of Maven
• Gradle is a programming build tool with DSL based on Groovy
Why gradle?
• Built-in dependency management through Maven and/or Ivy
• Make it easy to configure, extend and customize the build process
• Make it easy to reuse code and resources
• Make it easy to create several variants of an application, either for multi-apk distribution or for different flavors of an application
• Good IDE Integration
Basiс Gradle Configbuildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.14.0'
}
}
apply plugin: 'com.android.application'
android {
compileSdkVersion 19
buildToolsVersion "21.0.2"
}
Dependencies• Maven, Ivy – artifacts
Remote and local
• Local files
Jar
Other gradle-projects
AAR
Dependencies
dependencies {
compile 'com.android.support:support-v4:21.0.0‘
compile 'org.apache.commons:commons-collections4:4.0'
compile project(':libraries:catalitClient')
compile files('libs/AF-Android-SDK-v2.3.1.11.jar')
compile 'com.actionbarsherlock:actionbarsherlock:4.4.0@aar'
}
• Example: debug / release
• Might have own
o Dependencies
o Resources
o Special settings
Build customization
Build types
• Default
o debug
o release
• What can configure
o packageNameSuffix
o BuildConfig.java
o Own recourses/code
o Other
Build customizationandroid {
defaultConfig {
applicationId 'ru.litres.android'
minSdkVersion 8
targetSdkVersion 19
versionCode 20141009
versionName "2.14.5"
}
buildTypes {
debug {
packageNameSuffix ".debug"
buildConfigField “String", " HOST_URL ", ‘”debug.litres.ru”’
}
release {
buildConfigField “String", “HOST_URL", ‘”release.litres.ru”’
}
}
Build flavors
• Ability to easy generate few different apk.
• Example
o Paid / free
o Partner app
o Building multiple apk (abi, density)
o Other cases
Build customizationandroid {
flavorDimensions 'store'
productFlavors {
googlePlay {
flavorDimension 'store'
}
samsungApps {
flavorDimension 'store'
buildConfigField "boolean", "IS_SAMSUNG_APPS_BUILD", "true"
}
amazon {
flavorDimension 'store'
buildConfigField "boolean", "IS_AMAZON_BUILD", "true"
}
}
}
Build variants
Flavor
Build
Free
Paid
ReleaseDebug
PaidDebug
FreeDebug FreeRelease
PaidRelease
BuildVariant
Source sets
• src/
main/
• java/
• res/
• …AndroidManifest.xml
• paid/
• free/
Source sets for BuildTypeanв Flavor
• src/
• main/
• release/
• debug/
• free/
• paid/
Build the app
main
free
debug
Resources and placeholdersandroid {
productFlavors {
readFree{
applicationId 'ru.litres.android.readfree'
versionCode 20141009
versionName "2.14.5"
resValue 'string', 'provider_search_authorities', 'ru.litres.android.readfree.SearchProvider'
resValue 'string', 'package_name', 'ru.litres.android.readfree‘
manifestPlaceholders = [adviatorPackage: "av111363.android",
adviatorServiceName: "av111363.android.S111363",
adviatorAppId: “app id",
adviatorAppKey: “somes secret"]
}
}
}
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="ru.litres.android">
<permission
android:name="${applicationId}.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="${applicationId}.permission.C2D_MESSAGE" />
<application>
<provider
android:name="ru.litres.android.providers.BookSuggestionProvider"
android:authorities="@string/provider_search_authorities" />
<meta-data
android:name="ADVIATOR_APPID"
android:value="id:${adviatorAppId}" />
<meta-data
android:name="ADVIATOR_APPKEY"
android:value="key:${adviatorAppKey}" />
<service
android:name="com.${adviatorServiceName}"
android:exported="false" />
</application>
</manifest>
Build customizationres/xml/searchable.xml
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:hint="@string/searchable_hint"
android:label="@string/app_name"
android:searchSuggestAuthority="@string/provider_search_authorities"
android:voiceSearchMode="showVoiceSearchButton|launchRecognizer" />
res/xml/main_settings.xml
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory android:title="@string/settings_info" >
<Preference android:title="@string/about_program" >
<intent
android:targetClass="ru.litres.android.ui.AboutActivity"
android:targetPackage="@string/package_name" />
</Preference>
</PreferenceCategory>
</PreferenceScreen>
Splitsandroid {
flavorDimensions 'store‘, ‘abi’
productFlavors {
arm {
flavorDimension 'abi'
versionCode Integer.parseInt("1" + defaultConfig.versionCode)
ndk {
abiFilter "armeabi"
}
}
armv7 {
flavorDimension 'abi'
versionCode Integer.parseInt("2" + defaultConfig.versionCode)
ndk {
abiFilter "armeabi-v7a"
}
}
}
}
Splitsandroid {
project.ext.abiVersionCodesPrefix = ['armeabi':1, 'armeabi-v7a':2, 'mips':4, x86':6]
splits {
abi {
enable true
reset()
include 'armeabi', 'armeabi-v7a', 'mips', 'x86'
universalApk false
}
}
applicationVariants.all { variant ->
variant.outputs.each { output ->
output.versionCodeOverride =
Integer.parseInt(project.ext.abiVersionCodesPrefix.get(output.getFilter(com.android.build.OutputFile.ABI), 0) + "" + variant.mergedFlavor.versionCode)
}
}
}
}
Android Gradle plugin docs SUCK :-(
But community rocks :)
+Android Developer Tools
http://goo.gl/hAnxTf
+Tor Norbye
+Alex Ruiz [gradle, android]
Resources
http://www.gradle.org
http://tools.android.com/tech-docs/new-build-system
http://gradleplease.appspot.com/
https://groups.google.com/forum/#!forum/adt-dev
http://stackoverflow.com/