build.gradle 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915
  1. import com.android.tools.profgen.ArtProfileKt
  2. import com.android.tools.profgen.ArtProfileSerializer
  3. import com.android.tools.profgen.DexFile
  4. plugins {
  5. id 'org.sonarqube'
  6. }
  7. apply plugin: 'com.android.application'
  8. apply plugin: 'kotlin-android'
  9. apply plugin: 'kotlin-kapt'
  10. // only apply the plugin if we are dealing with a AppGallery build
  11. if (getGradle().getStartParameter().getTaskRequests().toString().contains("Hms")) {
  12. println "enabling hms plugin"
  13. apply plugin: 'com.huawei.agconnect'
  14. }
  15. // version codes
  16. def app_version = "5.0.4"
  17. def beta_suffix = "" // with leading dash
  18. /**
  19. * Return the git hash, if git is installed.
  20. */
  21. def getGitHash = { ->
  22. def stdout = new ByteArrayOutputStream()
  23. def stderr = new ByteArrayOutputStream()
  24. try {
  25. exec {
  26. commandLine 'git', 'rev-parse', '--short', 'HEAD'
  27. standardOutput = stdout
  28. errorOutput = stderr
  29. ignoreExitValue true
  30. }
  31. } catch (ignored) { /* If git binary is not found, carry on */ }
  32. def hash = stdout.toString().trim()
  33. return (hash.isEmpty()) ? "?" : hash
  34. }
  35. /**
  36. * Look up the keystore with the specified name in a `keystore` directory
  37. * adjacent to this project directory. If it exists, return a signing config.
  38. * Otherwise, return null.
  39. */
  40. def findKeystore = { name ->
  41. def basePath = "${projectDir.getAbsolutePath()}/../../keystore"
  42. def storePath = "${basePath}/${name}.keystore"
  43. def storeFile = new File(storePath)
  44. if (storeFile.exists() && storeFile.isFile()) {
  45. def propertiesPath = "${basePath}/${name}.properties"
  46. def propertiesFile = new File(propertiesPath)
  47. if (propertiesFile.exists() && propertiesFile.isFile()) {
  48. Properties props = new Properties()
  49. propertiesFile.withInputStream { props.load(it) }
  50. return [
  51. storeFile: storePath,
  52. storePassword: props.storePassword,
  53. keyAlias: props.keyAlias,
  54. keyPassword: props.keyPassword,
  55. ]
  56. } else {
  57. return [
  58. storeFile: storePath,
  59. storePassword: null,
  60. keyAlias: null,
  61. keyPassword: null,
  62. ]
  63. }
  64. }
  65. }
  66. /**
  67. * Map with keystore paths (if found).
  68. */
  69. def keystores = [
  70. debug: findKeystore("debug"),
  71. release: findKeystore("threema"),
  72. hms_release: findKeystore("threema_hms"),
  73. onprem_release: findKeystore("onprem"),
  74. red_release: findKeystore("red"),
  75. ]
  76. android {
  77. // NOTE: When adjusting compileSdkVersion, buildToolsVersion or ndkVersion,
  78. // make sure to adjust them in `scripts/Dockerfile` and
  79. // `.gitlab-ci.yml` as well!
  80. compileSdkVersion 33
  81. buildToolsVersion '33.0.0'
  82. ndkVersion '25.1.8937393'
  83. defaultConfig {
  84. minSdkVersion 21
  85. //noinspection OldTargetApi
  86. targetSdkVersion 31
  87. vectorDrawables.useSupportLibrary = true
  88. applicationId "ch.threema.app"
  89. testApplicationId 'ch.threema.app.test'
  90. versionCode 790
  91. versionName "${app_version}${beta_suffix}"
  92. resValue "string", "app_name", "Threema"
  93. // package name used for sync adapter - needs to match mime types below
  94. resValue "string", "package_name", applicationId
  95. resValue "string", "contacts_mime_type", "vnd.android.cursor.item/vnd.ch.threema.app.profile"
  96. resValue "string", "call_mime_type", "vnd.android.cursor.item/vnd.ch.threema.app.call"
  97. buildConfigField "int", "MAX_GROUP_SIZE", "256"
  98. buildConfigField "String", "CHAT_SERVER_PREFIX", "\"g-\""
  99. buildConfigField "String", "CHAT_SERVER_IPV6_PREFIX", "\"ds.g-\""
  100. buildConfigField "String", "CHAT_SERVER_SUFFIX", "\".0.threema.ch\""
  101. buildConfigField "int[]", "CHAT_SERVER_PORTS", "{5222, 443}"
  102. buildConfigField "String", "MEDIA_PATH", "\"Threema\""
  103. buildConfigField "boolean", "CHAT_SERVER_GROUPS", "true"
  104. buildConfigField "boolean", "DISABLE_CERT_PINNING", "false"
  105. buildConfigField "boolean", "VIDEO_CALLS_ENABLED", "true"
  106. buildConfigField "boolean", "GROUP_CALLS_ENABLED", "true"
  107. 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 }"
  108. 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 }"
  109. buildConfigField "String", "GIT_HASH", "\"${getGitHash()}\""
  110. buildConfigField "String", "DIRECTORY_SERVER_URL", "\"https://apip.threema.ch/\""
  111. buildConfigField "String", "DIRECTORY_SERVER_IPV6_URL", "\"https://ds-apip.threema.ch/\""
  112. buildConfigField "String", "WORK_SERVER_URL", "null"
  113. buildConfigField "String", "WORK_SERVER_IPV6_URL", "null"
  114. buildConfigField "String", "BLOB_SERVER_DOWNLOAD_URL", "\"https://blobp-{blobIdPrefix}.threema.ch/{blobId}\""
  115. buildConfigField "String", "BLOB_SERVER_DOWNLOAD_IPV6_URL", "\"https://ds-blobp-{blobIdPrefix}.threema.ch/{blobId}\""
  116. buildConfigField "String", "BLOB_SERVER_DONE_URL", "\"https://blobp-{blobIdPrefix}.threema.ch/{blobId}/done\""
  117. buildConfigField "String", "BLOB_SERVER_DONE_IPV6_URL", "\"https://ds-blobp-{blobIdPrefix}.threema.ch/{blobId}/done\""
  118. buildConfigField "String", "BLOB_SERVER_UPLOAD_URL", "\"https://blobp-upload.threema.ch/upload\""
  119. buildConfigField "String", "BLOB_SERVER_UPLOAD_IPV6_URL", "\"https://ds-blobp-upload.threema.ch/upload\""
  120. buildConfigField "String", "AVATAR_FETCH_URL", "\"https://avatar.threema.ch/\""
  121. buildConfigField "String", "SAFE_SERVER_URL", "\"https://safe-%h.threema.ch/\""
  122. buildConfigField "String", "WEB_SERVER_URL", "\"https://web.threema.ch/\""
  123. buildConfigField "String", "ONPREM_ID_PREFIX", "\"O\""
  124. buildConfigField "String", "LOG_TAG", "\"3ma\""
  125. buildConfigField "String[]", "ONPREM_CONFIG_TRUSTED_PUBLIC_KEYS", "null"
  126. buildConfigField "boolean", "SEND_CONSUMED_DELIVERY_RECEIPTS", "false"
  127. buildConfigField "boolean", "FORWARD_SECURITY", "true"
  128. // config fields for action URLs / deep links
  129. buildConfigField "String", "uriScheme", "\"threema\""
  130. buildConfigField "String", "actionUrl", "\"go.threema.ch\""
  131. buildConfigField "String", "contactActionUrl", "\"threema.id\""
  132. buildConfigField "String", "groupLinkActionUrl", "\"threema.group\""
  133. // duplicated for manifest
  134. manifestPlaceholders = [
  135. uriScheme: "threema",
  136. contactActionUrl: "threema.id",
  137. groupLinkActionUrl: "threema.group",
  138. actionUrl: "go.threema.ch",
  139. callMimeType: "vnd.android.cursor.item/vnd.ch.threema.app.call",
  140. ]
  141. ndk {
  142. abiFilters "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
  143. }
  144. testInstrumentationRunner 'ch.threema.app.ThreemaTestRunner'
  145. testInstrumentationRunnerArgument 'notAnnotation', 'ch.threema.app.TestFastlaneOnly,ch.threema.app.DangerousTest'
  146. testInstrumentationRunnerArgument 'disableAnalytics', 'true' // https://developer.android.com/training/testing/espresso/setup#analytics
  147. }
  148. splits {
  149. abi {
  150. enable true
  151. reset()
  152. include 'armeabi-v7a', 'x86', "arm64-v8a", "x86_64"
  153. exclude 'armeabi', 'mips', 'mips64'
  154. universalApk true
  155. }
  156. }
  157. // Assign different version code for each output
  158. project.ext.versionCodes = ['armeabi': 1, 'armeabi-v7a': 2, 'arm64-v8a': 3, 'mips': 5, 'mips64': 6, 'x86': 8, 'x86_64': 9]
  159. android.applicationVariants.all { variant ->
  160. variant.outputs.each { output ->
  161. output.versionCodeOverride =
  162. project.ext.versionCodes.get(output.getFilter(com.android.build.OutputFile.ABI), 0) * 1000000 + android.defaultConfig.versionCode
  163. }
  164. }
  165. namespace 'ch.threema.app'
  166. flavorDimensions "default"
  167. productFlavors {
  168. none { }
  169. store_google { }
  170. store_threema {
  171. resValue "string", "shop_download_filename", "Threema-update.apk"
  172. }
  173. store_google_work {
  174. versionName "${app_version}k${beta_suffix}"
  175. applicationId "ch.threema.app.work"
  176. testApplicationId 'ch.threema.app.work.test'
  177. resValue "string", "app_name", "Threema Work"
  178. resValue "string", "package_name", applicationId
  179. resValue "string", "contacts_mime_type", "vnd.android.cursor.item/vnd.ch.threema.app.work.profile"
  180. resValue "string", "call_mime_type", "vnd.android.cursor.item/vnd.ch.threema.app.work.call"
  181. buildConfigField "String", "CHAT_SERVER_PREFIX", "\"w-\""
  182. buildConfigField "String", "CHAT_SERVER_IPV6_PREFIX", "\"ds.w-\""
  183. buildConfigField "String", "MEDIA_PATH", "\"ThreemaWork\""
  184. buildConfigField "String", "WORK_SERVER_URL", "\"https://apip-work.threema.ch/\""
  185. buildConfigField "String", "WORK_SERVER_IPV6_URL", "\"https://ds-apip-work.threema.ch/\""
  186. buildConfigField "String", "LOG_TAG", "\"3mawrk\""
  187. // config fields for action URLs / deep links
  188. buildConfigField "String", "uriScheme", "\"threemawork\""
  189. buildConfigField "String", "actionUrl", "\"work.threema.ch\""
  190. manifestPlaceholders = [
  191. uriScheme: "threemawork",
  192. actionUrl: "work.threema.ch",
  193. callMimeType: "vnd.android.cursor.item/vnd.ch.threema.app.work.call",
  194. ]
  195. }
  196. sandbox {
  197. applicationId "ch.threema.app.sandbox"
  198. testApplicationId 'ch.threema.app.sandbox.test'
  199. resValue "string", "app_name", "Threema Sandbox"
  200. resValue "string", "package_name", applicationId
  201. resValue "string", "contacts_mime_type", "vnd.android.cursor.item/vnd.ch.threema.app.sandbox.profile"
  202. resValue "string", "call_mime_type", "vnd.android.cursor.item/vnd.ch.threema.app.sandbox.call"
  203. buildConfigField "String", "MEDIA_PATH", "\"ThreemaSandbox\""
  204. buildConfigField "String", "CHAT_SERVER_SUFFIX", "\".0.test.threema.ch\""
  205. 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 }"
  206. 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 }"
  207. buildConfigField "String", "DIRECTORY_SERVER_URL", "\"https://apip.test.threema.ch/\""
  208. buildConfigField "String", "DIRECTORY_SERVER_IPV6_URL", "\"https://ds-apip.test.threema.ch/\""
  209. buildConfigField "String", "AVATAR_FETCH_URL", "\"https://avatar.test.threema.ch/\""
  210. }
  211. sandbox_work {
  212. versionName "${app_version}k${beta_suffix}"
  213. applicationId "ch.threema.app.sandbox.work"
  214. testApplicationId 'ch.threema.app.sandbox.work.test'
  215. resValue "string", "app_name", "Threema Sandbox Work"
  216. resValue "string", "package_name", applicationId
  217. resValue "string", "contacts_mime_type", "vnd.android.cursor.item/vnd.ch.threema.app.sandbox.work.profile"
  218. resValue "string", "call_mime_type", "vnd.android.cursor.item/vnd.ch.threema.app.sandbox.work.call"
  219. buildConfigField "String", "CHAT_SERVER_PREFIX", "\"w-\""
  220. buildConfigField "String", "CHAT_SERVER_IPV6_PREFIX", "\"ds.w-\""
  221. buildConfigField "String", "CHAT_SERVER_SUFFIX", "\".0.test.threema.ch\""
  222. buildConfigField "String", "MEDIA_PATH", "\"ThreemaWorkSandbox\""
  223. 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 }"
  224. 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 }"
  225. buildConfigField "String", "DIRECTORY_SERVER_URL", "\"https://apip.test.threema.ch/\""
  226. buildConfigField "String", "DIRECTORY_SERVER_IPV6_URL", "\"https://ds-apip.test.threema.ch/\""
  227. buildConfigField "String", "WORK_SERVER_URL", "\"https://apip-work.test.threema.ch/\""
  228. buildConfigField "String", "WORK_SERVER_IPV6_URL", "\"https://ds-apip-work.test.threema.ch/\""
  229. buildConfigField "String", "AVATAR_FETCH_URL", "\"https://avatar.test.threema.ch/\""
  230. buildConfigField "String", "LOG_TAG", "\"3mawrk\""
  231. // config fields for action URLs / deep links
  232. buildConfigField "String", "uriScheme", "\"threemawork\""
  233. buildConfigField "String", "actionUrl", "\"work.threema.ch\""
  234. manifestPlaceholders = [
  235. uriScheme : "threemawork",
  236. actionUrl : "work.threema.ch",
  237. ]
  238. }
  239. onprem {
  240. versionName "${app_version}o${beta_suffix}"
  241. applicationId "ch.threema.app.onprem"
  242. testApplicationId 'ch.threema.app.onprem.test'
  243. resValue "string", "app_name", "Threema OnPrem"
  244. resValue "string", "package_name", applicationId
  245. resValue "string", "contacts_mime_type", "vnd.android.cursor.item/vnd.ch.threema.app.onprem.profile"
  246. resValue "string", "call_mime_type", "vnd.android.cursor.item/vnd.ch.threema.app.onprem.call"
  247. buildConfigField "int", "MAX_GROUP_SIZE", "256"
  248. buildConfigField "String", "CHAT_SERVER_PREFIX", "\"\""
  249. buildConfigField "String", "CHAT_SERVER_IPV6_PREFIX", "\"\""
  250. buildConfigField "String", "CHAT_SERVER_SUFFIX", "null"
  251. buildConfigField "String", "MEDIA_PATH", "\"ThreemaOnPrem\""
  252. buildConfigField "boolean", "CHAT_SERVER_GROUPS", "false"
  253. buildConfigField "byte[]", "SERVER_PUBKEY", "null"
  254. buildConfigField "byte[]", "SERVER_PUBKEY_ALT", "null"
  255. buildConfigField "String", "DIRECTORY_SERVER_URL", "null"
  256. buildConfigField "String", "DIRECTORY_SERVER_IPV6_URL", "null"
  257. buildConfigField "String", "BLOB_SERVER_DOWNLOAD_URL", "null"
  258. buildConfigField "String", "BLOB_SERVER_DOWNLOAD_IPV6_URL", "null"
  259. buildConfigField "String", "BLOB_SERVER_DONE_URL", "null"
  260. buildConfigField "String", "BLOB_SERVER_DONE_IPV6_URL", "null"
  261. buildConfigField "String", "BLOB_SERVER_UPLOAD_URL", "null"
  262. buildConfigField "String", "BLOB_SERVER_UPLOAD_IPV6_URL", "null"
  263. buildConfigField "String[]", "ONPREM_CONFIG_TRUSTED_PUBLIC_KEYS", "new String[] {\"ek1qBp4DyRmLL9J5sCmsKSfwbsiGNB4veDAODjkwe/k=\", \"Hrk8aCjwKkXySubI7CZ3y9Sx+oToEHjNkGw98WSRneU=\", \"5pEn1T/5bhecNWrp9NgUQweRfgVtu/I8gRb3VxGP7k4=\"}"
  264. buildConfigField "String", "LOG_TAG", "\"3maop\""
  265. // config fields for action URLs / deep links
  266. buildConfigField "String", "uriScheme", "\"threemaonprem\""
  267. buildConfigField "String", "actionUrl", "\"onprem.threema.ch\""
  268. manifestPlaceholders = [
  269. uriScheme: "threemaonprem",
  270. actionUrl: "onprem.threema.ch",
  271. callMimeType: "vnd.android.cursor.item/vnd.ch.threema.app.onprem.call",
  272. ]
  273. }
  274. red { // Essentially like sandbox work, but with a different icon and accent color, used for internal testing
  275. versionName "${app_version}r${beta_suffix}"
  276. applicationId "ch.threema.app.red"
  277. testApplicationId 'ch.threema.app.red.test'
  278. resValue "string", "app_name", "Threema Red"
  279. resValue "string", "package_name", applicationId
  280. resValue "string", "contacts_mime_type", "vnd.android.cursor.item/vnd.ch.threema.app.red.profile"
  281. resValue "string", "call_mime_type", "vnd.android.cursor.item/vnd.ch.threema.app.red.call"
  282. buildConfigField "String", "CHAT_SERVER_PREFIX", "\"w-\""
  283. buildConfigField "String", "CHAT_SERVER_IPV6_PREFIX", "\"ds.w-\""
  284. buildConfigField "String", "CHAT_SERVER_SUFFIX", "\".0.test.threema.ch\""
  285. buildConfigField "String", "MEDIA_PATH", "\"ThreemaRed\""
  286. 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 }"
  287. 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 }"
  288. buildConfigField "String", "DIRECTORY_SERVER_URL", "\"https://apip.test.threema.ch/\""
  289. buildConfigField "String", "DIRECTORY_SERVER_IPV6_URL", "\"https://ds-apip.test.threema.ch/\""
  290. buildConfigField "String", "WORK_SERVER_URL", "\"https://apip-work.test.threema.ch/\""
  291. buildConfigField "String", "WORK_SERVER_IPV6_URL", "\"https://ds-apip-work.test.threema.ch/\""
  292. buildConfigField "String", "AVATAR_FETCH_URL", "\"https://avatar.test.threema.ch/\""
  293. buildConfigField "String", "LOG_TAG", "\"3mared\""
  294. buildConfigField "boolean", "SEND_CONSUMED_DELIVERY_RECEIPTS", "true"
  295. // config fields for action URLs / deep links
  296. buildConfigField "String", "uriScheme", "\"threemared\""
  297. buildConfigField "String", "actionUrl", "\"red.threema.ch\""
  298. manifestPlaceholders = [
  299. uriScheme: "threemared",
  300. actionUrl: "red.threema.ch",
  301. callMimeType: "vnd.android.cursor.item/vnd.ch.threema.app.red.call",
  302. ]
  303. }
  304. hms {
  305. applicationId "ch.threema.app.hms"
  306. }
  307. hms_work {
  308. versionName "${app_version}k${beta_suffix}"
  309. applicationId "ch.threema.app.work.hms"
  310. testApplicationId 'ch.threema.app.work.test.hms'
  311. resValue "string", "app_name", "Threema Work"
  312. resValue "string", "package_name", "ch.threema.app.work"
  313. resValue "string", "contacts_mime_type", "vnd.android.cursor.item/vnd.ch.threema.app.work.profile"
  314. resValue "string", "call_mime_type", "vnd.android.cursor.item/vnd.ch.threema.app.work.call"
  315. buildConfigField "String", "CHAT_SERVER_PREFIX", "\"w-\""
  316. buildConfigField "String", "CHAT_SERVER_IPV6_PREFIX", "\"ds.w-\""
  317. buildConfigField "String", "MEDIA_PATH", "\"ThreemaWork\""
  318. buildConfigField "String", "WORK_SERVER_URL", "\"https://apip-work.threema.ch/\""
  319. buildConfigField "String", "WORK_SERVER_IPV6_URL", "\"https://ds-apip-work.threema.ch/\""
  320. buildConfigField "String", "LOG_TAG", "\"3mawrk\""
  321. // config fields for action URLs / deep links
  322. buildConfigField "String", "uriScheme", "\"threemawork\""
  323. buildConfigField "String", "actionUrl", "\"work.threema.ch\""
  324. manifestPlaceholders = [
  325. uriScheme: "threemawork",
  326. actionUrl: "work.threema.ch",
  327. callMimeType: "vnd.android.cursor.item/vnd.ch.threema.app.work.call",
  328. ]
  329. }
  330. libre {
  331. versionName "${app_version}l${beta_suffix}"
  332. applicationId "ch.threema.app.libre"
  333. testApplicationId 'ch.threema.app.libre.test'
  334. resValue "string", "app_name", "Threema Libre"
  335. buildConfigField "String", "MEDIA_PATH", "\"ThreemaLibre\""
  336. }
  337. }
  338. signingConfigs {
  339. // Debug config
  340. if (keystores.debug != null) {
  341. debug {
  342. storeFile file(keystores.debug.storeFile)
  343. }
  344. } else {
  345. logger.warn("No debug keystore found. Falling back to locally generated keystore.")
  346. }
  347. // Release config
  348. if (keystores.release != null) {
  349. release {
  350. storeFile file(keystores.release.storeFile)
  351. storePassword keystores.release.storePassword
  352. keyAlias keystores.release.keyAlias
  353. keyPassword keystores.release.keyPassword
  354. }
  355. } else {
  356. logger.warn("No release keystore found. Falling back to locally generated keystore.")
  357. }
  358. // Release config
  359. if (keystores.hms_release != null) {
  360. hms_release {
  361. storeFile file(keystores.hms_release.storeFile)
  362. storePassword keystores.hms_release.storePassword
  363. keyAlias keystores.hms_release.keyAlias
  364. keyPassword keystores.hms_release.keyPassword
  365. }
  366. } else {
  367. logger.warn("No hms keystore found. Falling back to locally generated keystore.")
  368. }
  369. // Onprem release config
  370. if (keystores.onprem_release != null) {
  371. onprem_release {
  372. storeFile file(keystores.onprem_release.storeFile)
  373. storePassword keystores.onprem_release.storePassword
  374. keyAlias keystores.onprem_release.keyAlias
  375. keyPassword keystores.onprem_release.keyPassword
  376. }
  377. } else {
  378. logger.warn("No onprem keystore found. Falling back to locally generated keystore.")
  379. }
  380. // Red release config
  381. if (keystores.red_release != null) {
  382. red_release {
  383. storeFile file(keystores.red_release.storeFile)
  384. storePassword keystores.red_release.storePassword
  385. keyAlias keystores.red_release.keyAlias
  386. keyPassword keystores.red_release.keyPassword
  387. }
  388. } else {
  389. logger.warn("No red keystore found. Falling back to locally generated keystore.")
  390. }
  391. // Note: Libre release is signed with HSM, no config here
  392. }
  393. sourceSets {
  394. main {
  395. assets.srcDirs = ['assets']
  396. jniLibs.srcDirs = ['libs']
  397. }
  398. // Based on Google services
  399. none {
  400. java.srcDir 'src/google_services_based/java'
  401. }
  402. store_google {
  403. java.srcDir 'src/google_services_based/java'
  404. }
  405. store_google_work {
  406. java.srcDir 'src/google_services_based/java'
  407. }
  408. store_threema {
  409. java.srcDir 'src/google_services_based/java'
  410. }
  411. libre {
  412. assets.srcDirs = ['src/foss_based/assets']
  413. java.srcDir 'src/foss_based/java'
  414. }
  415. onprem {
  416. java.srcDir 'src/google_services_based/java'
  417. }
  418. sandbox {
  419. java.srcDir 'src/google_services_based/java'
  420. manifest.srcFile 'src/store_google/AndroidManifest.xml'
  421. }
  422. sandbox_work {
  423. java.srcDir 'src/google_services_based/java'
  424. res.srcDir 'src/store_google_work/res'
  425. manifest.srcFile 'src/store_google_work/AndroidManifest.xml'
  426. }
  427. red {
  428. java.srcDir 'src/google_services_based/java'
  429. res.srcDir 'src/red/res'
  430. }
  431. // Based on Huawei services
  432. hms {
  433. java.srcDir 'src/hms_services_based/java'
  434. }
  435. hms_work {
  436. java.srcDir 'src/hms_services_based/java'
  437. res.srcDir 'src/store_google_work/res'
  438. }
  439. // FOSS, no proprietary services
  440. libre {
  441. assets.srcDirs = ['src/foss_based/assets']
  442. java.srcDir 'src/foss_based/java'
  443. }
  444. }
  445. buildTypes {
  446. debug {
  447. debuggable true
  448. jniDebuggable false
  449. multiDexEnabled true
  450. multiDexKeepProguard file('multidex-keep.pro')
  451. testCoverageEnabled false
  452. if (keystores['debug'] != null) {
  453. signingConfig signingConfigs.debug
  454. }
  455. }
  456. release {
  457. debuggable false
  458. jniDebuggable false
  459. minifyEnabled true
  460. shrinkResources false // Caused inconsistencies between local and CI builds
  461. zipAlignEnabled true
  462. multiDexEnabled true
  463. multiDexKeepProguard file('multidex-keep.pro')
  464. proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-project.txt'
  465. if (keystores['release'] != null) {
  466. productFlavors.store_google.signingConfig signingConfigs.release
  467. productFlavors.store_google_work.signingConfig signingConfigs.release
  468. productFlavors.store_threema.signingConfig signingConfigs.release
  469. productFlavors.sandbox.signingConfig signingConfigs.release
  470. productFlavors.sandbox_work.signingConfig signingConfigs.release
  471. productFlavors.none.signingConfig signingConfigs.release
  472. }
  473. if (keystores['hms_release'] != null) {
  474. productFlavors.hms.signingConfig signingConfigs.hms_release
  475. productFlavors.hms_work.signingConfig signingConfigs.hms_release
  476. }
  477. if (keystores['onprem_release'] != null) {
  478. productFlavors.onprem.signingConfig signingConfigs.onprem_release
  479. }
  480. if (keystores['red_release'] != null) {
  481. productFlavors.red.signingConfig signingConfigs.red_release
  482. }
  483. // Note: Libre release is signed with HSM, no config here
  484. }
  485. }
  486. // Only build relevant buildType / flavor combinations
  487. variantFilter { variant ->
  488. def names = variant.flavors*.name
  489. if (
  490. variant.buildType.name == "release" && (
  491. names.contains("sandbox") || names.contains("sandbox_work")
  492. )
  493. ) {
  494. setIgnore(true)
  495. }
  496. }
  497. externalNativeBuild {
  498. ndkBuild {
  499. path 'jni/Android.mk'
  500. }
  501. }
  502. packagingOptions {
  503. jniLibs {
  504. // fix https://stackoverflow.com/questions/42739916/aarch64-linux-android-strip-file-missing
  505. keepDebugSymbols += ['*/mips/*.so', '*/mips64/*.so', '*/armeabi/*.so']
  506. }
  507. resources {
  508. excludes += ['META-INF/DEPENDENCIES.txt', 'META-INF/LICENSE.txt', 'META-INF/NOTICE.txt', 'META-INF/NOTICE', 'META-INF/LICENSE', 'META-INF/DEPENDENCIES', 'META-INF/notice.txt', 'META-INF/license.txt', 'META-INF/dependencies.txt', 'META-INF/LGPL2.1', '**/*.proto']
  509. }
  510. }
  511. testOptions {
  512. // Disable animations in instrumentation tests
  513. animationsDisabled true
  514. unitTests {
  515. all {
  516. // All the usual Gradle options.
  517. testLogging {
  518. events "passed", "skipped", "failed", "standardOut", "standardError"
  519. outputs.upToDateWhen { false }
  520. exceptionFormat = 'full'
  521. }
  522. }
  523. // By default, local unit tests throw an exception any time the code you are testing tries to access
  524. // Android platform APIs (unless you mock Android dependencies yourself or with a testing
  525. // framework like Mockito). However, you can enable the following property so that the test
  526. // returns either null or zero when accessing platform APIs, rather than throwing an exception.
  527. returnDefaultValues true
  528. }
  529. }
  530. compileOptions {
  531. sourceCompatibility JavaVersion.VERSION_11
  532. targetCompatibility JavaVersion.VERSION_11
  533. }
  534. kotlinOptions {
  535. jvmTarget = "11"
  536. }
  537. kotlin {
  538. jvmToolchain {
  539. languageVersion.set(JavaLanguageVersion.of(11))
  540. }
  541. }
  542. androidResources {
  543. noCompress 'png'
  544. }
  545. // Fix non-producible `baseline.profm` in release builds due to unstable ordering.
  546. // See https://issuetracker.google.com/issues/231837768
  547. project.afterEvaluate {
  548. applicationVariants.all { variant ->
  549. if (variant.name.endsWith("Release")) {
  550. tasks["compile${variant.name.capitalize()}ArtProfile"].doLast {
  551. outputs.files.each { file ->
  552. if (file.toString().endsWith(".profm")) {
  553. println("Sorting ${file} ...")
  554. def version = ArtProfileSerializer.valueOf("METADATA_0_0_2")
  555. def profile = ArtProfileKt.ArtProfile(file)
  556. def keys = new ArrayList(profile.profileData.keySet())
  557. def sortedData = new LinkedHashMap()
  558. Collections.sort keys, new DexFile.Companion()
  559. keys.each { key -> sortedData[key] = profile.profileData[key] }
  560. new FileOutputStream(file).with {
  561. write(version.magicBytes$profgen)
  562. write(version.versionBytes$profgen)
  563. version.write$profgen(it, sortedData, "")
  564. }
  565. }
  566. }
  567. }
  568. }
  569. }
  570. }
  571. lint {
  572. // if true, stop the gradle build if errors are found
  573. abortOnError true
  574. // if true, check all issues, including those that are off by default
  575. checkAllWarnings true
  576. // check dependencies
  577. checkDependencies true
  578. // set to true to have all release builds run lint on issues with severity=fatal
  579. // and abort the build (controlled by abortOnError above) if fatal issues are found
  580. checkReleaseBuilds true
  581. // turn off checking the given issue id's
  582. disable 'TypographyFractions', 'TypographyQuotes', 'RtlHardcoded', 'RtlCompat', 'RtlEnabled'
  583. // Set the severity of the given issues to error
  584. error 'Wakelock', 'TextViewEdits', 'ResourceAsColor'
  585. // Set the severity of the given issues to fatal (which means they will be
  586. // checked during release builds (even if the lint target is not included)
  587. fatal 'NewApi', 'InlinedApi'
  588. // Set the severity of the given issues to ignore (same as disabling the check)
  589. ignore 'TypographyQuotes'
  590. ignoreWarnings false
  591. // if true, don't include source code lines in the error output
  592. noLines false
  593. // if true, show all locations for an error, do not truncate lists, etc.
  594. showAll true
  595. // Set the severity of the given issues to warning
  596. warning 'MissingTranslation'
  597. // if true, treat all warnings as errors
  598. warningsAsErrors false
  599. // file to write report to (if not specified, defaults to lint-results.xml)
  600. xmlOutput file('lint-report.xml')
  601. // if true, generate an XML report for use by for example Jenkins
  602. xmlReport true
  603. }
  604. }
  605. dependencies {
  606. configurations.all {
  607. // Prefer modules that are part of this build (multi-project or composite build)
  608. // over external modules
  609. resolutionStrategy.preferProjectModules()
  610. // Alternatively, we can fail eagerly on version conflict to see the conflicts
  611. //resolutionStrategy.failOnVersionConflict()
  612. }
  613. implementation project(':domain')
  614. implementation 'net.zetetic:android-database-sqlcipher:4.5.2'
  615. implementation 'com.davemorrissey.labs:subsampling-scale-image-view-androidx:3.10.0'
  616. implementation 'net.sf.opencsv:opencsv:2.3'
  617. implementation 'net.lingala.zip4j:zip4j:2.11.4'
  618. implementation 'com.getkeepsafe.taptargetview:taptargetview:1.13.3'
  619. // commons-io >2.6 requires android 8
  620. implementation 'commons-io:commons-io:2.6'
  621. implementation 'org.apache.commons:commons-text:1.9'
  622. implementation "org.slf4j:slf4j-api:$slf4j_version"
  623. implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.25'
  624. implementation 'com.github.CanHub:Android-Image-Cropper:4.3.0'
  625. implementation 'com.datatheorem.android.trustkit:trustkit:1.1.5'
  626. implementation 'me.zhanghai.android.fastscroll:library:1.1.8'
  627. implementation 'com.googlecode.ez-vcard:ez-vcard:0.11.3'
  628. // AndroidX / Jetpack support libraries
  629. implementation "androidx.preference:preference-ktx:1.2.0"
  630. implementation 'androidx.recyclerview:recyclerview:1.2.1'
  631. implementation 'androidx.palette:palette-ktx:1.0.0'
  632. implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
  633. implementation 'androidx.appcompat:appcompat:1.5.1'
  634. implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
  635. implementation 'androidx.biometric:biometric:1.1.0'
  636. implementation 'androidx.work:work-runtime-ktx:2.7.1'
  637. implementation 'androidx.fragment:fragment-ktx:1.5.4'
  638. implementation 'androidx.activity:activity-ktx:1.6.1'
  639. implementation 'androidx.sqlite:sqlite:2.1.0'
  640. implementation "androidx.concurrent:concurrent-futures:1.1.0"
  641. implementation "androidx.camera:camera-camera2:1.1.0"
  642. implementation "androidx.camera:camera-lifecycle:1.1.0"
  643. implementation "androidx.camera:camera-view:1.1.0"
  644. implementation 'androidx.multidex:multidex:2.0.1'
  645. implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1"
  646. implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.5.1"
  647. implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.5.1"
  648. implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:2.5.1"
  649. implementation "androidx.lifecycle:lifecycle-service:2.5.1"
  650. implementation "androidx.lifecycle:lifecycle-process:2.5.1"
  651. implementation "androidx.lifecycle:lifecycle-common-java8:2.5.1"
  652. implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
  653. implementation "androidx.paging:paging-runtime:3.1.1"
  654. implementation "androidx.sharetarget:sharetarget:1.2.0"
  655. implementation 'androidx.room:room-runtime:2.4.3'
  656. kapt 'androidx.room:room-compiler:2.4.3'
  657. implementation 'com.google.android.material:material:1.7.0'
  658. implementation 'com.google.android.exoplayer:exoplayer-core:2.18.2'
  659. implementation 'com.google.android.exoplayer:exoplayer-ui:2.18.2'
  660. implementation 'com.google.zxing:core:3.3.3' // zxing 3.4 crashes on API < 24
  661. implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.57' // make sure to update this in domain's build.gradle as well
  662. // webclient dependencies
  663. implementation 'org.msgpack:msgpack-core:0.8.24!!'
  664. implementation 'com.fasterxml.jackson.core:jackson-core:2.12.5!!'
  665. implementation 'com.neovisionaries:nv-websocket-client:2.9'
  666. // Backport of Streams and CompletableFuture. Remove once API level 24 is supported.
  667. implementation 'net.sourceforge.streamsupport:streamsupport-cfuture:1.7.4'
  668. implementation('org.saltyrtc:saltyrtc-client:0.14.2') {
  669. exclude group: 'org.json'
  670. }
  671. implementation 'org.saltyrtc:chunked-dc:1.0.1'
  672. implementation 'ch.threema:webrtc-android:108.0.0'
  673. implementation('org.saltyrtc:saltyrtc-task-webrtc:0.18.1') {
  674. exclude module: 'saltyrtc-client'
  675. }
  676. // Glide components
  677. implementation 'com.github.bumptech.glide:glide:4.14.2'
  678. kapt 'com.github.bumptech.glide:compiler:4.14.2'
  679. // kotlin
  680. implementation 'androidx.core:core-ktx:1.9.0'
  681. implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
  682. implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
  683. // use leak canary in debug builds
  684. // debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.9.1'
  685. // test dependencies
  686. testImplementation "junit:junit:$junit_version"
  687. testImplementation(testFixtures(project(":domain")))
  688. // use powermock instead of mockito. it support mocking static classes.
  689. def mockitoVersion = '2.0.9'
  690. testImplementation "org.powermock:powermock-api-mockito2:${mockitoVersion}"
  691. testImplementation "org.powermock:powermock-module-junit4-rule-agent:${mockitoVersion}"
  692. testImplementation "org.powermock:powermock-module-junit4-rule:${mockitoVersion}"
  693. testImplementation "org.powermock:powermock-module-junit4:${mockitoVersion}"
  694. // add JSON support to tests without mocking
  695. testImplementation 'org.json:json:20220924'
  696. testImplementation 'com.tngtech.archunit:archunit-junit4:0.18.0'
  697. androidTestImplementation(testFixtures(project(":domain")))
  698. androidTestImplementation 'androidx.test:rules:1.4.0'
  699. androidTestImplementation 'tools.fastlane:screengrab:2.1.1', {
  700. exclude group: 'androidx.annotation', module: 'annotation'
  701. }
  702. androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0', {
  703. exclude group: 'androidx.annotation', module: 'annotation'
  704. }
  705. androidTestImplementation 'androidx.test:runner:1.4.0', {
  706. exclude group: 'androidx.annotation', module: 'annotation'
  707. }
  708. androidTestImplementation 'androidx.test.ext:junit:1.1.3'
  709. androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.4.0', {
  710. exclude group: 'androidx.annotation', module: 'annotation'
  711. exclude group: 'androidx.appcompat', module: 'appcompat'
  712. exclude group: 'androidx.legacy', module: 'legacy-support-v4'
  713. exclude group: 'com.google.android.material', module: 'material'
  714. exclude group: 'androidx.recyclerview', module: 'recyclerview'
  715. exclude(group: 'org.checkerframework', module: 'checker')
  716. }
  717. androidTestImplementation 'androidx.test.espresso:espresso-intents:3.4.0', {
  718. exclude group: 'androidx.annotation', module: 'annotation'
  719. }
  720. androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0'
  721. // Google Play Services and related libraries
  722. def googleDependencies = [
  723. // Play services
  724. 'com.google.android.gms:play-services-base:16.1.0': [],
  725. // Firebase push
  726. //
  727. // Note: Do not upgrade to a higher version of firebase-messaging,
  728. // as we do not want the Firebase Installations API in our app
  729. 'com.google.firebase:firebase-messaging:20.1.0': [
  730. [group: 'com.google.firebase', module: 'firebase-core'],
  731. [group: 'com.google.firebase', module: 'firebase-analytics'],
  732. [group: 'com.google.firebase', module: 'firebase-measurement-connector'],
  733. ],
  734. ]
  735. googleDependencies.each {
  736. def dependency = it.key
  737. def excludes = it.value
  738. noneImplementation(dependency) { excludes.each { exclude it } }
  739. store_googleImplementation(dependency) { excludes.each { exclude it } }
  740. store_google_workImplementation(dependency) { excludes.each { exclude it } }
  741. store_threemaImplementation(dependency) { excludes.each { exclude it } }
  742. onpremImplementation(dependency) { excludes.each { exclude it } }
  743. sandboxImplementation(dependency) { excludes.each { exclude it } }
  744. sandbox_workImplementation(dependency) { excludes.each { exclude it } }
  745. redImplementation(dependency) { excludes.each { exclude it } }
  746. }
  747. // Google Assistant Voice Action verification library
  748. noneImplementation(name: 'libgsaverification-client', ext: 'aar')
  749. store_googleImplementation(name: 'libgsaverification-client', ext: 'aar')
  750. store_google_workImplementation(name: 'libgsaverification-client', ext: 'aar')
  751. onpremImplementation(name: 'libgsaverification-client', ext: 'aar')
  752. store_threemaImplementation(name: 'libgsaverification-client', ext: 'aar')
  753. sandboxImplementation(name: 'libgsaverification-client', ext: 'aar')
  754. sandbox_workImplementation(name: 'libgsaverification-client', ext: 'aar')
  755. redImplementation(name: 'libgsaverification-client', ext: 'aar')
  756. // Maplibre (may have transitive dependencies on Google location services)
  757. def maplibreDependency = 'org.maplibre.gl:android-sdk:9.6.0'
  758. noneImplementation maplibreDependency
  759. store_googleImplementation maplibreDependency
  760. store_google_workImplementation maplibreDependency
  761. store_threemaImplementation maplibreDependency
  762. libreImplementation maplibreDependency, { exclude group: 'com.google.android.gms' }
  763. onpremImplementation maplibreDependency
  764. sandboxImplementation maplibreDependency
  765. sandbox_workImplementation maplibreDependency
  766. redImplementation maplibreDependency
  767. hmsImplementation maplibreDependency
  768. hms_workImplementation maplibreDependency
  769. // Huawei related libraries (only for hms* build variants)
  770. def huaweiDependencies = [
  771. // HMS push
  772. 'com.huawei.hms:push:6.3.0.304': [
  773. // Exclude agconnect dependency, we'll replace it with the vendored version below
  774. [group: 'com.huawei.agconnect'],
  775. ],
  776. ]
  777. huaweiDependencies.each {
  778. def dependency = it.key
  779. def excludes = it.value
  780. hmsImplementation(dependency) { excludes.each { exclude it } }
  781. hms_workImplementation(dependency) { excludes.each { exclude it } }
  782. }
  783. hmsImplementation(name: 'agconnect-core-1.5.0.300', ext: 'aar')
  784. hms_workImplementation(name: 'agconnect-core-1.5.0.300', ext: 'aar')
  785. }
  786. sonarqube {
  787. properties {
  788. property "sonar.sources", "src/main/, ../scripts/, ../scripts-internal/"
  789. property "sonar.exclusions", "src/main/java/ch/threema/localcrypto/**, src/test/java/ch/threema/localcrypto/**"
  790. property "sonar.tests", "src/test/"
  791. property "sonar.sourceEncoding", "UTF-8"
  792. property "sonar.verbose", "true"
  793. property 'sonar.projectKey', 'android-client'
  794. property 'sonar.projectName', 'Threema for Android'
  795. }
  796. }
  797. // Set up Gradle tasks to fetch screenshots on UI test failures
  798. // See https://medium.com/stepstone-tech/how-to-capture-screenshots-for-failed-ui-tests-9927eea6e1e4
  799. def reportsDirectory = "$buildDir/reports/androidTests/connected"
  800. def screenshotsDirectory = "/sdcard/testfailures/screenshots/"
  801. def clearScreenshotsTask = task('clearScreenshots', type: Exec) {
  802. executable "${android.getAdbExe().toString()}"
  803. args 'shell', 'rm', '-r', screenshotsDirectory
  804. }
  805. def createScreenshotsDirectoryTask = task('createScreenshotsDirectory', type: Exec, group: 'reporting') {
  806. executable "${android.getAdbExe().toString()}"
  807. args 'shell', 'mkdir', '-p', screenshotsDirectory
  808. }
  809. def fetchScreenshotsTask = task('fetchScreenshots', type: Exec, group: 'reporting') {
  810. executable "${android.getAdbExe().toString()}"
  811. args 'pull', screenshotsDirectory + '.', reportsDirectory
  812. finalizedBy {
  813. clearScreenshotsTask
  814. }
  815. dependsOn {
  816. createScreenshotsDirectoryTask
  817. }
  818. doFirst {
  819. new File(reportsDirectory).mkdirs()
  820. }
  821. }
  822. tasks.whenTaskAdded { task ->
  823. if (task.name == 'connectedDebugAndroidTest') {
  824. task.finalizedBy {
  825. fetchScreenshotsTask
  826. }
  827. }
  828. }