| 1 | // Top-level build file where you can add configuration options common to all |
| 2 | // sub-projects/modules. |
| 3 | buildscript { |
| 4 | repositories { |
| 5 | google() |
| 6 | mavenCentral() |
| 7 | } |
| 8 | dependencies { |
| 9 | classpath 'com.android.tools.build:gradle:9.0.1' |
| 10 | classpath 'com.diffplug.spotless:spotless-plugin-gradle:8.6.0' |
| 11 | } |
| 12 | } |
| 13 | |
| 14 | apply plugin: 'com.android.application' |
| 15 | apply plugin: 'com.diffplug.spotless' |
| 16 | |
| 17 | repositories { |
| 18 | google() |
| 19 | mavenCentral() |
| 20 | maven { url='https://jitpack.io'} |
| 21 | } |
| 22 | |
| 23 | configurations { |
| 24 | playstoreImplementation |
| 25 | freeImplementation |
| 26 | conversationsFreeImplementation |
| 27 | conversationsPlaystorImplementation |
| 28 | conversationsPlaystoreImplementation |
| 29 | quicksyPlaystoreImplementation |
| 30 | quicksyPlaystoreImplementation |
| 31 | quicksyFreeImplementation |
| 32 | quicksyImplementation |
| 33 | } |
| 34 | |
| 35 | spotless { |
| 36 | ratchetFrom '2.17.4' |
| 37 | java { |
| 38 | target '**/*.java' |
| 39 | googleJavaFormat().aosp().reflowLongStrings() |
| 40 | } |
| 41 | } |
| 42 | |
| 43 | |
| 44 | dependencies { |
| 45 | coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.5' |
| 46 | |
| 47 | annotationProcessor 'org.immutables:value:2.12.2' |
| 48 | implementation 'org.immutables:value-annotations:2.12.2' |
| 49 | annotationProcessor project(':libs:annotation-processor') |
| 50 | implementation project(':libs:annotation') |
| 51 | implementation 'androidx.appcompat:appcompat:1.7.1' |
| 52 | implementation 'androidx.cardview:cardview:1.0.0' |
| 53 | implementation 'androidx.concurrent:concurrent-futures:1.3.0' |
| 54 | implementation 'androidx.documentfile:documentfile:1.1.0' |
| 55 | implementation 'androidx.emoji2:emoji2:1.6.0' |
| 56 | freeImplementation 'androidx.emoji2:emoji2-bundled:1.6.0' |
| 57 | implementation 'androidx.emoji2:emoji2-emojipicker:1.6.0' |
| 58 | implementation 'androidx.exifinterface:exifinterface:1.4.2' |
| 59 | implementation 'androidx.heifwriter:heifwriter:1.1.0' |
| 60 | implementation 'androidx.preference:preference:1.2.1' |
| 61 | implementation 'androidx.biometric:biometric:1.1.0' |
| 62 | implementation 'androidx.sharetarget:sharetarget:1.2.0' |
| 63 | implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.2.0' |
| 64 | implementation 'androidx.viewpager:viewpager:1.1.0' |
| 65 | implementation 'androidx.work:work-runtime:2.11.2' |
| 66 | implementation 'com.github.open-keychain.open-keychain:openpgp-api:v5.7.1' |
| 67 | implementation 'com.google.android.material:material:1.14.0' |
| 68 | implementation 'com.google.guava:guava:33.6.0-android' |
| 69 | implementation 'com.google.zxing:core:3.5.4' |
| 70 | implementation 'com.leinardi.android:speed-dial:3.3.0' |
| 71 | implementation 'com.squareup.okhttp3:okhttp:5.3.2' |
| 72 | implementation 'com.squareup.retrofit2:converter-gson:3.0.0' |
| 73 | implementation 'com.squareup.retrofit2:retrofit:3.0.0' |
| 74 | implementation 'com.vanniktech:android-image-cropper:4.7.0' |
| 75 | implementation 'im.conversations.webrtc:webrtc-android:129.0.0' |
| 76 | implementation 'io.deepmedia.community:transcoder-android:0.11.2' |
| 77 | implementation 'me.leolin:ShortcutBadger:1.1.22@aar' |
| 78 | //noinspection NewerVersionAvailable |
| 79 | implementation 'net.fellbaum:jemoji:1.7.6' //1.7.6 is the latest with Java 8 support |
| 80 | implementation 'org.bouncycastle:bcmail-jdk18on:1.84' |
| 81 | implementation 'org.conscrypt:conscrypt-android:2.5.3' |
| 82 | implementation 'org.hsluv:hsluv:1.0' |
| 83 | implementation 'org.jxmpp:jxmpp-jid:1.1.0' |
| 84 | implementation 'org.jxmpp:jxmpp-stringprep-libidn:1.1.0' |
| 85 | implementation 'org.minidns:minidns-client:1.1.1' |
| 86 | implementation 'org.minidns:minidns-dnssec:1.1.1' |
| 87 | implementation 'org.osmdroid:osmdroid-android:6.1.20' |
| 88 | implementation 'org.whispersystems:signal-protocol-java:2.6.2' |
| 89 | conversationsPlaystoreImplementation 'com.android.installreferrer:installreferrer:2.2' |
| 90 | quicksyImplementation 'io.michaelrocks:libphonenumber-android:9.0.31' |
| 91 | |
| 92 | quicksyPlaystoreImplementation 'com.google.android.gms:play-services-auth-api-phone:18.3.0' |
| 93 | |
| 94 | testImplementation 'junit:junit:4.13.2' |
| 95 | testImplementation 'org.robolectric:robolectric:4.16.1' |
| 96 | androidTestImplementation 'androidx.test.ext:junit:1.3.0' |
| 97 | |
| 98 | } |
| 99 | |
| 100 | ext { |
| 101 | preDexEnabled = System.getProperty("pre-dex", "true") |
| 102 | abiCodes = ['armeabi-v7a': 1, 'x86': 2, 'x86_64': 3, 'arm64-v8a': 4] |
| 103 | } |
| 104 | |
| 105 | // Load local.properties so GIPHY_API_KEY etc. don't need to be passed on the command line |
| 106 | def localProps = new Properties() |
| 107 | def localPropsFile = rootProject.file('local.properties') |
| 108 | if (localPropsFile.exists()) localProps.load(new FileInputStream(localPropsFile)) |
| 109 | |
| 110 | android { |
| 111 | namespace 'tel.xmpp.jabjab' |
| 112 | compileSdk = 36 |
| 113 | |
| 114 | defaultConfig { |
| 115 | minSdkVersion 23 |
| 116 | versionCode 42290 |
| 117 | versionName "1.0.1" |
| 118 | applicationId "tel.xmpp.jabjab" |
| 119 | resValue "string", "applicationId", applicationId |
| 120 | def appName = "JabJab" |
| 121 | resValue "string", "app_name", appName |
| 122 | buildConfigField "String", "APP_NAME", "\"$appName\"" |
| 123 | // Giphy GIF search — override with GIPHY_API_KEY gradle property |
| 124 | def giphyKey = localProps.getProperty('GIPHY_API_KEY') ?: project.findProperty('GIPHY_API_KEY') ?: "" |
| 125 | buildConfigField "String", "GIPHY_API_KEY", "\"${giphyKey}\"" |
| 126 | def updateUrl = project.findProperty('UPDATE_SERVER_URL') ?: "" |
| 127 | buildConfigField "String", "UPDATE_SERVER_URL", "\"${updateUrl}\"" |
| 128 | // Conversations upstream version — read from conversations.doap at build time |
| 129 | def conversationsVersion = "unknown" |
| 130 | def doapFile = file("conversations.doap") |
| 131 | if (doapFile.exists()) { |
| 132 | def m = doapFile.text =~ /<revision>([^<]+)<\/revision>/ |
| 133 | if (m.find()) conversationsVersion = m.group(1).trim() |
| 134 | } |
| 135 | buildConfigField "String", "CONVERSATIONS_BASE_VERSION", "\"${conversationsVersion}\"" |
| 136 | base { |
| 137 | archivesName = "jabjab-${android.defaultConfig.versionName}-${android.defaultConfig.versionCode}" |
| 138 | } |
| 139 | } |
| 140 | |
| 141 | splits { |
| 142 | abi { |
| 143 | universalApk true |
| 144 | enable true |
| 145 | reset() |
| 146 | //noinspection ChromeOsAbiSupport |
| 147 | include project.ext.abiCodes.keySet() as String[] |
| 148 | } |
| 149 | } |
| 150 | |
| 151 | configurations { |
| 152 | implementation.exclude group: 'org.jetbrains' , module:'annotations' |
| 153 | } |
| 154 | |
| 155 | dataBinding { |
| 156 | enabled true |
| 157 | } |
| 158 | |
| 159 | compileOptions { |
| 160 | coreLibraryDesugaringEnabled true |
| 161 | sourceCompatibility JavaVersion.VERSION_21 |
| 162 | targetCompatibility JavaVersion.VERSION_21 |
| 163 | } |
| 164 | |
| 165 | flavorDimensions += "mode" |
| 166 | flavorDimensions += "distribution" |
| 167 | |
| 168 | productFlavors { |
| 169 | |
| 170 | quicksy { |
| 171 | dimension "mode" |
| 172 | applicationId = "im.quicksy.client" |
| 173 | resValue "string", "applicationId", applicationId |
| 174 | |
| 175 | def appName = "Quicksy" |
| 176 | resValue "string", "app_name", appName |
| 177 | buildConfigField "String", "APP_NAME", "\"$appName\"" |
| 178 | buildConfigField "String", "PRIVACY_POLICY", "\"https://quicksy.im/privacy.htm\"" |
| 179 | def propsFile = rootProject.file('quicksy-auth-secret.properties') |
| 180 | if (propsFile.exists()) { |
| 181 | def props = new Properties() |
| 182 | props.load(new FileInputStream(propsFile)) |
| 183 | def key = props.getProperty('QUICKSY_AUTHENTICATION_SECRET') |
| 184 | if (key != null) { |
| 185 | buildConfigField "String", "QUICKSY_AUTHENTICATION_SECRET", "\"${key}\"" |
| 186 | } else { |
| 187 | buildConfigField "String", "QUICKSY_AUTHENTICATION_SECRET", "null" |
| 188 | } |
| 189 | } else { |
| 190 | buildConfigField "String", "QUICKSY_AUTHENTICATION_SECRET", "null" |
| 191 | } |
| 192 | } |
| 193 | |
| 194 | conversations { |
| 195 | dimension "mode" |
| 196 | buildConfigField "String", "PRIVACY_POLICY", "\"https://conversations.im/privacy.html\"" |
| 197 | } |
| 198 | |
| 199 | playstore { |
| 200 | dimension "distribution" |
| 201 | versionNameSuffix "+playstore" |
| 202 | } |
| 203 | free { |
| 204 | dimension "distribution" |
| 205 | versionNameSuffix "+free" |
| 206 | } |
| 207 | } |
| 208 | |
| 209 | sourceSets { |
| 210 | quicksyFree { |
| 211 | java { |
| 212 | srcDir 'src/quicksyFree/java' |
| 213 | } |
| 214 | } |
| 215 | quicksyPlaystore { |
| 216 | java { |
| 217 | srcDir 'src/quicksyPlaystore/java' |
| 218 | } |
| 219 | res { |
| 220 | srcDir 'src/quicksyPlaystore/res' |
| 221 | } |
| 222 | } |
| 223 | conversationsFree { |
| 224 | java { |
| 225 | srcDir 'src/conversationsFree/java' |
| 226 | } |
| 227 | } |
| 228 | conversationsPlaystore { |
| 229 | java { |
| 230 | srcDir 'src/conversationsPlaystore/java' |
| 231 | } |
| 232 | res { |
| 233 | srcDir 'src/conversationsPlaystore/res' |
| 234 | } |
| 235 | } |
| 236 | } |
| 237 | |
| 238 | buildTypes { |
| 239 | release { |
| 240 | shrinkResources true |
| 241 | minifyEnabled true |
| 242 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' |
| 243 | } |
| 244 | } |
| 245 | |
| 246 | |
| 247 | def signingPropsFile = ["signing.properties", |
| 248 | "${System.getProperty('user.home')}/.keys/android/jabjab/signing.properties"] |
| 249 | .collect { new File(it) } |
| 250 | .find { it.exists() } |
| 251 | |
| 252 | if (signingPropsFile != null) { |
| 253 | Properties props = new Properties() |
| 254 | props.load(new FileInputStream(signingPropsFile)) |
| 255 | |
| 256 | // Password is never stored in signing.properties — read from env var set by build-release.sh |
| 257 | def ksPassword = props['keystore.password'] ?: "" |
| 258 | |
| 259 | signingConfigs { |
| 260 | release { |
| 261 | storeFile file(props['keystore']) |
| 262 | storePassword ksPassword |
| 263 | keyAlias props['keystore.alias'] |
| 264 | keyPassword ksPassword |
| 265 | } |
| 266 | } |
| 267 | buildTypes.release.signingConfig = signingConfigs.release |
| 268 | buildTypes.debug.signingConfig = signingConfigs.release |
| 269 | } |
| 270 | |
| 271 | |
| 272 | subprojects { |
| 273 | |
| 274 | afterEvaluate { |
| 275 | if (getPlugins().hasPlugin('android') || |
| 276 | getPlugins().hasPlugin('android-library')) { |
| 277 | |
| 278 | configure(android.lintOptions) { |
| 279 | disable 'AndroidGradlePluginVersion', 'MissingTranslation' |
| 280 | } |
| 281 | } |
| 282 | |
| 283 | } |
| 284 | } |
| 285 | packagingOptions { |
| 286 | resources { |
| 287 | excludes += ['META-INF/BCKEY.DSA', 'META-INF/BCKEY.SF', 'META-INF/versions/9/OSGI-INF/MANIFEST.MF'] |
| 288 | } |
| 289 | } |
| 290 | lint { |
| 291 | disable 'MissingTranslation', 'InvalidPackage', 'AppCompatResource' |
| 292 | } |
| 293 | buildFeatures { |
| 294 | buildConfig true |
| 295 | resValues = true |
| 296 | } |
| 297 | |
| 298 | } |
Built with passion for open-source software, XMPP, privacy, and security —
the belief that people deserve communication tools that serve them, not surveil them.
Dedicated to every brave man and woman who stands up against tyranny and oppression across the world.
And in memory of those who were silenced before they could speak freely.