441 lines
17 KiB
Groovy
441 lines
17 KiB
Groovy
import com.android.build.OutputFile
|
|
|
|
apply plugin: 'com.android.application'
|
|
apply plugin: 'com.google.firebase.appdistribution'
|
|
apply plugin: 'com.google.android.gms.oss-licenses-plugin'
|
|
apply plugin: 'kotlin-android'
|
|
apply plugin: 'kotlin-parcelize'
|
|
apply plugin: 'kotlin-kapt'
|
|
apply plugin: 'com.google.devtools.ksp'
|
|
apply plugin: 'dagger.hilt.android.plugin'
|
|
apply plugin: 'kotlinx-knit'
|
|
apply plugin: 'com.likethesalad.stem'
|
|
|
|
if (project.hasProperty("coverage")) {
|
|
apply plugin: 'jacoco'
|
|
}
|
|
|
|
kapt {
|
|
correctErrorTypes = true
|
|
}
|
|
|
|
knit {
|
|
files = fileTree(project.rootDir) {
|
|
include '**/*.md'
|
|
include '**/*.kt'
|
|
include '**/*.kts'
|
|
exclude '**/build/**'
|
|
exclude '**/.gradle/**'
|
|
exclude '**/towncrier/template.md'
|
|
exclude '**/CHANGES.md'
|
|
}
|
|
}
|
|
|
|
// Note: 2 digits max for each value
|
|
ext.versionMajor = 1
|
|
ext.versionMinor = 6
|
|
// Note: even values are reserved for regular release, odd values for hotfix release.
|
|
// When creating a hotfix, you should decrease the value, since the current value
|
|
// is the value for the next regular release.
|
|
ext.versionPatch = 20
|
|
|
|
static def getGitTimestamp() {
|
|
def cmd = 'git show -s --format=%ct'
|
|
return cmd.execute().text.trim() as Long
|
|
}
|
|
|
|
static def generateVersionCodeFromTimestamp() {
|
|
// It's unix timestamp, minus timestamp of October 3rd 2018 (first commit date) divided by 100: It's incremented by one every 100 seconds.
|
|
// plus 20_000_000 for compatibility reason with the previous way the Version Code was computed
|
|
// Note that the result will be multiplied by 10 when adding the digit for the arch
|
|
return ((getGitTimestamp() - 1_538_524_800) / 100).toInteger() + 20_000_000
|
|
}
|
|
|
|
def generateVersionCodeFromVersionName() {
|
|
// plus 4_000_000 for compatibility reason with the previous way the Version Code was computed
|
|
// Note that the result will be multiplied by 10 when adding the digit for the arch
|
|
return (versionMajor * 1_00_00 + versionMinor * 1_00 + versionPatch) + 4_000_000
|
|
}
|
|
|
|
def getVersionCode() {
|
|
if (gitBranchName() == "develop") {
|
|
return generateVersionCodeFromTimestamp()
|
|
} else {
|
|
return generateVersionCodeFromVersionName()
|
|
}
|
|
}
|
|
|
|
def getNightlyUniversalApkPath() {
|
|
def taskNames = gradle.getStartParameter().taskNames.toString()
|
|
if(taskNames.contains("Nightly")) {
|
|
return "vector-app/build/outputs/apk/gplay/nightly/vector-gplay-universal-nightly.apk"
|
|
} else {
|
|
return ""
|
|
}
|
|
}
|
|
|
|
def getFirebaseAppId() {
|
|
// def taskNames = gradle.getStartParameter().taskNames.toString()
|
|
// if(taskNames.contains("RustCryptoNightly")) {
|
|
// return "1:912726360885:android:94fb99347eaa36d100427c"
|
|
// } else if (taskNames.contains("KotlinCryptoNightly")) {
|
|
return "1:912726360885:android:efd8545af52a9f9300427c"
|
|
// } else {
|
|
// return ""
|
|
// }
|
|
}
|
|
static def gitRevision() {
|
|
def cmd = "git rev-parse --short=8 HEAD"
|
|
return cmd.execute().text.trim()
|
|
}
|
|
|
|
static def gitRevisionDate() {
|
|
def cmd = "git show -s --format=%ci HEAD^{commit}"
|
|
return cmd.execute().text.trim()
|
|
}
|
|
|
|
static def gitBranchName() {
|
|
def cmd = "git rev-parse --abbrev-ref HEAD"
|
|
return cmd.execute().text.trim()
|
|
}
|
|
|
|
// For Google Play build, build on any other branch than main will have a "-dev" suffix
|
|
static def getGplayVersionSuffix() {
|
|
if (gitBranchName() == "main") {
|
|
return ""
|
|
} else {
|
|
return "-dev"
|
|
}
|
|
}
|
|
|
|
static def gitTag() {
|
|
def cmd = "git describe --exact-match --tags"
|
|
return cmd.execute().text.trim()
|
|
}
|
|
|
|
// For F-Droid build, build on a not tagged commit will have a "-dev" suffix
|
|
static def getFdroidVersionSuffix() {
|
|
if (gitTag() == "") {
|
|
return "-dev"
|
|
} else {
|
|
return ""
|
|
}
|
|
}
|
|
|
|
project.android.buildTypes.all { buildType ->
|
|
buildType.javaCompileOptions.annotationProcessorOptions.arguments =
|
|
[
|
|
validateEpoxyModelUsage: String.valueOf(buildType.name == 'debug')
|
|
]
|
|
}
|
|
|
|
// map for the version codes last digit
|
|
// x86 must have greater values than arm
|
|
// 64 bits have greater value than 32 bits
|
|
ext.abiVersionCodes = ["armeabi-v7a": 1, "arm64-v8a": 2, "x86": 3, "x86_64": 4].withDefault { 0 }
|
|
|
|
android {
|
|
namespace "im.vector.application"
|
|
// Due to a bug introduced in Android gradle plugin 3.6.0, we have to specify the ndk version to use
|
|
// Ref: https://issuetracker.google.com/issues/144111441
|
|
ndkVersion "21.3.6528147"
|
|
|
|
compileSdk versions.compileSdk
|
|
|
|
defaultConfig {
|
|
applicationId "im.vector.app"
|
|
// Set to API 21: see #405
|
|
minSdk versions.minSdk
|
|
targetSdk versions.targetSdk
|
|
multiDexEnabled true
|
|
|
|
renderscriptTargetApi 24
|
|
renderscriptSupportModeEnabled true
|
|
|
|
// `develop` branch will have version code from timestamp, to ensure each build from CI has a incremented versionCode.
|
|
// Other branches (main, features, etc.) will have version code based on application version.
|
|
versionCode project.getVersionCode()
|
|
|
|
// Required for sonar analysis
|
|
versionName "${versionMajor}.${versionMinor}.${versionPatch}-sonar"
|
|
|
|
// Generate a random app task affinity
|
|
manifestPlaceholders = [appTaskAffinitySuffix: "H_${gitRevision()}"]
|
|
|
|
buildConfigField "String", "GIT_REVISION", "\"${gitRevision()}\""
|
|
buildConfigField "String", "GIT_REVISION_DATE", "\"${gitRevisionDate()}\""
|
|
buildConfigField "String", "GIT_BRANCH_NAME", "\"${gitBranchName()}\""
|
|
|
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
|
|
|
// Keep abiFilter for the universalApk
|
|
ndk {
|
|
abiFilters "armeabi-v7a", "x86", 'arm64-v8a', 'x86_64'
|
|
}
|
|
|
|
// Ref: https://developer.android.com/studio/build/configure-apk-splits.html
|
|
splits {
|
|
// Configures multiple APKs based on ABI.
|
|
abi {
|
|
// Enables building multiple APKs per ABI.
|
|
enable true
|
|
|
|
// By default all ABIs are included, so use reset() and include to specify that we only
|
|
// want APKs for armeabi-v7a, x86, arm64-v8a and x86_64.
|
|
|
|
// Resets the list of ABIs that Gradle should create APKs for to none.
|
|
reset()
|
|
|
|
// Specifies a list of ABIs that Gradle should create APKs for.
|
|
include "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
|
|
|
|
// Generate a universal APK that includes all ABIs, so user who install from CI tool can use this one by default.
|
|
universalApk true
|
|
}
|
|
}
|
|
|
|
applicationVariants.all { variant ->
|
|
// assign different version code for each output
|
|
def baseVariantVersion = variant.versionCode * 10
|
|
variant.outputs.each { output ->
|
|
def baseAbiVersionCode = project.ext.abiVersionCodes.get(output.getFilter(OutputFile.ABI))
|
|
// Known limitation: it does not modify the value in the BuildConfig.java generated file
|
|
// See https://issuetracker.google.com/issues/171133218
|
|
output.versionCodeOverride = baseVariantVersion + baseAbiVersionCode
|
|
print "ABI " + output.getFilter(OutputFile.ABI) + " \t-> VersionCode = " + output.versionCode + "\n"
|
|
output.outputFileName = output.outputFileName.replace("vector-app", "vector")
|
|
}
|
|
}
|
|
|
|
// The following argument makes the Android Test Orchestrator run its
|
|
// "pm clear" command after each test invocation. This command ensures
|
|
// that the app's state is completely cleared between tests.
|
|
testInstrumentationRunnerArguments clearPackageData: 'true'
|
|
}
|
|
|
|
testOptions {
|
|
// Disables animations during instrumented tests you run from the command line…
|
|
// This property does not affect tests that you run using Android Studio.”
|
|
animationsDisabled = true
|
|
|
|
// Comment to run on Android 12
|
|
// execution 'ANDROIDX_TEST_ORCHESTRATOR'
|
|
}
|
|
|
|
signingConfigs {
|
|
debug {
|
|
keyAlias 'androiddebugkey'
|
|
keyPassword 'android'
|
|
storeFile file('./signature/debug.keystore')
|
|
storePassword 'android'
|
|
}
|
|
nightly {
|
|
keyAlias System.env.ELEMENT_ANDROID_NIGHTLY_KEYID ?: project.property("signing.element.nightly.keyId")
|
|
keyPassword System.env.ELEMENT_ANDROID_NIGHTLY_KEYPASSWORD ?: project.property("signing.element.nightly.keyPassword")
|
|
storeFile file('./signature/nightly.keystore')
|
|
storePassword System.env.ELEMENT_ANDROID_NIGHTLY_STOREPASSWORD ?: project.property("signing.element.nightly.storePassword")
|
|
}
|
|
release {
|
|
keyAlias project.property("signing.element.keyId")
|
|
keyPassword project.property("signing.element.keyPassword")
|
|
storeFile file(project.property("signing.element.storePath"))
|
|
storePassword project.property("signing.element.storePassword")
|
|
}
|
|
}
|
|
|
|
buildTypes {
|
|
debug {
|
|
applicationIdSuffix ".debug"
|
|
signingConfig signingConfigs.debug
|
|
resValue "string", "app_name", "Element - dbg"
|
|
|
|
if (project.hasProperty("coverage")) {
|
|
testCoverageEnabled = coverage == "true"
|
|
}
|
|
}
|
|
|
|
release {
|
|
resValue "string", "app_name", "Element"
|
|
postprocessing {
|
|
// FIXME Set to true.
|
|
removeUnusedCode false
|
|
removeUnusedResources true
|
|
// We do not activate obfuscation as it makes it hard then to read crash reports, and it's a bit useless on an open source project :)
|
|
obfuscate false
|
|
optimizeCode true
|
|
proguardFiles 'proguard-rules.pro'
|
|
}
|
|
// signingConfig signingConfigs.release
|
|
}
|
|
|
|
nightly {
|
|
initWith release
|
|
applicationIdSuffix ".nightly"
|
|
versionNameSuffix "-nightly"
|
|
// Just override the background color of the launcher icon for the nightly build.
|
|
// We need to copy paste this block, this is not done automatically by `initWith release`
|
|
postprocessing {
|
|
// FIXME Set to true.
|
|
removeUnusedCode false
|
|
removeUnusedResources true
|
|
// We do not activate obfuscation as it makes it hard then to read crash reports, and it's a bit useless on an open source project :)
|
|
obfuscate false
|
|
optimizeCode true
|
|
proguardFiles 'proguard-rules.pro'
|
|
}
|
|
matchingFallbacks = ['release']
|
|
signingConfig signingConfigs.nightly
|
|
firebaseAppDistribution {
|
|
artifactType = "APK"
|
|
// We upload the universal APK to fix this error:
|
|
// "App Distribution found more than 1 output file for this variant.
|
|
// Please contact firebase-support@google.com for help using APK splits with App Distribution."
|
|
artifactPath = "$rootDir/${getNightlyUniversalApkPath()}"
|
|
// This file will be generated by the GitHub action
|
|
releaseNotesFile = "CHANGES_NIGHTLY.md"
|
|
groups = "external-testers"
|
|
// This should not be required, but if I do not add the appId, I get this error:
|
|
// "App Distribution halted because it had a problem uploading the APK: [404] Requested entity was not found."
|
|
appId = "${getFirebaseAppId()}"
|
|
}
|
|
}
|
|
}
|
|
|
|
sourceSets {
|
|
nightly {
|
|
java.srcDirs += "src/release/java"
|
|
}
|
|
}
|
|
|
|
flavorDimensions = ["store"]
|
|
|
|
productFlavors {
|
|
gplay {
|
|
apply plugin: 'com.google.gms.google-services'
|
|
afterEvaluate {
|
|
tasks.matching { it.name.contains("GoogleServices") && !it.name.contains("Gplay") }*.enabled = false
|
|
}
|
|
|
|
dimension "store"
|
|
isDefault = true
|
|
versionName "${versionMajor}.${versionMinor}.${versionPatch}${getGplayVersionSuffix()}"
|
|
buildConfigField "String", "SHORT_FLAVOR_DESCRIPTION", "\"G\""
|
|
buildConfigField "String", "FLAVOR_DESCRIPTION", "\"GooglePlay\""
|
|
}
|
|
|
|
fdroid {
|
|
dimension "store"
|
|
versionName "${versionMajor}.${versionMinor}.${versionPatch}${getFdroidVersionSuffix()}"
|
|
buildConfigField "String", "SHORT_FLAVOR_DESCRIPTION", "\"F\""
|
|
buildConfigField "String", "FLAVOR_DESCRIPTION", "\"FDroid\""
|
|
}
|
|
|
|
}
|
|
|
|
variantFilter { variant ->
|
|
def names = variant.flavors*.name
|
|
def buildType = variant.buildType.name
|
|
// There is no nightly for fdroid
|
|
if (names.contains("fdroid") && buildType == "nightly") {
|
|
// Gradle ignores any variants that satisfy the conditions above.
|
|
setIgnore(true)
|
|
}
|
|
}
|
|
|
|
lintOptions {
|
|
lintConfig file("../tools/lint/lint.xml")
|
|
|
|
checkDependencies true
|
|
abortOnError true
|
|
}
|
|
|
|
compileOptions {
|
|
sourceCompatibility versions.sourceCompat
|
|
targetCompatibility versions.targetCompat
|
|
}
|
|
|
|
kotlinOptions {
|
|
jvmTarget = "11"
|
|
freeCompilerArgs += [
|
|
"-opt-in=kotlin.RequiresOptIn",
|
|
// Fixes false positive "This is an internal Mavericks API. It is not intended for external use."
|
|
// of MvRx `by viewModel()` calls. Maybe due to the inlining of code... This is a temporary fix...
|
|
"-opt-in=com.airbnb.mvrx.InternalMavericksApi",
|
|
// Opt in for kotlinx.coroutines.FlowPreview too
|
|
"-opt-in=kotlinx.coroutines.FlowPreview",
|
|
// Opt in for kotlinx.coroutines.ExperimentalCoroutinesApi too
|
|
"-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
|
|
]
|
|
}
|
|
|
|
buildFeatures {
|
|
viewBinding true
|
|
}
|
|
}
|
|
|
|
dependencies {
|
|
implementation project(':vector')
|
|
implementation project(':vector-config')
|
|
implementation project(':library:core-utils')
|
|
debugImplementation project(':library:external:span')
|
|
debugImplementation project(':library:ui-styles')
|
|
implementation libs.dagger.hilt
|
|
implementation 'androidx.multidex:multidex:2.0.1'
|
|
implementation "androidx.sharetarget:sharetarget:1.2.0"
|
|
|
|
// Flipper, debug builds only
|
|
debugImplementation(libs.flipper.flipper) {
|
|
exclude group: 'com.facebook.fbjni', module: 'fbjni'
|
|
}
|
|
debugImplementation(libs.flipper.flipperNetworkPlugin) {
|
|
exclude group: 'com.facebook.fbjni', module: 'fbjni'
|
|
}
|
|
debugImplementation 'com.facebook.soloader:soloader:0.10.5'
|
|
debugImplementation "com.kgurgul.flipper:flipper-realm-android:2.2.0"
|
|
|
|
gplayImplementation "com.google.android.gms:play-services-location:21.0.1"
|
|
// UnifiedPush gplay flavor only
|
|
gplayImplementation platform(libs.google.firebaseBom)
|
|
gplayImplementation(libs.google.messaging) {
|
|
exclude group: 'com.google.firebase', module: 'firebase-core'
|
|
exclude group: 'com.google.firebase', module: 'firebase-analytics'
|
|
exclude group: 'com.google.firebase', module: 'firebase-measurement-connector'
|
|
}
|
|
|
|
// Nightly
|
|
// API-only library
|
|
gplayImplementation libs.google.appdistributionApi
|
|
// Full SDK implementation
|
|
nightlyImplementation libs.google.appdistribution
|
|
|
|
// OSS License, gplay flavor only
|
|
gplayImplementation 'com.google.android.gms:play-services-oss-licenses:17.0.1'
|
|
kapt libs.dagger.hiltCompiler
|
|
ksp libs.airbnb.epoxyProcessor
|
|
|
|
androidTestImplementation libs.androidx.testCore
|
|
androidTestImplementation libs.androidx.testRunner
|
|
androidTestImplementation libs.androidx.testRules
|
|
androidTestImplementation libs.androidx.junit
|
|
androidTestImplementation libs.androidx.espressoCore
|
|
androidTestImplementation libs.androidx.espressoContrib
|
|
androidTestImplementation libs.androidx.espressoIntents
|
|
androidTestImplementation libs.tests.kluent
|
|
androidTestImplementation libs.androidx.coreTesting
|
|
androidTestImplementation(libs.jetbrains.coroutinesTest) {
|
|
exclude group: "org.jetbrains.kotlinx", module: "kotlinx-coroutines-debug"
|
|
}
|
|
// Plant Timber tree for test
|
|
androidTestImplementation libs.tests.timberJunitRule
|
|
// "The one who serves a great Espresso"
|
|
androidTestImplementation('com.adevinta.android:barista:4.3.0') {
|
|
exclude group: 'org.jetbrains.kotlin'
|
|
}
|
|
androidTestImplementation libs.mockk.mockkAndroid
|
|
androidTestUtil libs.androidx.orchestrator
|
|
androidTestImplementation libs.androidx.fragmentTesting
|
|
androidTestImplementation "org.jetbrains.kotlin:kotlin-reflect:1.8.21"
|
|
debugImplementation libs.androidx.fragmentTestingManifest
|
|
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.10'
|
|
}
|