Skip to content

Instantly share code, notes, and snippets.

@olivierperez
Last active May 24, 2023 09:25
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save olivierperez/a166471dbcc81bddb5a6257c0cd38cef to your computer and use it in GitHub Desktop.
Save olivierperez/a166471dbcc81bddb5a6257c0cd38cef to your computer and use it in GitHub Desktop.
Useful tricks for Android gradle files
- build time
- ci_job
- dependencies
- force a lang for a specific flavor
- gcm flavorish google-services.json
- git commit count
- git sha
- isIdeBuild
- nice buildConfigField
- private signing certificate
- specify the file name of production release
- tests shown in console
def VERSION_NAME = "1.0"
def buildTime() {
new Date().format("yyyy-MM-dd'T'HH:mm:ss'Z'", TimeZone.getTimeZone("UTC")
}
android {
buildTypes {
release {
versionName VERSION_NAME
// and/or
buildConfigField "String", "BUILD_TIME", "\"\""
}
debug {
versionName VERSION_NAME + "-" + buildTime()
// and/or
buildConfigField "String", "BUILD_TIME", "\"${buildTime()}\""
// Example: Crashlytics.setString("Build time", BuildConfig.BUILD_TIME);
}
}
}
task ci_job {
group = 'ci'
}
if (project.hasProperty('buildVariant') && !project.property('buildVariant').isEmpty()) {
def checkVariant = '[RegularRelease]'
def testVariant = '[MockDebug]'
project.afterEvaluate {
/* Assemble */
def assemble = tasks["assemble${buildVariant}"]
assemble.mustRunAfter clean
/* Unit test */
def unitTests = project.tasks["test${testVariant}UnitTest"]
unitTests.mustRunAfter assemble
unitTests.onlyIf {
!project.hasProperty('skipUnitTest') || project.property('skipUnitTest') != 'true'
}
/* Quality */
task quality
quality.dependsOn project.tasks["lint${checkVariant}"]
quality.dependsOn project.tasks["findbugs${checkVariant}"]
quality.dependsOn project.tasks["checkstyle"]
quality.onlyIf {
!project.hasProperty('skipQuality') || project.property('skipQuality') != 'true'
}
/* Execute all */
ci_job.dependsOn clean
ci_job.dependsOn assemble
ci_job.dependsOn unitTests
ci_job.dependsOn quality
}
} else {
ci_job << {
println "Nothing to do, buildVariant is not wel defined"
}
}
ext.versions = [
dagger : '2.7',
rxAndroid : '1.2.1',
rxJava : '1.1.6',
// etc...
]
ext.deps = [
// Dependency injection
dagger : "com.google.dagger:dagger:${versions.dagger}",
daggerCompiler : "com.google.dagger:dagger-compiler:${versions.dagger}",
// RxJava
rxAndroid : "io.reactivex:rxandroid:${versions.rxAndroid}",
rxJava : "io.reactivex:rxjava:${versions.rxJava}",
rxJavaProguard : "com.artemzin.rxjava:proguard-rules:${versions.rxJava}.0",
]
dependencies {
// Dependency injection
compile deps.dagger
apt deps.daggerCompiler
// RxJava
compile deps.rxAndroid
compile deps.rxJava
compile deps.rxJavaProguard
}
// .gitignore
/app/src/prod/res-gen
// file: app/build.gradle
apply from: '../forceRU.gradle'
android {
sourceSets {
prod {
res.srcDirs += ['src/prod/res-gen']
}
}
}
// file: forceRU.gradle
project.afterEvaluate {
android {
applicationVariants.all { variant ->
logger.trace("variant.name: ${variant.name}")
logger.trace("variant.productFlavors[0].name: ${variant.productFlavors[0].name}")
// Force RU values only for prod flavor
if ("prod".equals(variant.productFlavors[0].name)) {
def forceRU = task("forceRU${variant.name.capitalize()}")
variant.mergeResources.dependsOn forceRU
forceRU << {
logger.info("Forcing strings to RU...")
File valuesRU = file("src/main/res/values-ru")
if (valuesRU.isDirectory() && valuesRU.list().length > 0) {
logger.debug("Directory \"" + valuesRU.path + "\" exists")
copy {
from "src/main/res/values-ru/"
into 'src/prod/res-gen/values/'
include '*'
}
} else {
throw new RuntimeException("\"" + valuesRU.path + "\" is not a drectory or is empty.")
}
}
}
}
}
}
// Put google-services.json in your flavors directories
// Then Git-ignore "app/google-services.json"
gradle.taskGraph.beforeTask { Task task ->
if (task.name ==~ /process.*GoogleServices/) {
android.applicationVariants.all { variant ->
if (task.name ==~ /(?i)process${variant.name}GoogleServices/) {
def envFlavor = variant.productFlavors.get(0).name
copy {
from "./src/${envFlavor}"
into '.'
include 'google-services.json'
}
}
}
}
}
def MAJOR_VERSION = 1
def MINOR_VERSION = 0
def gitCount() {
def cmd = 'git rev-list --count HEAD'
cmd.execute().text.trim().toInteger()
}
android {
productFlavors {
dev {
versionCode MAJOR_VERSION * 100000 + MINOR_VERSION * 1000
// and/or
buildConfigField "String", "GIT_COUNT", "\"\""
}
prod {
versionCode MAJOR_VERSION * 100000 + MINOR_VERSION * 1000 + getCount()
// and/or
buildConfigField "String", "GIT_COUNT", "\"${gitCount()}\""
// Example: Crashlytics.setString("Git Count", BuildConfig.GIT_COUNT);
}
}
}
def VERSION_NAME = "1.0"
def gitSha() {
// def cmd = 'git log -1 --format="%h"'
def cmd = 'git rev-parse --short HEAD'
cmd.execute().text.trim()
}
android {
productFlavors {
dev {
versionName VERSION_NAME
// and/or
buildConfigField "String", "GIT_SHA", "\"\""
}
prod {
versionName "$VERSION_NAME-${gitSha()}"
// and/or
buildConfigField "String", "GIT_SHA", "\"${gitSha()}\""
// Example: Crashlytics.setString("Git SHA", BuildConfig.GIT_SHA);
}
}
}
// Trick 1
allprojects {
ext {
isCIBuild = System.getenv('BUILD_ID')
}
}
// Trick 2
allprojects {
ext {
isIdeBuild = project.properties['android.injected.invoked.from.ide'] == 'true'
}
}
buildTypes {
def ENABLE_LOGS = "ENABLE_LOGS"
def BOOLEAN = "boolean"
def TRUE = "true"
def FALSE = "false"
release {
buildConfigField BOOLEAN, ENABLE_LOGS, FALSE
}
releaseWithLogs {
buildConfigField BOOLEAN, ENABLE_LOGS, TRUE
}
debug {
buildConfigField BOOLEAN, ENABLE_LOGS, TRUE
}
}
signingConfigs {
release {
storeFile file(System.env.MYAPP_PRIVATE_KEY)
keyAlias System.env.MYAPP_ALIAS
storePassword System.env.MYAPP_STORE_PASSWORD
keyPassword System.env.MYAPP_PASSWORD
}
}
buildTypes {
applicationVariants.all { variant ->
variant.outputs.each { output ->
if (variant.productFlavors[0].name.equals("prod")) {
output.outputFile = new File(
output.outputFile.parent,
output.outputFile.name.replace(
"app-prod-regular-release-unsigned",
"monApp-prod-unsigned-" + versionName + "-" + versionCode
)
);
}
}
}
}
testOptions.unitTests.all {
testLogging {
events 'passed', 'skipped', 'failed', 'standardOut', 'standardError'
outputs.upToDateWhen { false }
showStandardStreams = true
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment