705 lines
27 KiB
Groovy
705 lines
27 KiB
Groovy
plugins {
|
|
id "com.jetbrains.python.envs" version "$python_envs_plugin"
|
|
}
|
|
|
|
if (findProject(":geckoview") != null) {
|
|
buildDir "${topobjdir}/gradle/build/mobile/android/focus-android"
|
|
}
|
|
|
|
apply plugin: 'com.android.application'
|
|
apply plugin: 'kotlin-android'
|
|
apply plugin: 'kotlin-parcelize'
|
|
apply plugin: 'jacoco'
|
|
apply plugin: 'com.google.android.gms.oss-licenses-plugin'
|
|
|
|
def versionCodeGradle = "$project.rootDir/tools/gradle/versionCode.gradle"
|
|
if (findProject(":geckoview") != null) {
|
|
versionCodeGradle = "$project.rootDir/mobile/android/focus-android/tools/gradle/versionCode.gradle"
|
|
}
|
|
apply from: versionCodeGradle
|
|
|
|
import com.android.build.api.variant.FilterConfiguration
|
|
import groovy.json.JsonOutput
|
|
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
|
|
|
import static org.gradle.api.tasks.testing.TestResult.ResultType
|
|
|
|
android {
|
|
if (project.hasProperty("testBuildType")) {
|
|
// Allowing to configure the test build type via command line flag (./gradlew -PtestBuildType=beta ..)
|
|
// in order to run UI tests against other build variants than debug in automation.
|
|
testBuildType project.property("testBuildType")
|
|
}
|
|
|
|
defaultConfig {
|
|
applicationId "org.mozilla"
|
|
minSdkVersion config.minSdkVersion
|
|
compileSdk config.compileSdkVersion
|
|
targetSdkVersion config.targetSdkVersion
|
|
versionCode 11 // This versionCode is "frozen" for local builds. For "release" builds we
|
|
// override this with a generated versionCode at build time.
|
|
// The versionName is dynamically overridden for all the build variants at build time.
|
|
versionName Config.generateDebugVersionName()
|
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
|
testInstrumentationRunnerArguments clearPackageData: 'true'
|
|
// See override in release builds for why it's blank.
|
|
buildConfigField "String", "VCS_HASH", "\"\""
|
|
|
|
vectorDrawables.useSupportLibrary = true
|
|
}
|
|
|
|
bundle {
|
|
language {
|
|
// Because we have runtime language selection we will keep all strings and languages
|
|
// in the base APKs.
|
|
enableSplit = false
|
|
}
|
|
}
|
|
|
|
lint {
|
|
lintConfig file("lint.xml")
|
|
baseline file("lint-baseline.xml")
|
|
}
|
|
|
|
// We have a three dimensional build configuration:
|
|
// BUILD TYPE (debug, release) X PRODUCT FLAVOR (focus, klar)
|
|
|
|
buildTypes {
|
|
release {
|
|
// We allow disabling optimization by passing `-PdisableOptimization` to gradle. This is used
|
|
// in automation for UI testing non-debug builds.
|
|
shrinkResources !project.hasProperty("disableOptimization")
|
|
minifyEnabled !project.hasProperty("disableOptimization")
|
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
|
matchingFallbacks = ['release']
|
|
|
|
if (gradle.ext.vcsHashFileContent) {
|
|
buildConfigField "String", "VCS_HASH", "\"hg-${gradle.ext.vcsHashFileContent}\""
|
|
} else {
|
|
buildConfigField "String", "VCS_HASH", "\"${Config.getVcsHash(project)}\""
|
|
}
|
|
|
|
if (gradle.hasProperty("localProperties.autosignReleaseWithDebugKey")) {
|
|
println ("All builds will be automatically signed with the debug key")
|
|
signingConfig signingConfigs.debug
|
|
}
|
|
|
|
if (gradle.hasProperty("localProperties.debuggable")) {
|
|
println ("All builds will be debuggable")
|
|
debuggable true
|
|
}
|
|
}
|
|
debug {
|
|
applicationIdSuffix ".debug"
|
|
matchingFallbacks = ['debug']
|
|
}
|
|
beta {
|
|
initWith release
|
|
applicationIdSuffix ".beta"
|
|
// This is used when the user selects text in other third-party apps. See https://github.com/mozilla-mobile/focus-android/issues/6478
|
|
manifestPlaceholders = [textSelectionSearchAction: "@string/text_selection_search_action_focus_beta"]
|
|
}
|
|
nightly {
|
|
initWith release
|
|
applicationIdSuffix ".nightly"
|
|
// This is used when the user selects text in other third-party apps. See https://github.com/mozilla-mobile/focus-android/issues/6478
|
|
manifestPlaceholders = [textSelectionSearchAction: "@string/text_selection_search_action_focus_nightly"]
|
|
}
|
|
}
|
|
testOptions {
|
|
execution 'ANDROIDX_TEST_ORCHESTRATOR'
|
|
animationsDisabled = true
|
|
unitTests {
|
|
includeAndroidResources = true
|
|
}
|
|
}
|
|
|
|
buildFeatures {
|
|
compose true
|
|
viewBinding true
|
|
buildConfig true
|
|
}
|
|
|
|
composeOptions {
|
|
kotlinCompilerExtensionVersion = libs.versions.compose.compiler.get()
|
|
}
|
|
|
|
flavorDimensions.add("product")
|
|
|
|
productFlavors {
|
|
// In most countries we are Firefox Focus - but in some we need to be Firefox Klar
|
|
focus {
|
|
dimension "product"
|
|
|
|
applicationIdSuffix ".focus"
|
|
|
|
// This is used when the user selects text in other third-party apps. See https://github.com/mozilla-mobile/focus-android/issues/6478
|
|
manifestPlaceholders = [textSelectionSearchAction: "@string/text_selection_search_action_focus"]
|
|
}
|
|
klar {
|
|
dimension "product"
|
|
|
|
applicationIdSuffix ".klar"
|
|
|
|
// This is used when the user selects text in other third-party apps. See https://github.com/mozilla-mobile/focus-android/issues/6478
|
|
manifestPlaceholders = [textSelectionSearchAction: "@string/text_selection_search_action_klar"]
|
|
}
|
|
}
|
|
|
|
splits {
|
|
abi {
|
|
enable true
|
|
|
|
reset()
|
|
|
|
include "x86", "armeabi-v7a", "arm64-v8a", "x86_64"
|
|
}
|
|
}
|
|
|
|
sourceSets {
|
|
test {
|
|
resources {
|
|
// Make the default asset folder available as test resource folder. Robolectric seems
|
|
// to fail to read assets for our setup. With this we can just read the files directly
|
|
// and do not need to rely on Robolectric.
|
|
srcDir "${projectDir}/src/main/assets/"
|
|
}
|
|
}
|
|
|
|
// Release
|
|
focusRelease.root = 'src/focusRelease'
|
|
klarRelease.root = 'src/klarRelease'
|
|
|
|
// Debug
|
|
focusDebug.root = 'src/focusDebug'
|
|
klarDebug.root = 'src/klarDebug'
|
|
|
|
// Nightly
|
|
focusNightly.root = 'src/focusNightly'
|
|
klarNightly.root = 'src/klarNightly'
|
|
}
|
|
packagingOptions {
|
|
resources {
|
|
pickFirsts += ['META-INF/atomicfu.kotlin_module', 'META-INF/proguard/coroutines.pro']
|
|
}
|
|
jniLibs {
|
|
useLegacyPackaging true
|
|
}
|
|
}
|
|
|
|
namespace 'org.mozilla.focus'
|
|
}
|
|
|
|
tasks.withType(KotlinCompile).configureEach {
|
|
kotlinOptions.allWarningsAsErrors = true
|
|
kotlinOptions.freeCompilerArgs += [
|
|
"-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
|
|
"-opt-in=kotlin.RequiresOptIn",
|
|
"-Xjvm-default=all"
|
|
]
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------------------------
|
|
// Generate Kotlin code for the Focus Glean metrics.
|
|
// -------------------------------------------------------------------------------------------------
|
|
ext {
|
|
// Enable expiration by major version.
|
|
gleanExpireByVersion = 1
|
|
gleanNamespace = "mozilla.telemetry.glean"
|
|
gleanPythonEnvDir = gradle.mozconfig.substs.GRADLE_GLEAN_PARSER_VENV
|
|
}
|
|
apply plugin: "org.mozilla.telemetry.glean-gradle-plugin"
|
|
apply plugin: "org.mozilla.appservices.nimbus-gradle-plugin"
|
|
|
|
nimbus {
|
|
// The path to the Nimbus feature manifest file
|
|
manifestFile = "nimbus.fml.yaml"
|
|
// Map from the variant name to the channel as experimenter and nimbus understand it.
|
|
// If nimbus's channels were accurately set up well for this project, then this
|
|
// shouldn't be needed.
|
|
channels = [
|
|
focusDebug: "debug",
|
|
focusNightly: "nightly",
|
|
focusBeta: "beta",
|
|
focusRelease: "release",
|
|
klarDebug: "debug",
|
|
klarNightly: "nightly",
|
|
klarBeta: "beta",
|
|
klarRelease: "release",
|
|
]
|
|
// This is generated by the FML and should be checked into git.
|
|
// It will be fetched by Experimenter (the Nimbus experiment website)
|
|
// and used to inform experiment configuration.
|
|
experimenterManifest = ".experimenter.yaml"
|
|
}
|
|
|
|
dependencies {
|
|
implementation libs.androidx.activity
|
|
implementation libs.androidx.appcompat
|
|
implementation libs.androidx.browser
|
|
implementation libs.androidx.cardview
|
|
implementation libs.androidx.collection
|
|
|
|
implementation platform(libs.androidx.compose.bom)
|
|
androidTestImplementation platform(libs.androidx.compose.bom)
|
|
implementation libs.androidx.compose.foundation
|
|
implementation libs.androidx.compose.material
|
|
implementation libs.androidx.compose.material.icons
|
|
implementation libs.androidx.compose.runtime.livedata
|
|
implementation libs.androidx.compose.ui
|
|
implementation libs.androidx.compose.ui.tooling
|
|
|
|
implementation libs.androidx.constraintlayout
|
|
implementation libs.androidx.constraintlayout.compose
|
|
implementation libs.androidx.core.ktx
|
|
implementation libs.androidx.core.splashscreen
|
|
implementation libs.androidx.datastore.preferences
|
|
implementation libs.androidx.fragment
|
|
implementation libs.androidx.lifecycle.process
|
|
implementation libs.androidx.lifecycle.viewmodel
|
|
implementation libs.androidx.palette
|
|
implementation libs.androidx.preferences
|
|
implementation libs.androidx.recyclerview
|
|
implementation libs.androidx.savedstate
|
|
implementation libs.androidx.transition
|
|
implementation libs.androidx.work.runtime
|
|
|
|
// Required for in-app reviews
|
|
implementation libs.play.review
|
|
implementation libs.play.review.ktx
|
|
|
|
implementation libs.google.material
|
|
|
|
implementation libs.thirdparty.sentry
|
|
|
|
implementation project(':browser-engine-gecko')
|
|
implementation project(':browser-domains')
|
|
implementation project(':browser-errorpages')
|
|
implementation project(':browser-icons')
|
|
implementation project(':browser-menu')
|
|
implementation project(':browser-state')
|
|
implementation project(':browser-toolbar')
|
|
|
|
implementation project(':concept-awesomebar')
|
|
implementation project(':concept-engine')
|
|
implementation project(':concept-fetch')
|
|
implementation project(':concept-menu')
|
|
|
|
implementation project(':compose-awesomebar')
|
|
|
|
implementation project(':feature-awesomebar')
|
|
implementation project(':feature-app-links')
|
|
implementation project(':feature-customtabs')
|
|
implementation project(':feature-contextmenu')
|
|
implementation project(':feature-downloads')
|
|
implementation project(':feature-findinpage')
|
|
implementation project(':feature-intent')
|
|
implementation project(':feature-prompts')
|
|
implementation project(':feature-session')
|
|
implementation project(':feature-search')
|
|
implementation project(':feature-tabs')
|
|
implementation project(':feature-toolbar')
|
|
implementation project(':feature-top-sites')
|
|
implementation project(':feature-sitepermissions')
|
|
implementation project(':lib-crash')
|
|
implementation project(':lib-crash-sentry')
|
|
implementation project(':lib-state')
|
|
implementation project(':feature-media')
|
|
implementation project(':lib-auth')
|
|
implementation project(':lib-publicsuffixlist')
|
|
|
|
implementation project(':service-location')
|
|
implementation project(':service-nimbus')
|
|
|
|
implementation project(':support-ktx')
|
|
implementation project(':support-utils')
|
|
implementation project(':support-rusthttp')
|
|
implementation project(':support-rustlog')
|
|
implementation project(':support-license')
|
|
|
|
implementation project(':ui-autocomplete')
|
|
implementation project(':ui-colors')
|
|
implementation project(':ui-icons')
|
|
implementation project(':ui-tabcounter')
|
|
implementation project(':ui-widgets')
|
|
implementation project(':feature-webcompat')
|
|
implementation project(':feature-webcompat-reporter')
|
|
implementation project(':support-webextensions')
|
|
implementation project(':support-locale')
|
|
implementation project(':compose-cfr')
|
|
|
|
implementation project(":service-glean")
|
|
implementation libs.mozilla.glean, {
|
|
exclude group: 'org.mozilla.telemetry', module: 'glean-native'
|
|
}
|
|
|
|
implementation libs.kotlin.coroutines
|
|
debugImplementation libs.leakcanary
|
|
|
|
testImplementation "org.mozilla.telemetry:glean-native-forUnitTests:${project.ext.glean_version}"
|
|
|
|
testImplementation libs.junit.api
|
|
testImplementation libs.junit.params
|
|
testRuntimeOnly libs.junit.engine
|
|
|
|
testImplementation libs.testing.robolectric
|
|
testImplementation libs.testing.mockito
|
|
testImplementation libs.testing.coroutines
|
|
testImplementation libs.androidx.work.testing
|
|
testImplementation libs.androidx.arch.core.testing
|
|
testImplementation project(':support-test')
|
|
testImplementation project(':support-test-libstate')
|
|
|
|
androidTestImplementation libs.testing.mockwebserver
|
|
testImplementation libs.testing.mockwebserver
|
|
testImplementation project(':lib-fetch-okhttp')
|
|
|
|
testImplementation libs.androidx.test.core
|
|
testImplementation libs.androidx.test.runner
|
|
testImplementation libs.androidx.test.rules
|
|
|
|
androidTestImplementation libs.androidx.espresso.core
|
|
androidTestImplementation libs.androidx.espresso.idling.resource
|
|
androidTestImplementation libs.androidx.espresso.intents
|
|
androidTestImplementation libs.androidx.espresso.web
|
|
androidTestImplementation libs.androidx.test.core
|
|
androidTestImplementation libs.androidx.test.junit
|
|
androidTestImplementation libs.androidx.test.monitor
|
|
androidTestImplementation libs.androidx.test.runner
|
|
androidTestImplementation libs.androidx.test.uiautomator
|
|
androidTestUtil libs.androidx.test.orchestrator
|
|
|
|
lintChecks project(':tooling-lint')
|
|
}
|
|
// -------------------------------------------------------------------------------------------------
|
|
// Dynamically set versionCode (See tools/build/versionCode.gradle
|
|
// -------------------------------------------------------------------------------------------------
|
|
|
|
android.applicationVariants.configureEach { variant ->
|
|
def buildType = variant.buildType.name
|
|
|
|
project.logger.debug("----------------------------------------------")
|
|
project.logger.debug("Variant name: " + variant.name)
|
|
project.logger.debug("Application ID: " + [variant.applicationId, variant.buildType.applicationIdSuffix].findAll().join())
|
|
project.logger.debug("Build type: " + variant.buildType.name)
|
|
project.logger.debug("Flavor: " + variant.flavorName)
|
|
|
|
if (buildType == "release" || buildType == "nightly" || buildType == "beta") {
|
|
def baseVersionCode = generatedVersionCode
|
|
def versionName = buildType == "nightly" ?
|
|
"${Config.nightlyVersionName(project)}" :
|
|
"${Config.releaseVersionName(project)}"
|
|
project.logger.debug("versionName override: $versionName")
|
|
|
|
// The Google Play Store does not allow multiple APKs for the same app that all have the
|
|
// same version code. Therefore we need to have different version codes for our ARM and x86
|
|
// builds. See https://developer.android.com/studio/publish/versioning
|
|
|
|
// Our generated version code now has a length of 9 (See tools/gradle/versionCode.gradle).
|
|
// Our x86 builds need a higher version code to avoid installing ARM builds on an x86 device
|
|
// with ARM compatibility mode.
|
|
|
|
// AAB builds need a version code that is distinct from any APK builds. Since AAB and APK
|
|
// builds may run in parallel, AAB and APK version codes might be based on the same
|
|
// (minute granularity) time of day. To avoid conflicts, we ensure the minute portion
|
|
// of the version code is even for APKs and odd for AABs.
|
|
|
|
variant.outputs.each { output ->
|
|
def abi = output.getFilter(FilterConfiguration.FilterType.ABI.name())
|
|
def aab = project.hasProperty("aab")
|
|
// We use the same version code generator, that we inherited from Fennec, across all channels - even on
|
|
// channels that never shipped a Fennec build.
|
|
|
|
// ensure baseVersionCode is an even number
|
|
if (baseVersionCode % 2) {
|
|
baseVersionCode = baseVersionCode + 1
|
|
}
|
|
|
|
def versionCodeOverride = baseVersionCode
|
|
|
|
if (aab) {
|
|
// AAB version code is odd
|
|
versionCodeOverride = versionCodeOverride + 1
|
|
project.logger.debug("versionCode for AAB = $versionCodeOverride")
|
|
} else {
|
|
if (abi == "x86_64") {
|
|
versionCodeOverride = versionCodeOverride + 6
|
|
} else if (abi == "x86") {
|
|
versionCodeOverride = versionCodeOverride + 4
|
|
} else if (abi == "arm64-v8a") {
|
|
versionCodeOverride = versionCodeOverride + 2
|
|
} else if (abi == "armeabi-v7a") {
|
|
versionCodeOverride = versionCodeOverride + 0
|
|
} else {
|
|
throw new RuntimeException("Unknown ABI: " + abi)
|
|
}
|
|
project.logger.debug("versionCode for $abi = $versionCodeOverride")
|
|
}
|
|
|
|
if (versionName != null) {
|
|
output.versionNameOverride = versionName
|
|
}
|
|
output.versionCodeOverride = versionCodeOverride
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------------------------
|
|
// MLS: Read token from local file if it exists (Only release builds)
|
|
// -------------------------------------------------------------------------------------------------
|
|
|
|
android.applicationVariants.configureEach {
|
|
project.logger.debug("MLS token: ")
|
|
try {
|
|
def token = new File("${rootDir}/.mls_token").text.trim()
|
|
buildConfigField 'String', 'MLS_TOKEN', '"' + token + '"'
|
|
project.logger.debug("(Added from .mls_token file)")
|
|
} catch (FileNotFoundException ignored) {
|
|
buildConfigField 'String', 'MLS_TOKEN', '""'
|
|
project.logger.debug("X_X")
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------------------------
|
|
// Sentry: Read token from local file if it exists (Only release builds)
|
|
// -------------------------------------------------------------------------------------------------
|
|
|
|
android.applicationVariants.configureEach {
|
|
project.logger.debug("Sentry token: ")
|
|
try {
|
|
def token = new File("${rootDir}/.sentry_token").text.trim()
|
|
buildConfigField 'String', 'SENTRY_TOKEN', '"' + token + '"'
|
|
project.logger.debug("(Added from .sentry_token file)")
|
|
} catch (FileNotFoundException ignored) {
|
|
buildConfigField 'String', 'SENTRY_TOKEN', '""'
|
|
project.logger.debug("X_X")
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------------------------
|
|
// L10N: Generate list of locales
|
|
// Focus provides its own (Android independent) locale switcher. That switcher requires a list
|
|
// of locale codes. We generate that list here to avoid having to manually maintain a list of locales:
|
|
// -------------------------------------------------------------------------------------------------
|
|
|
|
def getEnabledLocales() {
|
|
def resDir = file('src/main/res')
|
|
|
|
def potentialLanguageDirs = resDir.listFiles(new FilenameFilter() {
|
|
@Override
|
|
boolean accept(File dir, String name) {
|
|
return name.startsWith("values-")
|
|
}
|
|
})
|
|
|
|
def langs = potentialLanguageDirs.findAll {
|
|
// Only select locales where strings.xml exists
|
|
// Some locales might only contain e.g. sumo URLS in urls.xml, and should be skipped (see es vs es-ES/es-MX/etc)
|
|
return file(new File(it, "strings.xml")).exists()
|
|
} .collect {
|
|
// And reduce down to actual values-* names
|
|
return it.name
|
|
} .collect {
|
|
return it.substring("values-".length())
|
|
} .collect {
|
|
if (it.length() > 3 && it.contains("-r")) {
|
|
// Android resource dirs add an "r" prefix to the region - we need to strip that for java usage
|
|
// Add 1 to have the index of the r, without the dash
|
|
def regionPrefixPosition = it.indexOf("-r") + 1
|
|
|
|
return it.substring(0, regionPrefixPosition) + it.substring(regionPrefixPosition + 1)
|
|
} else {
|
|
return it
|
|
}
|
|
}.collect {
|
|
return '"' + it + '"'
|
|
}
|
|
|
|
// en-US is the default language (in "values") and therefore needs to be added separately
|
|
langs << "\"en-US\""
|
|
|
|
return langs.sort { it }
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------------------------
|
|
// Nimbus: Read endpoint from local.properties of a local file if it exists
|
|
// -------------------------------------------------------------------------------------------------
|
|
|
|
project.logger.debug("Nimbus endpoint: ")
|
|
android.applicationVariants.configureEach { variant ->
|
|
def variantName = variant.getName()
|
|
|
|
if (!variantName.contains("Debug")) {
|
|
try {
|
|
def url = new File("${rootDir}/.nimbus").text.trim()
|
|
buildConfigField 'String', 'NIMBUS_ENDPOINT', '"' + url + '"'
|
|
project.logger.debug("(Added from .nimbus file)")
|
|
} catch (FileNotFoundException ignored) {
|
|
buildConfigField 'String', 'NIMBUS_ENDPOINT', 'null'
|
|
project.logger.debug("X_X")
|
|
}
|
|
} else if (gradle.hasProperty("localProperties.nimbus.remote-settings.url")) {
|
|
def url = gradle.getProperty("localProperties.nimbus.remote-settings.url")
|
|
buildConfigField 'String', 'NIMBUS_ENDPOINT', '"' + url + '"'
|
|
project.logger.debug("(Added from local.properties file)")
|
|
} else {
|
|
buildConfigField 'String', 'NIMBUS_ENDPOINT', 'null'
|
|
project.logger.debug("--")
|
|
}
|
|
}
|
|
|
|
def generatedLocaleListDir = file('src/main/java/org/mozilla/focus/generated')
|
|
def generatedLocaleListFilename = 'LocalesList.kt'
|
|
|
|
def enabledLocales = project.provider { getEnabledLocales() }
|
|
|
|
tasks.register('generateLocaleList') {
|
|
def localeList = file(new File(generatedLocaleListDir, generatedLocaleListFilename))
|
|
doLast {
|
|
generatedLocaleListDir.mkdir()
|
|
localeList.delete()
|
|
localeList.createNewFile()
|
|
localeList << "package org.mozilla.focus.generated" << "\n" << "\n"
|
|
localeList << "import java.util.Collections" << "\n"
|
|
localeList << "\n"
|
|
localeList << "/**"
|
|
localeList << "\n"
|
|
localeList << " * Provides a list of bundled locales based on the language files in the res folder."
|
|
localeList << "\n"
|
|
localeList << " */"
|
|
localeList << "\n"
|
|
localeList << "object LocalesList {" << "\n"
|
|
localeList << " " << "val BUNDLED_LOCALES: List<String> = Collections.unmodifiableList("
|
|
localeList << "\n"
|
|
localeList << " " << "listOf("
|
|
localeList << "\n"
|
|
localeList << " "
|
|
localeList << enabledLocales.get().join(",\n" + " ")
|
|
localeList << ",\n"
|
|
localeList << " )," << "\n"
|
|
localeList << " )" << "\n"
|
|
localeList << "}" << "\n"
|
|
}
|
|
}
|
|
|
|
tasks.configureEach { task ->
|
|
if (name.contains("compile")) {
|
|
task.dependsOn generateLocaleList
|
|
}
|
|
}
|
|
|
|
clean.doLast {
|
|
generatedLocaleListDir.deleteDir()
|
|
}
|
|
|
|
if (project.hasProperty("coverage")) {
|
|
tasks.withType(Test).configureEach {
|
|
jacoco.includeNoLocationClasses = true
|
|
jacoco.excludes = ['jdk.internal.*']
|
|
}
|
|
|
|
android.applicationVariants.configureEach { variant ->
|
|
tasks.register("jacoco${variant.name.capitalize()}TestReport", JacocoReport) {
|
|
|
|
dependsOn(["test${variant.name.capitalize()}UnitTest"])
|
|
reports {
|
|
html.required = true
|
|
xml.required = true
|
|
}
|
|
|
|
def fileFilter = ['**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*',
|
|
'**/*Test*.*', 'android/**/*.*', '**/*$[0-9].*']
|
|
def kotlinTree = fileTree(dir: "$project.layout.buildDirectory/tmp/kotlin-classes/${variant.name}", excludes: fileFilter)
|
|
def javaTree = fileTree(dir: "$project.layout.buildDirectory/intermediates/classes/${variant.flavorName}/${variant.buildType.name}",
|
|
excludes: fileFilter)
|
|
def mainSrc = "$project.projectDir/src/main/java"
|
|
sourceDirectories.setFrom(files([mainSrc]))
|
|
classDirectories.setFrom(files([kotlinTree, javaTree]))
|
|
executionData.setFrom(fileTree(dir: project.layout.buildDirectory, includes: [
|
|
"jacoco/test${variant.name.capitalize()}UnitTest.exec", 'outputs/code-coverage/connected/*coverage.ec'
|
|
]))
|
|
}
|
|
}
|
|
|
|
android {
|
|
buildTypes {
|
|
debug {
|
|
testCoverageEnabled true
|
|
applicationIdSuffix ".coverage"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------------------------
|
|
// Task for printing APK information for the requested variant
|
|
// Taskgraph Usage: "./gradlew printVariants
|
|
// -------------------------------------------------------------------------------------------------
|
|
tasks.register('printVariants') {
|
|
def variants = project.provider { android.applicationVariants.collect { variant -> [
|
|
apks: variant.outputs.collect { output -> [
|
|
abi: output.getFilter(FilterConfiguration.FilterType.ABI.name()),
|
|
fileName: output.outputFile.name
|
|
]},
|
|
build_type: variant.buildType.name,
|
|
name: variant.name,
|
|
]}}
|
|
doLast {
|
|
// AndroidTest is a special case not included above
|
|
variants.get().add([
|
|
apks: [[
|
|
abi: 'noarch',
|
|
fileName: 'app-debug-androidTest.apk',
|
|
]],
|
|
build_type: 'androidTest',
|
|
name: 'androidTest',
|
|
])
|
|
println 'variants: ' + JsonOutput.toJson(variants.get())
|
|
}
|
|
}
|
|
|
|
afterEvaluate {
|
|
|
|
// Format test output. Copied from Fenix, which was ported from AC #2401
|
|
tasks.withType(Test).configureEach {
|
|
systemProperty "robolectric.logging", "stdout"
|
|
systemProperty "logging.test-mode", "true"
|
|
|
|
testLogging.events = []
|
|
|
|
beforeSuite { descriptor ->
|
|
if (descriptor.getClassName() != null) {
|
|
println("\nSUITE: " + descriptor.getClassName())
|
|
}
|
|
}
|
|
|
|
beforeTest { descriptor ->
|
|
println(" TEST: " + descriptor.getName())
|
|
}
|
|
|
|
onOutput { descriptor, event ->
|
|
it.logger.lifecycle(" " + event.message.trim())
|
|
}
|
|
|
|
afterTest { descriptor, result ->
|
|
switch (result.getResultType()) {
|
|
case ResultType.SUCCESS:
|
|
println(" SUCCESS")
|
|
break
|
|
|
|
case ResultType.FAILURE:
|
|
def testId = descriptor.getClassName() + "." + descriptor.getName()
|
|
println(" TEST-UNEXPECTED-FAIL | " + testId + " | " + result.getException())
|
|
break
|
|
|
|
case ResultType.SKIPPED:
|
|
println(" SKIPPED")
|
|
break
|
|
}
|
|
it.logger.lifecycle("")
|
|
}
|
|
}
|
|
}
|