import com.android.build.OutputFile apply plugin: 'com.android.application' apply plugin: 'com.google.android.gms.oss-licenses-plugin' apply plugin: 'kotlin-android' apply plugin: 'kotlin-parcelize' apply plugin: 'kotlin-kapt' apply plugin: 'placeholder-resolver' kapt { correctErrorTypes = true } // Note: 2 digits max for each value ext.versionMajor = 1 ext.versionMinor = 2 ext.versionPatch = 1 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() } } 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 fromEnv = System.env.BUILDKITE_BRANCH as String ?: "" if (!fromEnv.isEmpty()) { return fromEnv } else { // Note: this command return "HEAD" on Buildkite, so use the system env 'BUILDKITE_BRANCH' content first 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 } def buildNumber = System.env.BUILDKITE_BUILD_NUMBER as Integer ?: 0 android { compileSdkVersion 30 // 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" defaultConfig { applicationId "im.vector.app" // Set to API 21: see #405 minSdkVersion 21 targetSdkVersion 30 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" buildConfigField "String", "GIT_REVISION", "\"${gitRevision()}\"" resValue "string", "git_revision", "\"${gitRevision()}\"" buildConfigField "String", "GIT_REVISION_DATE", "\"${gitRevisionDate()}\"" resValue "string", "git_revision_date", "\"${gitRevisionDate()}\"" buildConfigField "String", "GIT_BRANCH_NAME", "\"${gitBranchName()}\"" resValue "string", "git_branch_name", "\"${gitBranchName()}\"" buildConfigField "String", "BUILD_NUMBER", "\"${buildNumber}\"" resValue "string", "build_number", "\"${buildNumber}\"" // The two booleans must not have the same value. We need two values for the manifest // LoginFlowV2 is disabled to be merged on develop (changelog: Improve login/register flow (#1410, #2585, #3172)) resValue "bool", "useLoginV1", "true" resValue "bool", "useLoginV2", "false" // NotificationSettingsV2 is disabled. To be released in conjunction with iOS/Web def useNotificationSettingsV2 = true buildConfigField "Boolean", "USE_NOTIFICATION_SETTINGS_V2", "${useNotificationSettingsV2}" resValue "bool", "useNotificationSettingsV1", "${!useNotificationSettingsV2}" resValue "bool", "useNotificationSettingsV2", "${useNotificationSettingsV2}" buildConfigField "im.vector.app.features.crypto.keysrequest.OutboundSessionKeySharingStrategy", "outboundSessionKeySharingStrategy", "im.vector.app.features.crypto.keysrequest.OutboundSessionKeySharingStrategy.WhenTyping" buildConfigField "Long", "VOICE_MESSAGE_DURATION_LIMIT_MS", "120_000L" // If set, MSC3086 asserted identity messages sent on VoIP calls will cause the call to appear in the room corresponding to the asserted identity. // This *must* only be set in trusted environments. buildConfigField "Boolean", "handleCallAssertedIdentityEvents", "false" 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.versionCodeOverride + "\n" } } // 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 execution 'ANDROIDX_TEST_ORCHESTRATOR' } signingConfigs { debug { keyAlias 'androiddebugkey' keyPassword 'android' storeFile file('./signature/debug.keystore') storePassword 'android' } } buildTypes { debug { applicationIdSuffix ".debug" resValue "string", "app_name", "Element dbg" resValue "bool", "debug_mode", "true" buildConfigField "boolean", "LOW_PRIVACY_LOG_ENABLE", "false" // Set to true if you want to enable strict mode in debug buildConfigField "boolean", "ENABLE_STRICT_MODE_LOGS", "false" signingConfig signingConfigs.debug } release { resValue "string", "app_name", "Element" resValue "bool", "debug_mode", "false" buildConfigField "boolean", "LOW_PRIVACY_LOG_ENABLE", "false" buildConfigField "boolean", "ENABLE_STRICT_MODE_LOGS", "false" postprocessing { removeUnusedCode true 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' } } } 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()}" resValue "bool", "isGplay", "true" buildConfigField "boolean", "ALLOW_FCM_USE", "true" buildConfigField "String", "SHORT_FLAVOR_DESCRIPTION", "\"G\"" buildConfigField "String", "FLAVOR_DESCRIPTION", "\"GooglePlay\"" } fdroid { dimension "store" versionName "${versionMajor}.${versionMinor}.${versionPatch}${getFdroidVersionSuffix()}" resValue "bool", "isGplay", "false" buildConfigField "boolean", "ALLOW_FCM_USE", "false" buildConfigField "String", "SHORT_FLAVOR_DESCRIPTION", "\"F\"" buildConfigField "String", "FLAVOR_DESCRIPTION", "\"FDroid\"" } } lintOptions { lintConfig file("lint.xml") checkDependencies true abortOnError true } compileOptions { sourceCompatibility JavaVersion.VERSION_11 targetCompatibility JavaVersion.VERSION_11 } kotlinOptions { jvmTarget = "11" } sourceSets { androidTest { java.srcDirs += "src/sharedTest/java" } test { java.srcDirs += "src/sharedTest/java" } } buildFeatures { viewBinding true } } dependencies { def epoxy_version = '4.6.2' def fragment_version = '1.3.6' def arrow_version = "0.8.2" def markwon_version = '4.1.2' def big_image_viewer_version = '1.8.1' def glide_version = '4.12.0' def moshi_version = '1.12.0' def daggerVersion = '2.38.1' def autofill_version = "1.1.0" def work_version = '2.5.0' def arch_version = '2.1.0' def lifecycle_version = '2.2.0' def rxbinding_version = '3.1.0' def jjwt_version = '0.11.2' // Tests def kluent_version = '1.68' def androidxTest_version = '1.4.0' def espresso_version = '3.4.0' implementation project(":matrix-sdk-android") implementation project(":matrix-sdk-android-rx") implementation project(":diff-match-patch") implementation project(":multipicker") implementation project(":attachment-viewer") implementation project(":library:ui-styles") implementation 'androidx.multidex:multidex:2.0.1' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version" implementation "androidx.recyclerview:recyclerview:1.2.1" implementation 'androidx.appcompat:appcompat:1.3.1' implementation "androidx.fragment:fragment-ktx:$fragment_version" implementation 'androidx.constraintlayout:constraintlayout:2.1.0' implementation "androidx.sharetarget:sharetarget:1.1.0" implementation 'androidx.core:core-ktx:1.6.0' implementation "androidx.media:media:1.4.1" implementation "androidx.transition:transition:1.4.1" implementation "org.threeten:threetenbp:1.4.0:no-tzdb" implementation "com.gabrielittner.threetenbp:lazythreetenbp:0.9.0" implementation "com.squareup.moshi:moshi-adapters:$moshi_version" implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version" implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshi_version" // Log implementation 'com.jakewharton.timber:timber:5.0.1' // Debug implementation 'com.facebook.stetho:stetho:1.6.0' // Phone number https://github.com/google/libphonenumber implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.31' // rx implementation 'io.reactivex.rxjava2:rxkotlin:2.4.0' implementation 'io.reactivex.rxjava2:rxandroid:2.1.1' implementation 'com.jakewharton.rxrelay2:rxrelay:2.1.1' // RXBinding implementation "com.jakewharton.rxbinding3:rxbinding:$rxbinding_version" implementation "com.jakewharton.rxbinding3:rxbinding-appcompat:$rxbinding_version" implementation "com.jakewharton.rxbinding3:rxbinding-material:$rxbinding_version" implementation("com.airbnb.android:epoxy:$epoxy_version") implementation "com.airbnb.android:epoxy-glide-preloading:$epoxy_version" kapt "com.airbnb.android:epoxy-processor:$epoxy_version" implementation "com.airbnb.android:epoxy-paging:$epoxy_version" implementation 'com.airbnb.android:mvrx:1.5.1' // Work implementation "androidx.work:work-runtime-ktx:$work_version" // Paging implementation "androidx.paging:paging-runtime-ktx:2.1.2" // Functional Programming implementation "io.arrow-kt:arrow-core:$arrow_version" // Pref implementation 'androidx.preference:preference-ktx:1.1.1' // UI implementation 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1' implementation 'com.google.android.material:material:1.4.0' implementation 'me.gujun.android:span:1.7' implementation "io.noties.markwon:core:$markwon_version" implementation "io.noties.markwon:html:$markwon_version" implementation 'com.googlecode.htmlcompressor:htmlcompressor:1.5.2' implementation 'me.saket:better-link-movement-method:2.2.0' implementation 'com.google.android:flexbox:2.0.1' implementation "androidx.autofill:autofill:$autofill_version" implementation 'jp.wasabeef:glide-transformations:4.3.0' implementation 'com.github.vector-im:PFLockScreen-Android:1.0.0-beta12' implementation 'com.github.hyuwah:DraggableView:1.0.0' implementation 'com.github.Armen101:AudioRecordView:1.0.5' // Custom Tab implementation 'androidx.browser:browser:1.3.0' // Passphrase strength helper implementation 'com.nulab-inc:zxcvbn:1.5.2' // To convert voice message on old platforms implementation 'com.arthenica:ffmpeg-kit-audio:4.4.LTS' //Alerter implementation 'com.tapadoo.android:alerter:7.0.1' implementation 'com.otaliastudios:autocomplete:1.1.0' // Shake detection implementation 'com.squareup:seismic:1.0.2' // Image Loading implementation "com.github.piasy:BigImageViewer:$big_image_viewer_version" implementation "com.github.piasy:GlideImageLoader:$big_image_viewer_version" implementation "com.github.piasy:ProgressPieIndicator:$big_image_viewer_version" implementation "com.github.piasy:GlideImageViewFactory:$big_image_viewer_version" // implementation 'com.github.MikeOrtiz:TouchImageView:3.0.2' implementation 'com.github.chrisbanes:PhotoView:2.3.0' implementation "com.github.bumptech.glide:glide:$glide_version" kapt "com.github.bumptech.glide:compiler:$glide_version" implementation 'com.danikula:videocache:2.7.1' implementation 'com.github.yalantis:ucrop:2.2.7' // Badge for compatibility implementation 'me.leolin:ShortcutBadger:1.1.22@aar' // Chat effects implementation 'nl.dionsegijn:konfetti:1.3.2' implementation 'com.github.jetradarmobile:android-snowfall:1.2.1' // DI implementation "com.google.dagger:dagger:$daggerVersion" kapt "com.google.dagger:dagger-compiler:$daggerVersion" // gplay flavor only gplayImplementation('com.google.firebase:firebase-messaging:22.0.0') { 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' } // OSS License, gplay flavor only gplayImplementation 'com.google.android.gms:play-services-oss-licenses:17.0.0' implementation "androidx.emoji:emoji-appcompat:1.1.0" implementation 'com.github.BillCarsonFr:JsonViewer:0.6' // WebRTC // org.webrtc:google-webrtc is for development purposes only // implementation 'org.webrtc:google-webrtc:1.0.+' implementation('com.facebook.react:react-native-webrtc:1.87.3-jitsi-6624067@aar') // Jitsi implementation('org.jitsi.react:jitsi-meet-sdk:3.1.0') { exclude group: 'com.google.firebase' exclude group: 'com.google.android.gms' exclude group: 'com.android.installreferrer' } // QR-code // Stick to 3.3.3 because of https://github.com/zxing/zxing/issues/1170 implementation 'com.google.zxing:core:3.4.1' implementation 'me.dm7.barcodescanner:zxing:1.9.13' // Emoji Keyboard implementation 'com.vanniktech:emoji-material:0.7.0' implementation 'com.vanniktech:emoji-google:0.7.0' implementation 'im.dlg:android-dialer:1.2.5' // JWT api "io.jsonwebtoken:jjwt-api:$jjwt_version" runtimeOnly "io.jsonwebtoken:jjwt-impl:$jjwt_version" runtimeOnly("io.jsonwebtoken:jjwt-orgjson:$jjwt_version") { exclude group: 'org.json', module: 'json' //provided by Android natively } implementation 'commons-codec:commons-codec:1.15' // TESTS testImplementation 'junit:junit:4.13.2' testImplementation "org.amshove.kluent:kluent-android:$kluent_version" // Plant Timber tree for test testImplementation 'net.lachlanmckee:timber-junit-rule:1.0.1' // Activate when you want to check for leaks, from time to time. //debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.3' androidTestImplementation "androidx.test:core:$androidxTest_version" androidTestImplementation "androidx.test:runner:$androidxTest_version" androidTestImplementation "androidx.test:rules:$androidxTest_version" androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation "androidx.test.espresso:espresso-core:$espresso_version" androidTestImplementation "androidx.test.espresso:espresso-contrib:$espresso_version" androidTestImplementation "androidx.test.espresso:espresso-intents:$espresso_version" androidTestImplementation "org.amshove.kluent:kluent-android:$kluent_version" androidTestImplementation "androidx.arch.core:core-testing:$arch_version" // Plant Timber tree for test androidTestImplementation 'net.lachlanmckee:timber-junit-rule:1.0.1' // "The one who serves a great Espresso" androidTestImplementation('com.adevinta.android:barista:4.1.0') { exclude group: 'org.jetbrains.kotlin' } }