Files
comaps/android/app/build.gradle
Konstantin Pastbin 44eca9ab5e [android] Streamline Google Play metadata handling
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-05-25 12:30:14 +02:00

413 lines
14 KiB
Groovy

buildscript {
repositories {
google()
mavenCentral()
}
// Detect flavors from the task name.
def taskName = getGradle().getStartParameter().getTaskRequests().toString().toLowerCase()
def isFdroid = taskName.contains('fdroid')
def isBeta = taskName.contains('beta')
dependencies {
classpath libs.android.tools
classpath(libs.triplet.play.publisher)
classpath(libs.huawei.publish)
}
}
repositories {
google()
mavenCentral()
maven { url 'https://www.jitpack.io' } // MPAndroidChart
}
apply plugin: 'com.android.application'
apply plugin: 'com.github.triplet.play'
apply plugin: 'ru.cian.huawei-publish-gradle-plugin'
def run(cmd) {
def stdout = new ByteArrayOutputStream()
exec {
commandLine = cmd
standardOutput = stdout
}
return stdout.toString()
}
import com.github.triplet.gradle.androidpublisher.ReleaseStatus
import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform
def getVersion() {
def isWindows = DefaultNativePlatform.getCurrentOperatingSystem().isWindows()
def bash = isWindows ? 'C:\\Program Files\\Git\\bin\\bash.exe' : 'bash'
def versionCode = Integer.parseInt(run([bash, '../../tools/unix/version.sh', 'android_code']).trim())
def versionName = run([bash, '../../tools/unix/version.sh', 'android_name']).trim()
return new Tuple2(versionCode, versionName)
}
def getCommitMessage() {
return run(['git', '--no-pager', 'show', '-s', '--format=%s%n%n%b', 'HEAD']).trim()
}
def osName = System.properties['os.name'].toLowerCase()
project.ext.appId = 'app.comaps'
project.ext.appName = 'CoMaps'
// I have Java 21 installed, but this doesn't work on MacOS.
//java {
// toolchain {
// languageVersion.set(JavaLanguageVersion.of(17))
// }
//}
android {
namespace 'app.organicmaps'
buildFeatures {
dataBinding = true
buildConfig = true
}
// All properties are read from gradle.properties file
compileSdk propCompileSdkVersion.toInteger()
ndkVersion '27.2.12479018'
defaultConfig {
// Default package name is taken from the manifest and should be app.comaps
def ver = getVersion()
versionCode = ver.V1
versionName = ver.V2
println('Version: ' + versionName)
println('VersionCode: ' + versionCode)
minSdk propMinSdkVersion.toInteger()
targetSdk propTargetSdkVersion.toInteger()
applicationId project.ext.appId
buildConfigField 'String', 'SUPPORT_MAIL', '"android@comaps.app"'
// Should be customized in flavors.
buildConfigField 'String', 'REVIEW_URL', '""'
resourceConfigurations += [project.ext.supportedLocalizations]
externalNativeBuild {
def pchFlag = 'OFF'
if (project.hasProperty('pch')) pchFlag = 'ON'
def njobs = ''
if (project.hasProperty('njobs')) njobs = project.getProperty('njobs')
def enableVulkanDiagnostics = 'OFF'
if (project.hasProperty('enableVulkanDiagnostics')) {
enableVulkanDiagnostics = project.getProperty('enableVulkanDiagnostics')
}
def enableTrace = 'OFF'
if (project.hasProperty('enableTrace')) {
enableTrace = project.getProperty('enableTrace')
}
cmake {
cppFlags '-fexceptions', '-frtti'
// There is no sense to enable sections without gcc's --gc-sections flag.
cFlags '-fno-function-sections', '-fno-data-sections',
'-Wno-extern-c-compat'
arguments '-DANDROID_TOOLCHAIN=clang', '-DANDROID_STL=c++_static',
"-DOS=$osName", '-DSKIP_TESTS=ON', '-DSKIP_TOOLS=ON', "-DUSE_PCH=$pchFlag",
"-DNJOBS=$njobs", "-DENABLE_VULKAN_DIAGNOSTICS=$enableVulkanDiagnostics",
"-DENABLE_TRACE=$enableTrace"
targets 'organicmaps'
}
}
// Use, for example, -Parm32 gradle parameter to build only for armeabi-v7a.
ndk {
abiFilters = new HashSet<>()
if (project.hasProperty('arm32') || project.hasProperty('armeabi-v7a')) {
abiFilters.add('armeabi-v7a')
}
if (project.hasProperty('arm64') || project.hasProperty('arm64-v8a')) {
abiFilters.add('arm64-v8a')
}
if (project.hasProperty('x86')) {
abiFilters.add('x86')
}
if (project.hasProperty('x86_64') || project.hasProperty('x64')) {
abiFilters.add('x86_64')
}
if (abiFilters.isEmpty()) {
abiFilters.add('armeabi-v7a')
abiFilters.add('arm64-v8a')
// For the emulator, chromebooks and some Intel Atom devices.
abiFilters.add('x86_64')
}
println('Building for ' + abiFilters + ' archs.')
}
setProperty('archivesBaseName', appName.replaceAll('\\s','') + '-' + defaultConfig.versionCode)
}
flavorDimensions += 'default'
productFlavors {
// 01 is a historical artefact, sorry.
final int HUAWEI_VERSION_CODE_BASE = 01_00_00_00_00
google {
dimension 'default'
applicationIdSuffix '.google'
versionName = android.defaultConfig.versionName + '-Google'
buildConfigField 'String', 'SUPPORT_MAIL', '"gplay@comaps.app"'
buildConfigField 'String', 'REVIEW_URL', '"market://details?id=app.comaps.google"'
}
// Distributed directly by the project, e.g. in repo releases, chats, etc.
web {
dimension 'default'
versionName = android.defaultConfig.versionName
buildConfigField 'String', 'SUPPORT_MAIL', '"apk@comaps.app"'
}
fdroid {
dimension 'default'
applicationIdSuffix '.fdroid'
versionName = android.defaultConfig.versionName + '-FDroid'
buildConfigField 'String', 'SUPPORT_MAIL', '"fdroid@comaps.app"'
}
huawei {
dimension 'default'
applicationIdSuffix '.huawei'
versionName = android.defaultConfig.versionName + '-Huawei'
versionCode = HUAWEI_VERSION_CODE_BASE + android.defaultConfig.versionCode
buildConfigField 'String', 'SUPPORT_MAIL', '"huawei@comaps.app"'
buildConfigField 'String', 'REVIEW_URL', '"appmarket://details?id=app.comaps"'
}
}
playConfigs {
googleRelease {
enabled.set(true)
}
}
splits.abi {
boolean enabled = project.hasProperty('splitApk')
println ('Create separate apks: ' + enabled)
enable enabled
reset()
include 'x86', 'armeabi-v7a', 'arm64-v8a', 'x86_64'
universalApk true
}
lint {
disable 'MissingTranslation'
// https://github.com/organicmaps/organicmaps/issues/3551
disable 'MissingQuantity', 'UnusedQuantity'
// https://github.com/organicmaps/organicmaps/issues/3550
disable 'ByteOrderMark'
// https://github.com/organicmaps/organicmaps/issues/1077
disable 'CustomSplashScreen'
// https://github.com/organicmaps/organicmaps/issues/3610
disable 'InsecureBaseConfiguration'
abortOnError true
}
gradle.projectsEvaluated {
android.applicationVariants.all { variant ->
def task = variant.name.capitalize()
project.task(type: Exec, "run${task}", dependsOn: "install${task}") {
commandLine android.getAdbExe(), 'shell', 'am', 'start', '-n', "$applicationId/app.comaps.DownloadResourcesActivity", '-a', 'android.intent.action.MAIN', '-c', 'android.intent.category.LAUNCHER'
}
}
}
def securityPropertiesFileExists = file('secure.properties').exists()
if (securityPropertiesFileExists) {
apply from: 'secure.properties'
}
signingConfigs {
debug {
storeFile file('debug.keystore')
storePassword '12345678'
keyAlias 'debug'
keyPassword '12345678'
}
release {
if (securityPropertiesFileExists) {
println('The release signing keys are available')
storeFile file(spropStoreFile)
storePassword spropStorePassword
keyAlias spropKeyAlias
keyPassword spropKeyPassword
} else {
println('The release signing keys are unavailable')
}
}
}
buildTypes {
debug {
applicationIdSuffix '.debug' // Allows to install debug and release builds together
versionNameSuffix '-debug'
jniDebuggable true // Enable jni debug build
zipAlignEnabled true
signingConfig signingConfigs.debug
resValue 'string', 'app_name', 'CoMaps Debug'
// Do not generate separate debug symbols for debug apps, because we don't distribute them.
ndk.debugSymbolLevel = 'none'
}
release {
signingConfig signingConfigs.release
minifyEnabled true
shrinkResources true
// Includes the default ProGuard rules files that are packaged with the Android Gradle plugin.
// To learn more, go to the documentation section about R8 configuration files.
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
resValue 'string', 'app_name', project.ext.appName
// Full size symbols are too big for Google, 217mb aab vs 95mb.
ndk.debugSymbolLevel = 'symbol_table'
}
// TODO(@pastk): rename to "test" everywhere in code
beta {
applicationIdSuffix '.test'
versionNameSuffix '-test'
signingConfig signingConfigs.release
minifyEnabled true
shrinkResources true
// Includes the default ProGuard rules files that are packaged with the Android Gradle plugin.
// To learn more, go to the documentation section about R8 configuration files.
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
matchingFallbacks = ['release'] // use dependencies of "release" build type
resValue 'string', 'app_name', 'CoMaps Test'
// Full size symbols are too big for Google, 217mb aab vs 95mb.
ndk.debugSymbolLevel = 'symbol_table'
}
}
externalNativeBuild {
cmake {
version '3.22.1+'
buildStagingDirectory './nativeOutputs'
path '../../CMakeLists.txt'
}
}
// We don't compress these extensions in assets/ because our random FileReader can't read zip-compressed files from apk.
// TODO: Load all minor files via separate call to ReadAsString which can correctly handle compressed files in zip containers.
androidResources {
ignoreAssetsPattern '!.svn:!.git:!.DS_Store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~'
noCompress = ['txt', 'bin', 'html', 'png', 'json', 'mwm', 'ttf', 'sdf', 'ui', 'config', 'csv', 'spv', 'obj']
}
compileOptions {
coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
}
dependencies {
coreLibraryDesugaring libs.android.tools.desugar
// Google Play Location Services
// TODO(@pastk): enabled via microG in all flavors,
// so move google/java/app/organicmaps/location/* into main/ and remove symlinks.
//
// Please add symlinks to google/java/app/organicmaps/location for each new gms-enabled flavor below:
// ```
// mkdir -p src/$flavor/java/app/organicmaps/
// ln -sf ../../../../google/java/app/organicmaps/location src/$flavor/java/app/organicmaps/
// ls -la src/$flavor/java/app/organicmaps/location/GoogleFusedLocationProvider.java
// ```
//
// microG project's FOSS re-implementation of the proprietary libs.google.services.location
implementation libs.microg.services.location
// This line is added as a workaround for duplicate classes error caused by some outdated dependency:
// > A failure occurred while executing com.android.build.gradle.internal.tasks.CheckDuplicatesRunnable
// We don't use Kotlin, but some dependencies are actively using it.
// See https://stackoverflow.com/a/75719642
implementation libs.androidx.core
implementation(platform(libs.jetbrains.kotlin.bom))
implementation libs.androidx.annotation
implementation libs.androidx.appcompat
implementation libs.androidx.car.app
implementation libs.androidx.car.app.projected
implementation libs.androidx.constraintlayout
implementation libs.androidx.fragment
implementation libs.androidx.preference
implementation libs.androidx.recyclerview
implementation libs.androidx.work.runtime
implementation libs.androidx.lifecycle.process
implementation libs.android.material
// Fix for app/organicmaps/util/FileUploadWorker.java:14: error: cannot access ListenableFuture
// https://github.com/organicmaps/organicmaps/issues/6106
implementation libs.google.guava
implementation libs.devnullorthrow.mpandroidchart
implementation libs.jcip.annotations
// Test Dependencies
androidTestImplementation libs.androidx.test.junit
testImplementation libs.junit
testImplementation libs.mockito.core
testImplementation libs.mockito.inline
}
tasks.withType(JavaCompile) {
options.compilerArgs << '-Xlint:unchecked' << '-Xlint:deprecation'
}
android.applicationVariants.all { variant ->
def authorityValue = variant.applicationId + ".provider"
def authority = "\"" + authorityValue + "\""
variant.buildConfigField 'String', 'FILE_PROVIDER_AUTHORITY', authority
def flavor = variant.getMergedFlavor()
flavor.manifestPlaceholders += [FILE_PROVIDER_PLACEHOLDER : authorityValue]
variant.resValue 'string', 'app_id', variant.applicationId
}
play {
enabled.set(false)
track.set('production')
defaultToAppBundles.set(true)
releaseStatus.set(ReleaseStatus.IN_PROGRESS)
serviceAccountCredentials.set(file('google-play.json'))
}
huaweiPublish {
instances {
huaweiRelease {
credentialsPath = "$projectDir/huawei-appgallery.json"
buildFormat = 'aab'
deployType = 'draft' // confirm manually
def releaseDescriptions = []
def localeOverride = [
'am' : 'am-ET',
'gu': 'gu_IN',
'iw-IL': 'he_IL',
'kn-IN': 'kn_IN',
'ml-IN': 'ml_IN',
'mn-MN': 'mn_MN',
'mr-IN': 'mr_IN',
'ta-IN': 'ta_IN',
'te-IN': 'te_IN',
]
def files = fileTree(dir: "$projectDir/src/fdroid/play/listings",
include: '**/release-notes.txt')
files.each { File file ->
def path = file.getPath()
def locale = file.parentFile.getName()
locale = localeOverride.get(locale, locale)
releaseDescriptions.add(new ru.cian.huawei.publish.ReleaseNote(locale, path))
}
releaseNotes = new ru.cian.huawei.publish.ReleaseNotesExtension(releaseDescriptions, true)
}
}
}