buildscript { repositories { google() mavenCentral() } // Detect flavors from the task name. def taskName = getGradle().getStartParameter().getTaskRequests().toString().toLowerCase() def isFdroid = taskName.contains('fdroid') dependencies { classpath libs.android.tools classpath(libs.triplet.play.publisher) classpath(libs.huawei.publish) } } apply plugin: 'com.android.application' apply plugin: 'com.github.triplet.play' apply plugin: 'ru.cian.huawei-publish-gradle-plugin' import com.github.triplet.gradle.androidpublisher.ReleaseStatus def getCommitMessage() { return run(['git', '--no-pager', 'show', '-s', '--format=%s%n%n%b', 'HEAD']).trim() } project.ext.appId = 'app.comaps' project.ext.appName = 'CoMaps' java { toolchain { languageVersion.set(JavaLanguageVersion.of(21)) } } android { namespace = 'app.organicmaps' // TODO: it should not be here, but in sdk/build.gradle. But for some reason it should be specified here as well. ndkVersion = '28.2.13676358' dependenciesInfo { // Disables dependency metadata when building APKs (for IzzyOnDroid/F-Droid) includeInApk = false // Disables dependency metadata when building Android App Bundles (for Google Play) includeInBundle = false } buildFeatures { dataBinding = true buildConfig = true } // Users are complaining that the app should be re-downloaded from the Play Store after changing the language. bundle { language { enableSplit = false } } // All properties are read from gradle.properties file compileSdk = propCompileSdkVersion.toInteger() defaultConfig { versionCode = rootProject.ext.versionCode versionName = rootProject.ext.versionName 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', '""' base.archivesName = appName.replaceAll('\\s','') + '-' + defaultConfig.versionCode ndk.debugSymbolLevel = 'full' } 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/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.organicmaps.DownloadResourcesActivity", '-a', 'android.intent.action.MAIN', '-c', 'android.intent.category.LAUNCHER' } } } def secureReleasePropertiesFileExists = file('secure.properties.release').exists() if (secureReleasePropertiesFileExists) { apply from: 'secure.properties.release' } def secureTestPropertiesFileExists = file('secure.properties.test').exists() if (secureTestPropertiesFileExists) { apply from: 'secure.properties.test' } signingConfigs { debug { storeFile file('comaps-debug.keystore') storePassword '12345678' keyAlias 'CoMaps Debug' keyPassword '12345678' } test { if (secureTestPropertiesFileExists) { storeFile file(secretTestStoreFile) storePassword secretTestStorePassword keyAlias secretTestKeyAlias keyPassword secretTestKeyPassword } else { println('secure.properties.test doesn\'t exist') } } release { if (secureReleasePropertiesFileExists) { storeFile file(secretReleaseStoreFile) storePassword secretReleaseStorePassword keyAlias secretReleaseKeyAlias keyPassword secretReleaseKeyPassword } else { println('secure.properties.release doesn\'t exist') } } } buildTypes { def taskName = getGradle().getStartParameter().getTaskRequests().toString().toLowerCase() debug { applicationIdSuffix '.debug' // Allows to install debug and release builds together versionNameSuffix '-debug' zipAlignEnabled true signingConfig = signingConfigs.debug resValue 'string', 'app_name', 'CoMaps Debug' } release { if (taskName.contains('release')) { if (secureReleasePropertiesFileExists) { println('Using RELEASE signing keys from secure.properties.release') signingConfig = signingConfigs.release } else { println('NO RELEASE signing keys found') println('Using DEBUG signing keys') signingConfig = signingConfigs.debug } } 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 } beta { applicationIdSuffix '.test' versionNameSuffix '-test' if (taskName.contains('beta')) { if (secureTestPropertiesFileExists) { println('Using TEST signing keys from secure.properties.test') signingConfig = signingConfigs.test } else { println('NO TEST signing keys found') println('Using DEBUG signing keys') signingConfig = signingConfigs.debug } } 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' } } // 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:.*:_*:!CVS:!thumbs.db:!picasa.ini:!*~' noCompress = ['txt', 'bin', 'html', 'png', 'json', 'mwm', 'ttf', 'sdf', 'ui', 'config', 'csv', 'spv', 'obj'] localeFilters += [ "af", "ar", "az", "be", "bg", "ca", "cs", "da", "de", "el", "en", "en-rGB", "es", "es-rMX", "et", "eu", "fa", "fi", "fr", "fr-rCA", "iw", "hi", "hu", "in", "it", "ja", "ko", "lt", "lv", "mr", "mt", "nb", "nl", "pl", "pt", "pt-rBR", "ro", "ru", "sk", "sr", "sv", "sw", "th", "tr", "uk", "vi", "zh", "zh-rHK", "zh-rMO", "zh-rTW" ] } compileOptions { coreLibraryDesugaringEnabled = true sourceCompatibility JavaVersion.VERSION_21 targetCompatibility JavaVersion.VERSION_21 } } dependencies { implementation project(':sdk') 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.appdevnext.androidchart // Test Dependencies androidTestImplementation libs.androidx.test.junit testImplementation libs.junit testImplementation libs.mockito.core } 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) } } } tasks.withType(JavaCompile).configureEach { options.compilerArgs << '-Xlint:unchecked' << '-Xlint:deprecation' }