build.gradle 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028
  1. import org.jetbrains.kotlin.gradle.tasks.KaptGenerateStubs
  2. plugins {
  3. id 'org.sonarqube'
  4. id 'org.jetbrains.kotlin.plugin.serialization' version "$kotlin_version"
  5. }
  6. apply plugin: 'com.android.application'
  7. apply plugin: 'kotlin-android'
  8. apply plugin: 'kotlin-kapt'
  9. // only apply the plugin if we are dealing with a AppGallery build
  10. if (getGradle().getStartParameter().getTaskRequests().toString().contains("Hms")) {
  11. println "enabling hms plugin"
  12. apply plugin: 'com.huawei.agconnect'
  13. }
  14. // version codes
  15. // Only use the scheme "<major>.<minor>.<patch>" for the app_version
  16. def app_version = "5.3.1"
  17. // beta_suffix with leading dash (e.g. `-beta1`)
  18. // should be one of (alpha|beta|rc) and an increasing number or empty for a regular release.
  19. // Note: in nightly builds this will be overwritten with a nightly version "-n12345"
  20. def beta_suffix = ""
  21. def defaultVersionCode = 956
  22. /**
  23. * Return the git hash, if git is installed.
  24. */
  25. def getGitHash = { ->
  26. def stdout = new ByteArrayOutputStream()
  27. def stderr = new ByteArrayOutputStream()
  28. try {
  29. exec {
  30. commandLine 'git', 'rev-parse', '--short', 'HEAD'
  31. standardOutput = stdout
  32. errorOutput = stderr
  33. ignoreExitValue true
  34. }
  35. } catch (ignored) { /* If git binary is not found, carry on */ }
  36. def hash = stdout.toString().trim()
  37. return (hash.isEmpty()) ? "?" : hash
  38. }
  39. /**
  40. * Look up the keystore with the specified name in a `keystore` directory
  41. * adjacent to this project directory. If it exists, return a signing config.
  42. * Otherwise, return null.
  43. */
  44. def findKeystore = { name ->
  45. def basePath = "${projectDir.getAbsolutePath()}/../../keystore"
  46. def storePath = "${basePath}/${name}.keystore"
  47. def storeFile = new File(storePath)
  48. if (storeFile.exists() && storeFile.isFile()) {
  49. def propertiesPath = "${basePath}/${name}.properties"
  50. def propertiesFile = new File(propertiesPath)
  51. if (propertiesFile.exists() && propertiesFile.isFile()) {
  52. Properties props = new Properties()
  53. propertiesFile.withInputStream { props.load(it) }
  54. return [
  55. storeFile: storePath,
  56. storePassword: props.storePassword,
  57. keyAlias: props.keyAlias,
  58. keyPassword: props.keyPassword,
  59. ]
  60. } else {
  61. return [
  62. storeFile: storePath,
  63. storePassword: null,
  64. keyAlias: null,
  65. keyPassword: null,
  66. ]
  67. }
  68. }
  69. }
  70. /**
  71. * Map with keystore paths (if found).
  72. */
  73. def keystores = [
  74. debug: findKeystore("debug"),
  75. release: findKeystore("threema"),
  76. hms_release: findKeystore("threema_hms"),
  77. onprem_release: findKeystore("onprem"),
  78. blue_release: findKeystore("red"),
  79. ]
  80. android {
  81. // NOTE: When adjusting compileSdkVersion, buildToolsVersion or ndkVersion,
  82. // make sure to adjust them in `scripts/Dockerfile` and
  83. // `.gitlab-ci.yml` as well!
  84. compileSdk 34
  85. buildToolsVersion = '34.0.0'
  86. ndkVersion '25.2.9519653'
  87. defaultConfig {
  88. // https://developer.android.com/training/testing/espresso/setup#analytics
  89. testInstrumentationRunnerArguments notAnnotation: 'ch.threema.app.TestFastlaneOnly,ch.threema.app.DangerousTest', disableAnalytics: 'true'
  90. minSdkVersion 21
  91. //noinspection OldTargetApi
  92. targetSdkVersion 33
  93. vectorDrawables.useSupportLibrary = true
  94. applicationId "ch.threema.app"
  95. testApplicationId 'ch.threema.app.test'
  96. versionCode defaultVersionCode
  97. versionName "${app_version}${beta_suffix}"
  98. resValue "string", "app_name", "Threema"
  99. // package name used for sync adapter - needs to match mime types below
  100. resValue "string", "package_name", applicationId
  101. resValue "string", "contacts_mime_type", "vnd.android.cursor.item/vnd.ch.threema.app.profile"
  102. resValue "string", "call_mime_type", "vnd.android.cursor.item/vnd.ch.threema.app.call"
  103. buildConfigField "int", "MAX_GROUP_SIZE", "256"
  104. buildConfigField "String", "CHAT_SERVER_PREFIX", "\"g-\""
  105. buildConfigField "String", "CHAT_SERVER_IPV6_PREFIX", "\"ds.g-\""
  106. buildConfigField "String", "CHAT_SERVER_SUFFIX", "\".0.threema.ch\""
  107. buildConfigField "int[]", "CHAT_SERVER_PORTS", "{5222, 443}"
  108. buildConfigField "String", "MEDIA_PATH", "\"Threema\""
  109. buildConfigField "boolean", "CHAT_SERVER_GROUPS", "true"
  110. buildConfigField "boolean", "DISABLE_CERT_PINNING", "false"
  111. buildConfigField "boolean", "VIDEO_CALLS_ENABLED", "true"
  112. buildConfigField "boolean", "GROUP_CALLS_ENABLED", "true"
  113. buildConfigField "byte[]", "SERVER_PUBKEY", "new byte[] {(byte) 0x45, (byte) 0x0b, (byte) 0x97, (byte) 0x57, (byte) 0x35, (byte) 0x27, (byte) 0x9f, (byte) 0xde, (byte) 0xcb, (byte) 0x33, (byte) 0x13, (byte) 0x64, (byte) 0x8f, (byte) 0x5f, (byte) 0xc6, (byte) 0xee, (byte) 0x9f, (byte) 0xf4, (byte) 0x36, (byte) 0x0e, (byte) 0xa9, (byte) 0x2a, (byte) 0x8c, (byte) 0x17, (byte) 0x51, (byte) 0xc6, (byte) 0x61, (byte) 0xe4, (byte) 0xc0, (byte) 0xd8, (byte) 0xc9, (byte) 0x09 }"
  114. buildConfigField "byte[]", "SERVER_PUBKEY_ALT", "new byte[] {(byte) 0xda, (byte) 0x7c, (byte) 0x73, (byte) 0x79, (byte) 0x8f, (byte) 0x97, (byte) 0xd5, (byte) 0x87, (byte) 0xc3, (byte) 0xa2, (byte) 0x5e, (byte) 0xbe, (byte) 0x0a, (byte) 0x91, (byte) 0x41, (byte) 0x7f, (byte) 0x76, (byte) 0xdb, (byte) 0xcc, (byte) 0xcd, (byte) 0xda, (byte) 0x29, (byte) 0x30, (byte) 0xe6, (byte) 0xa9, (byte) 0x09, (byte) 0x0a, (byte) 0xf6, (byte) 0x2e, (byte) 0xba, (byte) 0x6f, (byte) 0x15 }"
  115. buildConfigField "String", "GIT_HASH", "\"${getGitHash()}\""
  116. buildConfigField "String", "DIRECTORY_SERVER_URL", "\"https://apip.threema.ch/\""
  117. buildConfigField "String", "DIRECTORY_SERVER_IPV6_URL", "\"https://ds-apip.threema.ch/\""
  118. buildConfigField "String", "WORK_SERVER_URL", "null"
  119. buildConfigField "String", "WORK_SERVER_IPV6_URL", "null"
  120. buildConfigField "String", "MEDIATOR_SERVER_URL", "\"wss://mediator-{deviceGroupIdPrefix4}.threema.ch/{deviceGroupIdPrefix8}\""
  121. buildConfigField "String", "BLOB_SERVER_DOWNLOAD_URL", "\"https://blobp-{blobIdPrefix}.threema.ch/{blobId}\""
  122. buildConfigField "String", "BLOB_SERVER_DOWNLOAD_IPV6_URL", "\"https://ds-blobp-{blobIdPrefix}.threema.ch/{blobId}\""
  123. buildConfigField "String", "BLOB_SERVER_DONE_URL", "\"https://blobp-{blobIdPrefix}.threema.ch/{blobId}/done\""
  124. buildConfigField "String", "BLOB_SERVER_DONE_IPV6_URL", "\"https://ds-blobp-{blobIdPrefix}.threema.ch/{blobId}/done\""
  125. buildConfigField "String", "BLOB_SERVER_UPLOAD_URL", "\"https://blobp-upload.threema.ch/upload\""
  126. buildConfigField "String", "BLOB_SERVER_UPLOAD_IPV6_URL", "\"https://ds-blobp-upload.threema.ch/upload\""
  127. buildConfigField "String", "AVATAR_FETCH_URL", "\"https://avatar.threema.ch/\""
  128. buildConfigField "String", "SAFE_SERVER_URL", "\"https://safe-{backupIdPrefix8}.threema.ch/\""
  129. buildConfigField "String", "WEB_SERVER_URL", "\"https://web.threema.ch/\""
  130. buildConfigField "String", "APP_RATING_URL", "\"https://threema.ch/app-rating/android/{rating}\""
  131. buildConfigField "byte[]", "THREEMA_PUSH_PUBLIC_KEY", "new byte[] {(byte) 0xfd, (byte) 0x71, (byte) 0x1e, (byte) 0x1a, (byte) 0x0d, (byte) 0xb0, (byte) 0xe2, (byte) 0xf0, (byte) 0x3f, (byte) 0xca, (byte) 0xab, (byte) 0x6c, (byte) 0x43, (byte) 0xda, (byte) 0x25, (byte) 0x75, (byte) 0xb9, (byte) 0x51, (byte) 0x36, (byte) 0x64, (byte) 0xa6, (byte) 0x2a, (byte) 0x12, (byte) 0xbd, (byte) 0x07, (byte) 0x28, (byte) 0xd8, (byte) 0x7f, (byte) 0x71, (byte) 0x25, (byte) 0xcc, (byte) 0x24}"
  132. buildConfigField "String", "ONPREM_ID_PREFIX", "\"O\""
  133. buildConfigField "String", "LOG_TAG", "\"3ma\""
  134. buildConfigField "String", "DEFAULT_APP_THEME", "\"2\""
  135. buildConfigField "String[]", "ONPREM_CONFIG_TRUSTED_PUBLIC_KEYS", "null"
  136. buildConfigField "boolean", "SEND_CONSUMED_DELIVERY_RECEIPTS", "false"
  137. buildConfigField "boolean", "MD_ENABLED", "false"
  138. // config fields for action URLs / deep links
  139. buildConfigField "String", "uriScheme", "\"threema\""
  140. buildConfigField "String", "actionUrl", "\"go.threema.ch\""
  141. buildConfigField "String", "contactActionUrl", "\"threema.id\""
  142. buildConfigField "String", "groupLinkActionUrl", "\"threema.group\""
  143. // duplicated for manifest
  144. manifestPlaceholders = [
  145. uriScheme: "threema",
  146. contactActionUrl: "threema.id",
  147. groupLinkActionUrl: "threema.group",
  148. actionUrl: "go.threema.ch",
  149. callMimeType: "vnd.android.cursor.item/vnd.ch.threema.app.call",
  150. ]
  151. testInstrumentationRunner 'ch.threema.app.ThreemaTestRunner'
  152. // Only include language resources for those languages
  153. resourceConfigurations += [
  154. "en",
  155. "be-rBY",
  156. "ca",
  157. "cs",
  158. "de",
  159. "es",
  160. "fr",
  161. "gsw",
  162. "hu",
  163. "it",
  164. "ja",
  165. "nl-rNL",
  166. "no",
  167. "pl",
  168. "pt-rBR",
  169. "rm",
  170. "ru",
  171. "sk",
  172. "tr",
  173. "uk",
  174. "zh-rCN",
  175. "zh-rTW"
  176. ]
  177. }
  178. splits {
  179. abi {
  180. enable true
  181. reset()
  182. include 'armeabi-v7a', 'x86', 'arm64-v8a', 'x86_64'
  183. exclude 'armeabi', 'mips', 'mips64'
  184. universalApk project.hasProperty("buildUniversalApk")
  185. }
  186. }
  187. // Assign different version code for each output
  188. def abiVersionCodes = ['armeabi-v7a': 2, 'arm64-v8a': 3, 'x86': 8, 'x86_64': 9]
  189. android.applicationVariants.all { variant ->
  190. variant.outputs.each { output ->
  191. def abi = output.getFilter("ABI")
  192. output.versionCodeOverride =
  193. abiVersionCodes.get(abi, 0) * 1000000 + defaultVersionCode
  194. }
  195. }
  196. namespace 'ch.threema.app'
  197. flavorDimensions "default"
  198. productFlavors {
  199. none { }
  200. store_google { }
  201. store_threema {
  202. resValue "string", "shop_download_filename", "Threema-update.apk"
  203. }
  204. store_google_work {
  205. versionName "${app_version}k${beta_suffix}"
  206. applicationId "ch.threema.app.work"
  207. testApplicationId 'ch.threema.app.work.test'
  208. resValue "string", "app_name", "Threema Work"
  209. resValue "string", "package_name", applicationId
  210. resValue "string", "contacts_mime_type", "vnd.android.cursor.item/vnd.ch.threema.app.work.profile"
  211. resValue "string", "call_mime_type", "vnd.android.cursor.item/vnd.ch.threema.app.work.call"
  212. buildConfigField "String", "CHAT_SERVER_PREFIX", "\"w-\""
  213. buildConfigField "String", "CHAT_SERVER_IPV6_PREFIX", "\"ds.w-\""
  214. buildConfigField "String", "MEDIA_PATH", "\"ThreemaWork\""
  215. buildConfigField "String", "WORK_SERVER_URL", "\"https://apip-work.threema.ch/\""
  216. buildConfigField "String", "WORK_SERVER_IPV6_URL", "\"https://ds-apip-work.threema.ch/\""
  217. buildConfigField "String", "APP_RATING_URL", "\"https://threema.ch/app-rating/android-work/{rating}\""
  218. buildConfigField "String", "LOG_TAG", "\"3mawrk\""
  219. buildConfigField "String", "DEFAULT_APP_THEME", "\"2\""
  220. // config fields for action URLs / deep links
  221. buildConfigField "String", "uriScheme", "\"threemawork\""
  222. buildConfigField "String", "actionUrl", "\"work.threema.ch\""
  223. manifestPlaceholders = [
  224. uriScheme: "threemawork",
  225. actionUrl: "work.threema.ch",
  226. callMimeType: "vnd.android.cursor.item/vnd.ch.threema.app.work.call",
  227. ]
  228. }
  229. green {
  230. // The app was previously named `sandbox`. The app id remains unchanged to still be able to install updates.
  231. applicationId "ch.threema.app.sandbox"
  232. testApplicationId 'ch.threema.app.sandbox.test'
  233. resValue "string", "app_name", "Threema Green"
  234. resValue "string", "package_name", applicationId
  235. resValue "string", "contacts_mime_type", "vnd.android.cursor.item/vnd.ch.threema.app.sandbox.profile"
  236. resValue "string", "call_mime_type", "vnd.android.cursor.item/vnd.ch.threema.app.sandbox.call"
  237. buildConfigField "String", "MEDIA_PATH", "\"ThreemaGreen\""
  238. buildConfigField "String", "CHAT_SERVER_SUFFIX", "\".0.test.threema.ch\""
  239. buildConfigField "byte[]", "SERVER_PUBKEY", "new byte[] {(byte) 0x5a, (byte) 0x98, (byte) 0xf2, (byte) 0x3d, (byte) 0xe6, (byte) 0x56, (byte) 0x05, (byte) 0xd0, (byte) 0x50, (byte) 0xdc, (byte) 0x00, (byte) 0x64, (byte) 0xbe, (byte) 0x07, (byte) 0xdd, (byte) 0xdd, (byte) 0x81, (byte) 0x1d, (byte) 0xa1, (byte) 0x16, (byte) 0xa5, (byte) 0x43, (byte) 0xce, (byte) 0x43, (byte) 0xaa, (byte) 0x26, (byte) 0x87, (byte) 0xd1, (byte) 0x9f, (byte) 0x20, (byte) 0xaf, (byte) 0x3c }"
  240. buildConfigField "byte[]", "SERVER_PUBKEY_ALT", "new byte[] {(byte) 0x5a, (byte) 0x98, (byte) 0xf2, (byte) 0x3d, (byte) 0xe6, (byte) 0x56, (byte) 0x05, (byte) 0xd0, (byte) 0x50, (byte) 0xdc, (byte) 0x00, (byte) 0x64, (byte) 0xbe, (byte) 0x07, (byte) 0xdd, (byte) 0xdd, (byte) 0x81, (byte) 0x1d, (byte) 0xa1, (byte) 0x16, (byte) 0xa5, (byte) 0x43, (byte) 0xce, (byte) 0x43, (byte) 0xaa, (byte) 0x26, (byte) 0x87, (byte) 0xd1, (byte) 0x9f, (byte) 0x20, (byte) 0xaf, (byte) 0x3c }"
  241. buildConfigField "String", "DIRECTORY_SERVER_URL", "\"https://apip.test.threema.ch/\""
  242. buildConfigField "String", "DIRECTORY_SERVER_IPV6_URL", "\"https://ds-apip.test.threema.ch/\""
  243. buildConfigField "String", "MEDIATOR_SERVER_URL", "\"wss://mediator-{deviceGroupIdPrefix4}.test.threema.ch/{deviceGroupIdPrefix8}\""
  244. buildConfigField "String", "AVATAR_FETCH_URL", "\"https://avatar.test.threema.ch/\""
  245. buildConfigField "String", "APP_RATING_URL", "\"https://test.threema.ch/app-rating/android/{rating}\""
  246. buildConfigField "boolean", "MD_ENABLED", "true"
  247. }
  248. sandbox_work {
  249. versionName "${app_version}k${beta_suffix}"
  250. applicationId "ch.threema.app.sandbox.work"
  251. testApplicationId 'ch.threema.app.sandbox.work.test'
  252. resValue "string", "app_name", "Threema Sandbox Work"
  253. resValue "string", "package_name", applicationId
  254. resValue "string", "contacts_mime_type", "vnd.android.cursor.item/vnd.ch.threema.app.sandbox.work.profile"
  255. resValue "string", "call_mime_type", "vnd.android.cursor.item/vnd.ch.threema.app.sandbox.work.call"
  256. buildConfigField "String", "CHAT_SERVER_PREFIX", "\"w-\""
  257. buildConfigField "String", "CHAT_SERVER_IPV6_PREFIX", "\"ds.w-\""
  258. buildConfigField "String", "CHAT_SERVER_SUFFIX", "\".0.test.threema.ch\""
  259. buildConfigField "String", "MEDIA_PATH", "\"ThreemaWorkSandbox\""
  260. buildConfigField "byte[]", "SERVER_PUBKEY", "new byte[] {(byte) 0x5a, (byte) 0x98, (byte) 0xf2, (byte) 0x3d, (byte) 0xe6, (byte) 0x56, (byte) 0x05, (byte) 0xd0, (byte) 0x50, (byte) 0xdc, (byte) 0x00, (byte) 0x64, (byte) 0xbe, (byte) 0x07, (byte) 0xdd, (byte) 0xdd, (byte) 0x81, (byte) 0x1d, (byte) 0xa1, (byte) 0x16, (byte) 0xa5, (byte) 0x43, (byte) 0xce, (byte) 0x43, (byte) 0xaa, (byte) 0x26, (byte) 0x87, (byte) 0xd1, (byte) 0x9f, (byte) 0x20, (byte) 0xaf, (byte) 0x3c }"
  261. buildConfigField "byte[]", "SERVER_PUBKEY_ALT", "new byte[] {(byte) 0x5a, (byte) 0x98, (byte) 0xf2, (byte) 0x3d, (byte) 0xe6, (byte) 0x56, (byte) 0x05, (byte) 0xd0, (byte) 0x50, (byte) 0xdc, (byte) 0x00, (byte) 0x64, (byte) 0xbe, (byte) 0x07, (byte) 0xdd, (byte) 0xdd, (byte) 0x81, (byte) 0x1d, (byte) 0xa1, (byte) 0x16, (byte) 0xa5, (byte) 0x43, (byte) 0xce, (byte) 0x43, (byte) 0xaa, (byte) 0x26, (byte) 0x87, (byte) 0xd1, (byte) 0x9f, (byte) 0x20, (byte) 0xaf, (byte) 0x3c }"
  262. buildConfigField "String", "DIRECTORY_SERVER_URL", "\"https://apip.test.threema.ch/\""
  263. buildConfigField "String", "DIRECTORY_SERVER_IPV6_URL", "\"https://ds-apip.test.threema.ch/\""
  264. buildConfigField "String", "WORK_SERVER_URL", "\"https://apip-work.test.threema.ch/\""
  265. buildConfigField "String", "WORK_SERVER_IPV6_URL", "\"https://ds-apip-work.test.threema.ch/\""
  266. buildConfigField "String", "MEDIATOR_SERVER_URL", "\"wss://mediator-{deviceGroupIdPrefix4}.test.threema.ch/{deviceGroupIdPrefix8}\""
  267. buildConfigField "String", "AVATAR_FETCH_URL", "\"https://avatar.test.threema.ch/\""
  268. buildConfigField "String", "APP_RATING_URL", "\"https://test.threema.ch/app-rating/android-work/{rating}\""
  269. buildConfigField "String", "LOG_TAG", "\"3mawrk\""
  270. buildConfigField "String", "DEFAULT_APP_THEME", "\"2\""
  271. // config fields for action URLs / deep links
  272. buildConfigField "String", "uriScheme", "\"threemawork\""
  273. buildConfigField "String", "actionUrl", "\"work.test.threema.ch\""
  274. buildConfigField "boolean", "MD_ENABLED", "true"
  275. manifestPlaceholders = [
  276. uriScheme : "threemawork",
  277. actionUrl : "work.test.threema.ch",
  278. ]
  279. }
  280. onprem {
  281. versionName "${app_version}o${beta_suffix}"
  282. applicationId "ch.threema.app.onprem"
  283. testApplicationId 'ch.threema.app.onprem.test'
  284. resValue "string", "app_name", "Threema OnPrem"
  285. resValue "string", "package_name", applicationId
  286. resValue "string", "contacts_mime_type", "vnd.android.cursor.item/vnd.ch.threema.app.onprem.profile"
  287. resValue "string", "call_mime_type", "vnd.android.cursor.item/vnd.ch.threema.app.onprem.call"
  288. buildConfigField "int", "MAX_GROUP_SIZE", "256"
  289. buildConfigField "String", "CHAT_SERVER_PREFIX", "\"\""
  290. buildConfigField "String", "CHAT_SERVER_IPV6_PREFIX", "\"\""
  291. buildConfigField "String", "CHAT_SERVER_SUFFIX", "null"
  292. buildConfigField "String", "MEDIA_PATH", "\"ThreemaOnPrem\""
  293. buildConfigField "boolean", "CHAT_SERVER_GROUPS", "false"
  294. buildConfigField "byte[]", "SERVER_PUBKEY", "null"
  295. buildConfigField "byte[]", "SERVER_PUBKEY_ALT", "null"
  296. buildConfigField "String", "DIRECTORY_SERVER_URL", "null"
  297. buildConfigField "String", "DIRECTORY_SERVER_IPV6_URL", "null"
  298. buildConfigField "String", "BLOB_SERVER_DOWNLOAD_URL", "null"
  299. buildConfigField "String", "BLOB_SERVER_DOWNLOAD_IPV6_URL", "null"
  300. buildConfigField "String", "BLOB_SERVER_DONE_URL", "null"
  301. buildConfigField "String", "BLOB_SERVER_DONE_IPV6_URL", "null"
  302. buildConfigField "String", "BLOB_SERVER_UPLOAD_URL", "null"
  303. buildConfigField "String", "BLOB_SERVER_UPLOAD_IPV6_URL", "null"
  304. buildConfigField "String[]", "ONPREM_CONFIG_TRUSTED_PUBLIC_KEYS", "new String[] {\"ek1qBp4DyRmLL9J5sCmsKSfwbsiGNB4veDAODjkwe/k=\", \"Hrk8aCjwKkXySubI7CZ3y9Sx+oToEHjNkGw98WSRneU=\", \"5pEn1T/5bhecNWrp9NgUQweRfgVtu/I8gRb3VxGP7k4=\"}"
  305. buildConfigField "String", "LOG_TAG", "\"3maop\""
  306. // config fields for action URLs / deep links
  307. buildConfigField "String", "uriScheme", "\"threemaonprem\""
  308. buildConfigField "String", "actionUrl", "\"onprem.threema.ch\""
  309. manifestPlaceholders = [
  310. uriScheme: "threemaonprem",
  311. actionUrl: "onprem.threema.ch",
  312. callMimeType: "vnd.android.cursor.item/vnd.ch.threema.app.onprem.call",
  313. ]
  314. }
  315. onprem_internal {
  316. versionName "${app_version}o${beta_suffix}"
  317. applicationId "ch.threema.app.onprem.internal"
  318. testApplicationId 'ch.threema.app.onprem.internal.test'
  319. resValue "string", "app_name", "Threema OnPrem Internal"
  320. resValue "string", "package_name", applicationId
  321. resValue "string", "contacts_mime_type", "vnd.android.cursor.item/vnd.ch.threema.app.onprem.internal.profile"
  322. resValue "string", "call_mime_type", "vnd.android.cursor.item/vnd.ch.threema.app.onprem.internal.call"
  323. buildConfigField "int", "MAX_GROUP_SIZE", "256"
  324. buildConfigField "String", "CHAT_SERVER_PREFIX", "\"\""
  325. buildConfigField "String", "CHAT_SERVER_IPV6_PREFIX", "\"\""
  326. buildConfigField "String", "CHAT_SERVER_SUFFIX", "null"
  327. buildConfigField "String", "MEDIA_PATH", "\"ThreemaOnPremInt\""
  328. buildConfigField "boolean", "CHAT_SERVER_GROUPS", "false"
  329. buildConfigField "byte[]", "SERVER_PUBKEY", "null"
  330. buildConfigField "byte[]", "SERVER_PUBKEY_ALT", "null"
  331. buildConfigField "String", "DIRECTORY_SERVER_URL", "null"
  332. buildConfigField "String", "DIRECTORY_SERVER_IPV6_URL", "null"
  333. buildConfigField "String", "BLOB_SERVER_DOWNLOAD_URL", "null"
  334. buildConfigField "String", "BLOB_SERVER_DOWNLOAD_IPV6_URL", "null"
  335. buildConfigField "String", "BLOB_SERVER_DONE_URL", "null"
  336. buildConfigField "String", "BLOB_SERVER_DONE_IPV6_URL", "null"
  337. buildConfigField "String", "BLOB_SERVER_UPLOAD_URL", "null"
  338. buildConfigField "String", "BLOB_SERVER_UPLOAD_IPV6_URL", "null"
  339. buildConfigField "String[]", "ONPREM_CONFIG_TRUSTED_PUBLIC_KEYS", "new String[] {\"ek1qBp4DyRmLL9J5sCmsKSfwbsiGNB4veDAODjkwe/k=\", \"Hrk8aCjwKkXySubI7CZ3y9Sx+oToEHjNkGw98WSRneU=\", \"5pEn1T/5bhecNWrp9NgUQweRfgVtu/I8gRb3VxGP7k4=\"}"
  340. buildConfigField "String", "LOG_TAG", "\"3maoi\""
  341. // config fields for action URLs / deep links
  342. buildConfigField "String", "uriScheme", "\"threemaonprem\""
  343. buildConfigField "String", "actionUrl", "\"onprem.threema.ch\""
  344. manifestPlaceholders = [
  345. uriScheme: "threemaonprem",
  346. actionUrl: "onprem.threema.ch",
  347. callMimeType: "vnd.android.cursor.item/vnd.ch.threema.app.onprem.internal.call",
  348. ]
  349. }
  350. blue { // Essentially like sandbox work, but with a different icon and accent color, used for internal testing
  351. versionName "${app_version}r${beta_suffix}"
  352. // The app was previously named `red`. The app id remains unchanged to still be able to install updates.
  353. applicationId "ch.threema.app.red"
  354. testApplicationId 'ch.threema.app.blue.test'
  355. resValue "string", "app_name", "Threema Blue"
  356. resValue "string", "package_name", applicationId
  357. resValue "string", "contacts_mime_type", "vnd.android.cursor.item/vnd.ch.threema.app.blue.profile"
  358. resValue "string", "call_mime_type", "vnd.android.cursor.item/vnd.ch.threema.app.blue.call"
  359. buildConfigField "String", "CHAT_SERVER_PREFIX", "\"w-\""
  360. buildConfigField "String", "CHAT_SERVER_IPV6_PREFIX", "\"ds.w-\""
  361. buildConfigField "String", "CHAT_SERVER_SUFFIX", "\".0.test.threema.ch\""
  362. buildConfigField "String", "MEDIA_PATH", "\"ThreemaBlue\""
  363. buildConfigField "byte[]", "SERVER_PUBKEY", "new byte[] {(byte) 0x5a, (byte) 0x98, (byte) 0xf2, (byte) 0x3d, (byte) 0xe6, (byte) 0x56, (byte) 0x05, (byte) 0xd0, (byte) 0x50, (byte) 0xdc, (byte) 0x00, (byte) 0x64, (byte) 0xbe, (byte) 0x07, (byte) 0xdd, (byte) 0xdd, (byte) 0x81, (byte) 0x1d, (byte) 0xa1, (byte) 0x16, (byte) 0xa5, (byte) 0x43, (byte) 0xce, (byte) 0x43, (byte) 0xaa, (byte) 0x26, (byte) 0x87, (byte) 0xd1, (byte) 0x9f, (byte) 0x20, (byte) 0xaf, (byte) 0x3c }"
  364. buildConfigField "byte[]", "SERVER_PUBKEY_ALT", "new byte[] {(byte) 0x5a, (byte) 0x98, (byte) 0xf2, (byte) 0x3d, (byte) 0xe6, (byte) 0x56, (byte) 0x05, (byte) 0xd0, (byte) 0x50, (byte) 0xdc, (byte) 0x00, (byte) 0x64, (byte) 0xbe, (byte) 0x07, (byte) 0xdd, (byte) 0xdd, (byte) 0x81, (byte) 0x1d, (byte) 0xa1, (byte) 0x16, (byte) 0xa5, (byte) 0x43, (byte) 0xce, (byte) 0x43, (byte) 0xaa, (byte) 0x26, (byte) 0x87, (byte) 0xd1, (byte) 0x9f, (byte) 0x20, (byte) 0xaf, (byte) 0x3c }"
  365. buildConfigField "String", "DIRECTORY_SERVER_URL", "\"https://apip.test.threema.ch/\""
  366. buildConfigField "String", "DIRECTORY_SERVER_IPV6_URL", "\"https://ds-apip.test.threema.ch/\""
  367. buildConfigField "String", "WORK_SERVER_URL", "\"https://apip-work.test.threema.ch/\""
  368. buildConfigField "String", "WORK_SERVER_IPV6_URL", "\"https://ds-apip-work.test.threema.ch/\""
  369. buildConfigField "String", "MEDIATOR_SERVER_URL", "\"wss://mediator-{deviceGroupIdPrefix4}.test.threema.ch/{deviceGroupIdPrefix8}\""
  370. buildConfigField "String", "AVATAR_FETCH_URL", "\"https://avatar.test.threema.ch/\""
  371. buildConfigField "String", "APP_RATING_URL", "\"https://test.threema.ch/app-rating/android-work/{rating}\""
  372. buildConfigField "String", "LOG_TAG", "\"3mablue\""
  373. buildConfigField "boolean", "SEND_CONSUMED_DELIVERY_RECEIPTS", "true"
  374. // config fields for action URLs / deep links
  375. buildConfigField "String", "uriScheme", "\"threemablue\""
  376. buildConfigField "String", "actionUrl", "\"blue.threema.ch\""
  377. manifestPlaceholders = [
  378. uriScheme: "threemablue",
  379. actionUrl: "blue.threema.ch",
  380. callMimeType: "vnd.android.cursor.item/vnd.ch.threema.app.blue.call",
  381. ]
  382. }
  383. hms {
  384. applicationId "ch.threema.app.hms"
  385. }
  386. hms_work {
  387. versionName "${app_version}k${beta_suffix}"
  388. applicationId "ch.threema.app.work.hms"
  389. testApplicationId 'ch.threema.app.work.test.hms'
  390. resValue "string", "app_name", "Threema Work"
  391. resValue "string", "package_name", "ch.threema.app.work"
  392. resValue "string", "contacts_mime_type", "vnd.android.cursor.item/vnd.ch.threema.app.work.profile"
  393. resValue "string", "call_mime_type", "vnd.android.cursor.item/vnd.ch.threema.app.work.call"
  394. buildConfigField "String", "CHAT_SERVER_PREFIX", "\"w-\""
  395. buildConfigField "String", "CHAT_SERVER_IPV6_PREFIX", "\"ds.w-\""
  396. buildConfigField "String", "MEDIA_PATH", "\"ThreemaWork\""
  397. buildConfigField "String", "WORK_SERVER_URL", "\"https://apip-work.threema.ch/\""
  398. buildConfigField "String", "WORK_SERVER_IPV6_URL", "\"https://ds-apip-work.threema.ch/\""
  399. buildConfigField "String", "APP_RATING_URL", "\"https://threema.ch/app-rating/android-work/{rating}\""
  400. buildConfigField "String", "LOG_TAG", "\"3mawrk\""
  401. buildConfigField "String", "DEFAULT_APP_THEME", "\"2\""
  402. // config fields for action URLs / deep links
  403. buildConfigField "String", "uriScheme", "\"threemawork\""
  404. buildConfigField "String", "actionUrl", "\"work.threema.ch\""
  405. manifestPlaceholders = [
  406. uriScheme: "threemawork",
  407. actionUrl: "work.threema.ch",
  408. callMimeType: "vnd.android.cursor.item/vnd.ch.threema.app.work.call",
  409. ]
  410. }
  411. libre {
  412. versionName "${app_version}l${beta_suffix}"
  413. applicationId "ch.threema.app.libre"
  414. testApplicationId 'ch.threema.app.libre.test'
  415. resValue "string", "package_name", applicationId
  416. resValue "string", "app_name", "Threema Libre"
  417. buildConfigField "String", "MEDIA_PATH", "\"ThreemaLibre\""
  418. }
  419. }
  420. signingConfigs {
  421. // Debug config
  422. if (keystores.debug != null) {
  423. debug {
  424. storeFile file(keystores.debug.storeFile)
  425. }
  426. } else {
  427. logger.warn("No debug keystore found. Falling back to locally generated keystore.")
  428. }
  429. // Release config
  430. if (keystores.release != null) {
  431. release {
  432. storeFile file(keystores.release.storeFile)
  433. storePassword keystores.release.storePassword
  434. keyAlias keystores.release.keyAlias
  435. keyPassword keystores.release.keyPassword
  436. }
  437. } else {
  438. logger.warn("No release keystore found. Falling back to locally generated keystore.")
  439. }
  440. // Release config
  441. if (keystores.hms_release != null) {
  442. hms_release {
  443. storeFile file(keystores.hms_release.storeFile)
  444. storePassword keystores.hms_release.storePassword
  445. keyAlias keystores.hms_release.keyAlias
  446. keyPassword keystores.hms_release.keyPassword
  447. }
  448. } else {
  449. logger.warn("No hms keystore found. Falling back to locally generated keystore.")
  450. }
  451. // Onprem release config
  452. if (keystores.onprem_release != null) {
  453. onprem_release {
  454. storeFile file(keystores.onprem_release.storeFile)
  455. storePassword keystores.onprem_release.storePassword
  456. keyAlias keystores.onprem_release.keyAlias
  457. keyPassword keystores.onprem_release.keyPassword
  458. }
  459. } else {
  460. logger.warn("No onprem keystore found. Falling back to locally generated keystore.")
  461. }
  462. // Blue release config
  463. if (keystores.blue_release != null) {
  464. blue_release {
  465. storeFile file(keystores.blue_release.storeFile)
  466. storePassword keystores.blue_release.storePassword
  467. keyAlias keystores.blue_release.keyAlias
  468. keyPassword keystores.blue_release.keyPassword
  469. }
  470. } else {
  471. logger.warn("No blue keystore found. Falling back to locally generated keystore.")
  472. }
  473. // Note: Libre release is signed with HSM, no config here
  474. }
  475. sourceSets {
  476. main {
  477. assets.srcDirs = ['assets']
  478. jniLibs.srcDirs = ['libs']
  479. }
  480. // Based on Google services
  481. none {
  482. java.srcDir 'src/google_services_based/java'
  483. }
  484. store_google {
  485. java.srcDir 'src/google_services_based/java'
  486. }
  487. store_google_work {
  488. java.srcDir 'src/google_services_based/java'
  489. }
  490. store_threema {
  491. java.srcDir 'src/google_services_based/java'
  492. }
  493. libre {
  494. assets.srcDirs = ['src/foss_based/assets']
  495. java.srcDir 'src/foss_based/java'
  496. }
  497. onprem {
  498. java.srcDir 'src/google_services_based/java'
  499. }
  500. onprem_internal {
  501. java.srcDir 'src/google_services_based/java'
  502. }
  503. green {
  504. java.srcDir 'src/google_services_based/java'
  505. manifest.srcFile 'src/store_google/AndroidManifest.xml'
  506. }
  507. sandbox_work {
  508. java.srcDir 'src/google_services_based/java'
  509. res.srcDir 'src/store_google_work/res'
  510. manifest.srcFile 'src/store_google_work/AndroidManifest.xml'
  511. }
  512. blue {
  513. java.srcDir 'src/google_services_based/java'
  514. res.srcDir 'src/blue/res'
  515. }
  516. // Based on Huawei services
  517. hms {
  518. java.srcDir 'src/hms_services_based/java'
  519. }
  520. hms_work {
  521. java.srcDir 'src/hms_services_based/java'
  522. res.srcDir 'src/store_google_work/res'
  523. }
  524. // FOSS, no proprietary services
  525. libre {
  526. assets.srcDirs = ['src/foss_based/assets']
  527. java.srcDir 'src/foss_based/java'
  528. }
  529. }
  530. buildTypes {
  531. debug {
  532. debuggable true
  533. jniDebuggable false
  534. testCoverageEnabled false
  535. ndk {
  536. debugSymbolLevel 'FULL'
  537. }
  538. if (keystores['debug'] != null) {
  539. signingConfig signingConfigs.debug
  540. }
  541. }
  542. release {
  543. debuggable false
  544. jniDebuggable false
  545. minifyEnabled true
  546. shrinkResources false // Caused inconsistencies between local and CI builds
  547. proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-project.txt'
  548. ndk {
  549. debugSymbolLevel 'FULL' // 'SYMBOL_TABLE'
  550. }
  551. if (keystores['release'] != null) {
  552. productFlavors.store_google.signingConfig signingConfigs.release
  553. productFlavors.store_google_work.signingConfig signingConfigs.release
  554. productFlavors.store_threema.signingConfig signingConfigs.release
  555. productFlavors.green.signingConfig signingConfigs.release
  556. productFlavors.sandbox_work.signingConfig signingConfigs.release
  557. productFlavors.none.signingConfig signingConfigs.release
  558. }
  559. if (keystores['hms_release'] != null) {
  560. productFlavors.hms.signingConfig signingConfigs.hms_release
  561. productFlavors.hms_work.signingConfig signingConfigs.hms_release
  562. }
  563. if (keystores['onprem_release'] != null) {
  564. productFlavors.onprem.signingConfig signingConfigs.onprem_release
  565. }
  566. if (keystores['blue_release'] != null) {
  567. productFlavors.blue.signingConfig signingConfigs.blue_release
  568. }
  569. // Note: Libre release is signed with HSM, no config here
  570. }
  571. }
  572. // Only build relevant buildType / flavor combinations
  573. variantFilter { variant ->
  574. def names = variant.flavors*.name
  575. if (
  576. variant.buildType.name == "release" && (
  577. names.contains("green") || names.contains("sandbox_work")
  578. )
  579. ) {
  580. setIgnore(true)
  581. }
  582. }
  583. externalNativeBuild {
  584. ndkBuild {
  585. path 'jni/Android.mk'
  586. }
  587. }
  588. packagingOptions {
  589. jniLibs {
  590. // replacement for extractNativeLibs in AndroidManifest
  591. useLegacyPackaging = false
  592. }
  593. resources {
  594. excludes += [
  595. 'META-INF/DEPENDENCIES.txt',
  596. 'META-INF/LICENSE.txt',
  597. 'META-INF/NOTICE.txt',
  598. 'META-INF/NOTICE',
  599. 'META-INF/LICENSE',
  600. 'META-INF/DEPENDENCIES',
  601. 'META-INF/notice.txt',
  602. 'META-INF/license.txt',
  603. 'META-INF/dependencies.txt',
  604. 'META-INF/LGPL2.1',
  605. '**/*.proto',
  606. 'DebugProbesKt.bin'
  607. ]
  608. }
  609. }
  610. testOptions {
  611. // Disable animations in instrumentation tests
  612. animationsDisabled true
  613. unitTests {
  614. all {
  615. // All the usual Gradle options.
  616. testLogging {
  617. events "passed", "skipped", "failed", "standardOut", "standardError"
  618. outputs.upToDateWhen { false }
  619. exceptionFormat = 'full'
  620. }
  621. jvmArgs = jvmArgs + ['--add-opens=java.base/java.util=ALL-UNNAMED']
  622. jvmArgs = jvmArgs + ['--add-opens=java.base/java.util.stream=ALL-UNNAMED']
  623. jvmArgs = jvmArgs + ['--add-opens=java.base/java.lang=ALL-UNNAMED']
  624. }
  625. // By default, local unit tests throw an exception any time the code you are testing tries to access
  626. // Android platform APIs (unless you mock Android dependencies yourself or with a testing
  627. // framework like Mockito). However, you can enable the following property so that the test
  628. // returns either null or zero when accessing platform APIs, rather than throwing an exception.
  629. returnDefaultValues true
  630. }
  631. }
  632. compileOptions {
  633. coreLibraryDesugaringEnabled true
  634. sourceCompatibility JavaVersion.VERSION_11
  635. targetCompatibility JavaVersion.VERSION_11
  636. }
  637. java {
  638. toolchain {
  639. languageVersion.set(JavaLanguageVersion.of(17))
  640. }
  641. }
  642. kotlin {
  643. jvmToolchain(17)
  644. }
  645. androidResources {
  646. noCompress 'png'
  647. }
  648. lint {
  649. // if true, stop the gradle build if errors are found
  650. abortOnError true
  651. // if true, check all issues, including those that are off by default
  652. checkAllWarnings true
  653. // check dependencies
  654. checkDependencies true
  655. // set to true to have all release builds run lint on issues with severity=fatal
  656. // and abort the build (controlled by abortOnError above) if fatal issues are found
  657. checkReleaseBuilds true
  658. // turn off checking the given issue id's
  659. disable 'TypographyFractions', 'TypographyQuotes', 'RtlHardcoded', 'RtlCompat', 'RtlEnabled'
  660. // Set the severity of the given issues to error
  661. error 'Wakelock', 'TextViewEdits', 'ResourceAsColor'
  662. // Set the severity of the given issues to fatal (which means they will be
  663. // checked during release builds (even if the lint target is not included)
  664. fatal 'NewApi', 'InlinedApi'
  665. // Set the severity of the given issues to ignore (same as disabling the check)
  666. ignore 'TypographyQuotes'
  667. ignoreWarnings false
  668. // if true, don't include source code lines in the error output
  669. noLines false
  670. // if true, show all locations for an error, do not truncate lists, etc.
  671. showAll true
  672. // Set the severity of the given issues to warning
  673. warning 'MissingTranslation'
  674. // if true, treat all warnings as errors
  675. warningsAsErrors false
  676. // file to write report to (if not specified, defaults to lint-results.xml)
  677. xmlOutput file('lint-report.xml')
  678. // if true, generate an XML report for use by for example Jenkins
  679. xmlReport true
  680. }
  681. }
  682. dependencies {
  683. configurations.all {
  684. // Prefer modules that are part of this build (multi-project or composite build)
  685. // over external modules
  686. resolutionStrategy.preferProjectModules()
  687. // Alternatively, we can fail eagerly on version conflict to see the conflicts
  688. //resolutionStrategy.failOnVersionConflict()
  689. }
  690. coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.4'
  691. implementation project(':domain')
  692. implementation 'net.zetetic:sqlcipher-android:4.5.5@aar'
  693. implementation 'com.davemorrissey.labs:subsampling-scale-image-view-androidx:3.10.0'
  694. implementation 'net.sf.opencsv:opencsv:2.3'
  695. implementation 'net.lingala.zip4j:zip4j:2.11.5'
  696. implementation 'com.getkeepsafe.taptargetview:taptargetview:1.13.3'
  697. // commons-io >2.6 requires android 8
  698. implementation 'commons-io:commons-io:2.6'
  699. implementation 'org.apache.commons:commons-text:1.10.0'
  700. implementation "org.slf4j:slf4j-api:$slf4j_version"
  701. implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.28'
  702. implementation 'com.vanniktech:android-image-cropper:4.5.0'
  703. implementation 'com.datatheorem.android.trustkit:trustkit:1.1.5'
  704. implementation 'me.zhanghai.android.fastscroll:library:1.3.0'
  705. implementation 'com.googlecode.ez-vcard:ez-vcard:0.11.3'
  706. implementation 'com.alexvasilkov:gesture-views:2.8.3'
  707. // AndroidX / Jetpack support libraries
  708. implementation "androidx.preference:preference-ktx:1.2.1"
  709. implementation 'androidx.recyclerview:recyclerview:1.3.2'
  710. implementation 'androidx.palette:palette-ktx:1.0.0'
  711. implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
  712. implementation 'androidx.core:core-ktx:1.12.0'
  713. implementation 'androidx.appcompat:appcompat:1.6.1'
  714. implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
  715. implementation 'androidx.biometric:biometric:1.1.0'
  716. implementation 'androidx.work:work-runtime-ktx:2.9.0'
  717. implementation 'androidx.fragment:fragment-ktx:1.6.2'
  718. implementation 'androidx.activity:activity-ktx:1.8.2'
  719. implementation 'androidx.sqlite:sqlite:2.2.2'
  720. implementation "androidx.concurrent:concurrent-futures:1.1.0"
  721. implementation "androidx.camera:camera-camera2:1.3.2"
  722. implementation "androidx.camera:camera-lifecycle:1.3.2"
  723. implementation "androidx.camera:camera-view:1.3.2"
  724. implementation 'androidx.camera:camera-video:1.3.2'
  725. implementation "androidx.media:media:1.7.0"
  726. implementation 'androidx.media3:media3-exoplayer:1.3.1'
  727. implementation 'androidx.media3:media3-ui:1.3.1'
  728. implementation "androidx.media3:media3-session:1.3.1"
  729. implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0"
  730. implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.7.0"
  731. implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.7.0"
  732. implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:2.7.0"
  733. implementation "androidx.lifecycle:lifecycle-service:2.7.0"
  734. implementation "androidx.lifecycle:lifecycle-process:2.7.0"
  735. implementation "androidx.lifecycle:lifecycle-common-java8:2.7.0"
  736. implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
  737. implementation "androidx.paging:paging-runtime-ktx:3.2.1"
  738. implementation "androidx.sharetarget:sharetarget:1.2.0"
  739. implementation 'androidx.room:room-runtime:2.6.1'
  740. implementation 'androidx.window:window:1.2.0'
  741. kapt 'androidx.room:room-compiler:2.6.1'
  742. implementation 'com.google.android.material:material:1.10.0' // last version before switch to tonal system: https://github.com/material-components/material-components-android/releases/tag/1.11.0
  743. implementation 'com.google.zxing:core:3.3.3' // zxing 3.4 crashes on API < 24
  744. implementation 'com.googlecode.libphonenumber:libphonenumber:8.13.23' // make sure to update this in domain's build.gradle as well
  745. // webclient dependencies
  746. implementation 'org.msgpack:msgpack-core:0.8.24!!'
  747. implementation 'com.fasterxml.jackson.core:jackson-core:2.12.5!!'
  748. implementation 'com.neovisionaries:nv-websocket-client:2.9'
  749. // Backport of Streams and CompletableFuture. Remove once API level 24 is supported.
  750. implementation 'net.sourceforge.streamsupport:streamsupport-cfuture:1.7.4'
  751. implementation('org.saltyrtc:saltyrtc-client:0.14.2') {
  752. exclude group: 'org.json'
  753. }
  754. implementation 'org.saltyrtc:chunked-dc:1.0.1'
  755. implementation 'ch.threema:webrtc-android:123.0.0'
  756. implementation('org.saltyrtc:saltyrtc-task-webrtc:0.18.1') {
  757. exclude module: 'saltyrtc-client'
  758. }
  759. // Glide components
  760. // Glide 4.15+ does not work on API 21
  761. implementation 'com.github.bumptech.glide:glide:4.16.0'
  762. kapt 'com.github.bumptech.glide:compiler:4.16.0'
  763. annotationProcessor 'com.github.bumptech.glide:compiler:4.16.0'
  764. // Kotlin
  765. implementation 'androidx.core:core-ktx:1.10.1'
  766. implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
  767. implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
  768. implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1"
  769. testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
  770. androidTestImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
  771. // use leak canary in dev builds
  772. if (!project.hasProperty("noLeakCanary")) {
  773. def leakCanaryDependency = 'com.squareup.leakcanary:leakcanary-android:2.13'
  774. blueImplementation(leakCanaryDependency)
  775. greenImplementation(leakCanaryDependency)
  776. sandbox_workImplementation(leakCanaryDependency)
  777. // Uncomment the following line to use leak canary in *any* debug build
  778. // debugImplementation(leakCanaryDependency)
  779. }
  780. // test dependencies
  781. testImplementation "junit:junit:$junit_version"
  782. testImplementation(testFixtures(project(":domain")))
  783. // use powermock instead of mockito. it support mocking static classes.
  784. def mockitoVersion = '2.0.9'
  785. testImplementation "org.powermock:powermock-api-mockito2:${mockitoVersion}"
  786. testImplementation "org.powermock:powermock-module-junit4-rule-agent:${mockitoVersion}"
  787. testImplementation "org.powermock:powermock-module-junit4-rule:${mockitoVersion}"
  788. testImplementation "org.powermock:powermock-module-junit4:${mockitoVersion}"
  789. // add JSON support to tests without mocking
  790. testImplementation 'org.json:json:20220924'
  791. testImplementation 'com.tngtech.archunit:archunit-junit4:0.18.0'
  792. androidTestImplementation(testFixtures(project(":domain")))
  793. androidTestImplementation 'androidx.test:rules:1.5.0'
  794. androidTestImplementation 'tools.fastlane:screengrab:2.1.1', {
  795. exclude group: 'androidx.annotation', module: 'annotation'
  796. }
  797. androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0', {
  798. exclude group: 'androidx.annotation', module: 'annotation'
  799. }
  800. androidTestImplementation 'androidx.test:runner:1.4.0', {
  801. exclude group: 'androidx.annotation', module: 'annotation'
  802. }
  803. androidTestImplementation 'androidx.test.ext:junit-ktx:1.1.5'
  804. androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.4.0', {
  805. exclude group: 'androidx.annotation', module: 'annotation'
  806. exclude group: 'androidx.appcompat', module: 'appcompat'
  807. exclude group: 'androidx.legacy', module: 'legacy-support-v4'
  808. exclude group: 'com.google.android.material', module: 'material'
  809. exclude group: 'androidx.recyclerview', module: 'recyclerview'
  810. exclude(group: 'org.checkerframework', module: 'checker')
  811. exclude module: "protobuf-lite"
  812. }
  813. androidTestImplementation 'androidx.test.espresso:espresso-intents:3.4.0', {
  814. exclude group: 'androidx.annotation', module: 'annotation'
  815. }
  816. androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0'
  817. androidTestImplementation 'androidx.test:core-ktx:1.5.0'
  818. androidTestImplementation "org.mockito:mockito-core:4.8.1"
  819. androidTestImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$kotlin_coroutines_version"
  820. // Google Play Services and related libraries
  821. def googleDependencies = [
  822. // Play services
  823. 'com.google.android.gms:play-services-base:18.0.1': [],
  824. // Firebase push
  825. 'com.google.firebase:firebase-messaging:23.1.2': [
  826. [group: 'com.google.firebase', module: 'firebase-core'],
  827. [group: 'com.google.firebase', module: 'firebase-analytics'],
  828. [group: 'com.google.firebase', module: 'firebase-measurement-connector'],
  829. ],
  830. ]
  831. googleDependencies.each {
  832. def dependency = it.key
  833. def excludes = it.value
  834. noneImplementation(dependency) { excludes.each { exclude it } }
  835. store_googleImplementation(dependency) { excludes.each { exclude it } }
  836. store_google_workImplementation(dependency) { excludes.each { exclude it } }
  837. store_threemaImplementation(dependency) { excludes.each { exclude it } }
  838. onpremImplementation(dependency) { excludes.each { exclude it } }
  839. onprem_internalImplementation(dependency) { excludes.each { exclude it } }
  840. greenImplementation(dependency) { excludes.each { exclude it } }
  841. sandbox_workImplementation(dependency) { excludes.each { exclude it } }
  842. blueImplementation(dependency) { excludes.each { exclude it } }
  843. }
  844. // Google Assistant Voice Action verification library
  845. noneImplementation(name: 'libgsaverification-client', ext: 'aar')
  846. store_googleImplementation(name: 'libgsaverification-client', ext: 'aar')
  847. store_google_workImplementation(name: 'libgsaverification-client', ext: 'aar')
  848. onpremImplementation(name: 'libgsaverification-client', ext: 'aar')
  849. onprem_internalImplementation(name: 'libgsaverification-client', ext: 'aar')
  850. store_threemaImplementation(name: 'libgsaverification-client', ext: 'aar')
  851. greenImplementation(name: 'libgsaverification-client', ext: 'aar')
  852. sandbox_workImplementation(name: 'libgsaverification-client', ext: 'aar')
  853. blueImplementation(name: 'libgsaverification-client', ext: 'aar')
  854. // Maplibre (may have transitive dependencies on Google location services)
  855. def maplibreDependency = 'org.maplibre.gl:android-sdk:10.3.0'
  856. noneImplementation maplibreDependency
  857. store_googleImplementation maplibreDependency
  858. store_google_workImplementation maplibreDependency
  859. store_threemaImplementation maplibreDependency
  860. libreImplementation maplibreDependency, { exclude group: 'com.google.android.gms' }
  861. onpremImplementation maplibreDependency
  862. onprem_internalImplementation maplibreDependency
  863. greenImplementation maplibreDependency
  864. sandbox_workImplementation maplibreDependency
  865. blueImplementation maplibreDependency
  866. hmsImplementation maplibreDependency
  867. hms_workImplementation maplibreDependency
  868. // Huawei related libraries (only for hms* build variants)
  869. def huaweiDependencies = [
  870. // HMS push
  871. 'com.huawei.hms:push:6.3.0.304': [
  872. // Exclude agconnect dependency, we'll replace it with the vendored version below
  873. [group: 'com.huawei.agconnect'],
  874. ],
  875. ]
  876. huaweiDependencies.each {
  877. def dependency = it.key
  878. def excludes = it.value
  879. hmsImplementation(dependency) { excludes.each { exclude it } }
  880. hms_workImplementation(dependency) { excludes.each { exclude it } }
  881. }
  882. hmsImplementation(name: 'agconnect-core-1.9.1.301', ext: 'aar')
  883. hms_workImplementation(name: 'agconnect-core-1.9.1.301', ext: 'aar')
  884. }
  885. tasks.withType(KaptGenerateStubs).configureEach {
  886. kotlinOptions {
  887. jvmTarget = JavaVersion.VERSION_11.toString()
  888. }
  889. }
  890. sonarqube {
  891. properties {
  892. property "sonar.sources", "src/main/, ../scripts/, ../scripts-internal/"
  893. property "sonar.exclusions", "src/main/java/ch/threema/localcrypto/**, src/test/java/ch/threema/localcrypto/**"
  894. property "sonar.tests", "src/test/"
  895. property "sonar.sourceEncoding", "UTF-8"
  896. property "sonar.verbose", "true"
  897. property 'sonar.projectKey', 'android-client'
  898. property 'sonar.projectName', 'Threema for Android'
  899. }
  900. }
  901. // Set up Gradle tasks to fetch screenshots on UI test failures
  902. // See https://medium.com/stepstone-tech/how-to-capture-screenshots-for-failed-ui-tests-9927eea6e1e4
  903. def reportsDirectory = "$buildDir/reports/androidTests/connected"
  904. def screenshotsDirectory = "/sdcard/testfailures/screenshots/"
  905. def clearScreenshotsTask = task('clearScreenshots', type: Exec) {
  906. executable "${android.getAdbExe().toString()}"
  907. args 'shell', 'rm', '-r', screenshotsDirectory
  908. }
  909. def createScreenshotsDirectoryTask = task('createScreenshotsDirectory', type: Exec, group: 'reporting') {
  910. executable "${android.getAdbExe().toString()}"
  911. args 'shell', 'mkdir', '-p', screenshotsDirectory
  912. }
  913. def fetchScreenshotsTask = task('fetchScreenshots', type: Exec, group: 'reporting') {
  914. executable "${android.getAdbExe().toString()}"
  915. args 'pull', screenshotsDirectory + '.', reportsDirectory
  916. finalizedBy {
  917. clearScreenshotsTask
  918. }
  919. dependsOn {
  920. createScreenshotsDirectoryTask
  921. }
  922. doFirst {
  923. new File(reportsDirectory).mkdirs()
  924. }
  925. }
  926. tasks.whenTaskAdded { task ->
  927. if (task.name == 'connectedDebugAndroidTest') {
  928. task.finalizedBy {
  929. fetchScreenshotsTask
  930. }
  931. }
  932. }