build.gradle 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  1. plugins {
  2. id "org.sonarqube" version "3.0"
  3. }
  4. apply plugin: 'com.android.application'
  5. /**
  6. * Return the git hash, if git is installed.
  7. */
  8. def getGitHash = { ->
  9. def stdout = new ByteArrayOutputStream()
  10. def stderr = new ByteArrayOutputStream()
  11. try {
  12. exec {
  13. commandLine 'git', 'rev-parse', '--short', 'HEAD'
  14. standardOutput = stdout
  15. errorOutput = stderr
  16. ignoreExitValue true
  17. }
  18. } catch (ignored) { /* If git binary is not found, carry on */ }
  19. def hash = stdout.toString().trim()
  20. return (hash.isEmpty()) ? "?" : hash
  21. }
  22. /**
  23. * Look up the keystore with the specified name in a `keystore` directory
  24. * adjacent to this project directory. If it exists, return a signing config.
  25. * Otherwise, return null.
  26. */
  27. def findKeystore = { name ->
  28. def basePath = "${projectDir.getAbsolutePath()}/../../keystore"
  29. def storePath = "${basePath}/${name}.keystore"
  30. def storeFile = new File(storePath)
  31. if (storeFile.exists() && storeFile.isFile()) {
  32. def propertiesPath = "${basePath}/${name}.properties"
  33. def propertiesFile = new File(propertiesPath)
  34. if (propertiesFile.exists() && propertiesFile.isFile()) {
  35. Properties props = new Properties()
  36. propertiesFile.withInputStream { props.load(it) }
  37. return [
  38. storeFile: storePath,
  39. storePassword: props.storePassword,
  40. keyAlias: props.keyAlias,
  41. keyPassword: props.keyPassword,
  42. ]
  43. } else {
  44. return [
  45. storeFile: storePath,
  46. storePassword: null,
  47. keyAlias: null,
  48. keyPassword: null,
  49. ]
  50. }
  51. }
  52. }
  53. /**
  54. * Map with keystore paths (if found).
  55. */
  56. def keystores = [
  57. debug: findKeystore("debug"),
  58. release: findKeystore("threema"),
  59. ]
  60. android {
  61. // NOTE: When adjusting compileSdkVersion or buildToolsVersion,
  62. // make sure to adjust them in `scripts/Dockerfile` as well!
  63. compileSdkVersion 29
  64. buildToolsVersion '29.0.3'
  65. defaultConfig {
  66. minSdkVersion 19
  67. //noinspection OldTargetApi
  68. targetSdkVersion 29
  69. vectorDrawables.useSupportLibrary = true
  70. applicationId "ch.threema.app"
  71. testApplicationId 'ch.threema.app.test'
  72. versionCode 663
  73. versionName "4.5"
  74. resValue "string", "version_name_suffix", ""
  75. resValue "string", "app_name", "Threema"
  76. resValue "string", "uri_scheme", "threema"
  77. resValue "string", "action_url", "go.threema.ch"
  78. resValue "string", "contact_action_url", "threema.id"
  79. // package name used for sync adapter
  80. resValue "string", "package_name", applicationId
  81. resValue "string", "contacts_mime_type", "vnd.android.cursor.item/vnd.ch.threema.app.profile"
  82. resValue "string", "call_mime_type", "vnd.android.cursor.item/vnd.ch.threema.app.call"
  83. resValue "integer", "max_group_size", "256"
  84. resValue "string", "shop_download_filename", "Threema-update.apk"
  85. buildConfigField "String", "CHAT_SERVER_PREFIX", "\"g-\""
  86. buildConfigField "String", "CHAT_SERVER_IPV6_PREFIX", "\"ds.\""
  87. buildConfigField "String", "CHAT_SERVER_SUFFIX", "\".0.threema.ch\""
  88. buildConfigField "String", "MEDIA_PATH", "\"Threema\""
  89. buildConfigField "boolean", "CHAT_SERVER_GROUPS", "true"
  90. buildConfigField "boolean", "DISABLE_CERT_PINNING", "false"
  91. buildConfigField "boolean", "VIDEO_CALLS_ENABLED", "true"
  92. 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 }"
  93. 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 }"
  94. buildConfigField "String", "GIT_HASH", "\"${getGitHash()}\""
  95. manifestPlaceholders = [
  96. actionUrl: "go.threema.ch",
  97. uriScheme: "threema",
  98. contactActionUrl: "threema.id"
  99. ]
  100. ndk {
  101. abiFilters "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
  102. }
  103. testInstrumentationRunner 'ch.threema.app.ThreemaTestRunner'
  104. testInstrumentationRunnerArgument 'notAnnotation', 'ch.threema.app.TestFastlaneOnly,ch.threema.app.DangerousTest'
  105. testInstrumentationRunnerArgument 'disableAnalytics', 'true' // https://developer.android.com/training/testing/espresso/setup#analytics
  106. }
  107. splits {
  108. abi {
  109. enable true
  110. reset()
  111. include 'armeabi-v7a', 'x86', "arm64-v8a", "x86_64"
  112. exclude 'armeabi', 'mips', 'mips64'
  113. universalApk true
  114. }
  115. }
  116. // Assign different version code for each output
  117. project.ext.versionCodes = ['armeabi': 1, 'armeabi-v7a': 2, 'arm64-v8a': 3, 'mips': 5, 'mips64': 6, 'x86': 8, 'x86_64': 9]
  118. android.applicationVariants.all { variant ->
  119. variant.outputs.each { output ->
  120. output.versionCodeOverride =
  121. project.ext.versionCodes.get(output.getFilter(com.android.build.OutputFile.ABI), 0) * 1000000 + android.defaultConfig.versionCode
  122. }
  123. }
  124. flavorDimensions "default"
  125. productFlavors {
  126. none { }
  127. store_google {
  128. resValue "string", "shop_download_filename", ""
  129. }
  130. store_threema { }
  131. store_google_work {
  132. versionName "4.5k"
  133. applicationId "ch.threema.app.work"
  134. testApplicationId 'ch.threema.app.work.test'
  135. resValue "string", "package_name", applicationId
  136. resValue "string", "app_name", "Threema Work"
  137. resValue "string", "uri_scheme", "threemawork"
  138. resValue "string", "action_url", "work.threema.ch"
  139. resValue "string", "contact_action_url", "threema.id"
  140. resValue "string", "contacts_mime_type", "vnd.android.cursor.item/vnd.ch.threema.app.work.profile"
  141. resValue "string", "call_mime_type", "vnd.android.cursor.item/vnd.ch.threema.app.work.call"
  142. resValue "integer", "max_group_size", "256"
  143. resValue "string", "shop_download_filename", ""
  144. buildConfigField "String", "CHAT_SERVER_PREFIX", "\"w-\""
  145. buildConfigField "String", "CHAT_SERVER_IPV6_PREFIX", "\"ds.\""
  146. buildConfigField "String", "CHAT_SERVER_SUFFIX", "\".0.threema.ch\""
  147. buildConfigField "String", "MEDIA_PATH", "\"ThreemaWork\""
  148. buildConfigField "boolean", "CHAT_SERVER_GROUPS", "true"
  149. manifestPlaceholders = [
  150. actionUrl: "work.threema.ch",
  151. uriScheme: "threemawork",
  152. contactActionUrl: "threema.id"
  153. ]
  154. }
  155. sandbox {
  156. applicationId "ch.threema.app.sandbox"
  157. testApplicationId 'ch.threema.app.sandbox.test'
  158. resValue "string", "package_name", applicationId
  159. resValue "string", "app_name", "Threema Sandbox"
  160. buildConfigField "String", "MEDIA_PATH", "\"ThreemaSandbox\""
  161. buildConfigField "String", "CHAT_SERVER_SUFFIX", "\".0.test.threema.ch\""
  162. 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 }"
  163. 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 }"
  164. }
  165. sandbox_work {
  166. versionName "4.5k"
  167. applicationId "ch.threema.app.sandbox.work"
  168. testApplicationId 'ch.threema.app.sandbox.work.test'
  169. resValue "string", "package_name", applicationId
  170. resValue "string", "app_name", "Threema Sandbox Work"
  171. resValue "string", "uri_scheme", "threemawork"
  172. resValue "string", "action_url", "work.threema.ch"
  173. resValue "string", "contact_action_url", "threema.id"
  174. resValue "string", "contacts_mime_type", "vnd.android.cursor.item/vnd.ch.threema.app.work.profile"
  175. resValue "string", "call_mime_type", "vnd.android.cursor.item/vnd.ch.threema.app.work.call"
  176. resValue "integer", "max_group_size", "256"
  177. resValue "string", "shop_download_filename", ""
  178. buildConfigField "String", "CHAT_SERVER_PREFIX", "\"w-\""
  179. buildConfigField "String", "CHAT_SERVER_IPV6_PREFIX", "\"ds.\""
  180. buildConfigField "String", "MEDIA_PATH", "\"ThreemaWorkSandbox\""
  181. buildConfigField "boolean", "CHAT_SERVER_GROUPS", "true"
  182. buildConfigField "String", "CHAT_SERVER_SUFFIX", "\".0.test.threema.ch\""
  183. 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 }"
  184. 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 }"
  185. manifestPlaceholders = [
  186. actionUrl: "work.threema.ch",
  187. uriScheme: "threemawork",
  188. contactActionUrl: "threema.id"
  189. ]
  190. }
  191. red { // Essentially like sandbox work, but with a different icon and accent color, used for internal testing
  192. versionName "4.5r"
  193. applicationId "ch.threema.app.red"
  194. testApplicationId 'ch.threema.app.red.test'
  195. resValue "string", "package_name", applicationId
  196. resValue "string", "app_name", "Threema Red"
  197. resValue "string", "uri_scheme", "threemawork"
  198. resValue "string", "action_url", "work.threema.ch"
  199. resValue "string", "contact_action_url", "threema.id"
  200. resValue "string", "contacts_mime_type", "vnd.android.cursor.item/vnd.ch.threema.app.redwork.profile"
  201. resValue "string", "call_mime_type", "vnd.android.cursor.item/vnd.ch.threema.app.redwork.call"
  202. resValue "integer", "max_group_size", "256"
  203. resValue "string", "shop_download_filename", ""
  204. buildConfigField "String", "CHAT_SERVER_PREFIX", "\"w-\""
  205. buildConfigField "String", "CHAT_SERVER_IPV6_PREFIX", "\"ds.\""
  206. buildConfigField "String", "MEDIA_PATH", "\"ThreemaRed\""
  207. buildConfigField "boolean", "CHAT_SERVER_GROUPS", "true"
  208. buildConfigField "String", "CHAT_SERVER_SUFFIX", "\".0.test.threema.ch\""
  209. 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 }"
  210. 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 }"
  211. manifestPlaceholders = [
  212. actionUrl: "work.threema.ch",
  213. uriScheme: "threemawork",
  214. contactActionUrl: "threema.id"
  215. ]
  216. }
  217. }
  218. signingConfigs {
  219. // Debug config
  220. if (keystores.debug != null) {
  221. debug {
  222. storeFile file(keystores.debug.storeFile)
  223. }
  224. } else {
  225. logger.warn("No debug keystore found. Falling back to locally generated keystore.")
  226. }
  227. // Release config
  228. if (keystores.release != null) {
  229. release {
  230. storeFile file(keystores.release.storeFile)
  231. storePassword keystores.release.storePassword
  232. keyAlias keystores.release.keyAlias
  233. keyPassword keystores.release.keyPassword
  234. }
  235. } else {
  236. logger.warn("No release keystore found. Falling back to locally generated keystore.")
  237. }
  238. }
  239. sourceSets {
  240. main {
  241. assets.srcDirs = ['assets']
  242. jniLibs.srcDirs = ['libs']
  243. }
  244. sandbox {
  245. java {
  246. srcDir 'src/none'
  247. }
  248. }
  249. sandbox_work {
  250. setRoot 'src/store_google_work'
  251. }
  252. red {
  253. setRoot 'src/red'
  254. }
  255. }
  256. buildTypes {
  257. debug {
  258. debuggable true
  259. jniDebuggable false
  260. multiDexEnabled true
  261. multiDexKeepProguard file('multidex-keep.pro')
  262. if (keystores['debug'] != null) {
  263. signingConfig signingConfigs.debug
  264. }
  265. }
  266. release {
  267. debuggable false
  268. jniDebuggable false
  269. minifyEnabled true
  270. shrinkResources false // Caused inconsistencies between local and CI builds
  271. zipAlignEnabled true
  272. multiDexEnabled true
  273. multiDexKeepProguard file('multidex-keep.pro')
  274. proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-project.txt'
  275. if (keystores['release'] != null) {
  276. signingConfig signingConfigs.release
  277. }
  278. }
  279. }
  280. externalNativeBuild {
  281. ndkBuild {
  282. path 'jni/Android.mk'
  283. }
  284. }
  285. lintOptions {
  286. // set to true to have all release builds run lint on issues with severity=fatal
  287. // and abort the build (controlled by abortOnError above) if fatal issues are found
  288. checkReleaseBuilds true
  289. // set to true to turn off analysis progress reporting by lint
  290. // quiet true
  291. // if true, stop the gradle build if errors are found
  292. abortOnError true
  293. // if true, only report errors
  294. ignoreWarnings false
  295. // if true, emit full/absolute paths to files with errors (true by default)
  296. //absolutePaths true
  297. // if true, check all issues, including those that are off by default
  298. checkAllWarnings true
  299. // if true, treat all warnings as errors
  300. warningsAsErrors false
  301. // turn off checking the given issue id's
  302. disable 'TypographyFractions', 'TypographyQuotes'
  303. // turn on the given issue id's
  304. disable 'RtlHardcoded', 'RtlCompat', 'RtlEnabled'
  305. // check *only* the given issue id's
  306. // check 'NewApi', 'InlinedApi'
  307. // if true, don't include source code lines in the error output
  308. noLines false
  309. // if true, show all locations for an error, do not truncate lists, etc.
  310. showAll true
  311. // if true, generate an XML report for use by for example Jenkins
  312. xmlReport true
  313. // file to write report to (if not specified, defaults to lint-results.xml)
  314. xmlOutput file("lint-report.xml")
  315. // Set the severity of the given issues to fatal (which means they will be
  316. // checked during release builds (even if the lint target is not included)
  317. fatal 'NewApi', 'InlinedApi'
  318. // Set the severity of the given issues to error
  319. error 'Wakelock', 'TextViewEdits', 'ResourceAsColor'
  320. // Set the severity of the given issues to warning
  321. warning 'MissingTranslation'
  322. // Set the severity of the given issues to ignore (same as disabling the check)
  323. ignore 'TypographyQuotes'
  324. }
  325. packagingOptions {
  326. exclude 'META-INF/DEPENDENCIES.txt'
  327. exclude 'META-INF/LICENSE.txt'
  328. exclude 'META-INF/NOTICE.txt'
  329. exclude 'META-INF/NOTICE'
  330. exclude 'META-INF/LICENSE'
  331. exclude 'META-INF/DEPENDENCIES'
  332. exclude 'META-INF/notice.txt'
  333. exclude 'META-INF/license.txt'
  334. exclude 'META-INF/dependencies.txt'
  335. exclude 'META-INF/LGPL2.1'
  336. // fix https://stackoverflow.com/questions/42739916/aarch64-linux-android-strip-file-missing
  337. doNotStrip '*/mips/*.so'
  338. doNotStrip '*/mips64/*.so'
  339. doNotStrip '*/armeabi/*.so'
  340. }
  341. testOptions {
  342. // Disable animations in instrumentation tests
  343. animationsDisabled true
  344. unitTests {
  345. all {
  346. // All the usual Gradle options.
  347. testLogging {
  348. events "passed", "skipped", "failed", "standardOut", "standardError"
  349. outputs.upToDateWhen { false }
  350. exceptionFormat = 'full'
  351. }
  352. }
  353. // By default, local unit tests throw an exception any time the code you are testing tries to access
  354. // Android platform APIs (unless you mock Android dependencies yourself or with a testing
  355. // framework like Mockito). However, you can enable the following property so that the test
  356. // returns either null or zero when accessing platform APIs, rather than throwing an exception.
  357. returnDefaultValues true
  358. }
  359. }
  360. compileOptions {
  361. targetCompatibility 1.8
  362. sourceCompatibility 1.8
  363. }
  364. aaptOptions {
  365. noCompress 'png'
  366. }
  367. }
  368. dependencies {
  369. configurations.all {
  370. // Prefer modules that are part of this build (multi-project or composite build)
  371. // over external modules
  372. resolutionStrategy.preferProjectModules()
  373. // Alternatively, we can fail eagerly on version conflict to see the conflicts
  374. //resolutionStrategy.failOnVersionConflict()
  375. }
  376. // Include all JARs in the "libs" directory
  377. implementation fileTree(dir: 'libs', include: ['*.jar'])
  378. // play services
  379. implementation 'com.google.android.gms:play-services-base:16.1.0'
  380. implementation 'com.google.android.gms:play-services-wearable:16.0.1'
  381. // do not upgrade to a higher version of firebase-messaging - as we do not want the Firebase Installations API in our app
  382. implementation('com.google.firebase:firebase-messaging:20.1.0') {
  383. exclude group: 'com.google.firebase', module: 'firebase-core'
  384. exclude group: 'com.google.firebase', module: 'firebase-analytics'
  385. exclude group: 'com.google.firebase', module: 'firebase-measurement-connector'
  386. }
  387. implementation 'net.zetetic:android-database-sqlcipher:4.4.2'
  388. implementation 'com.davemorrissey.labs:subsampling-scale-image-view-androidx:3.10.0'
  389. implementation 'net.sf.opencsv:opencsv:2.3'
  390. implementation 'net.lingala.zip4j:zip4j:2.6.4'
  391. implementation 'com.getkeepsafe.taptargetview:taptargetview:1.13.0'
  392. implementation 'com.mapbox.mapboxsdk:mapbox-android-sdk:9.2.1'
  393. // commons-io 2.6 requires android 4.4
  394. implementation 'commons-io:commons-io:2.4'
  395. implementation 'org.slf4j:slf4j-api:1.7.25'
  396. implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.21'
  397. implementation 'com.theartofdev.edmodo:android-image-cropper:2.8.0'
  398. implementation 'com.datatheorem.android.trustkit:trustkit:1.1.3'
  399. implementation 'com.takisoft.preferencex:preferencex:1.1.0'
  400. implementation 'com.takisoft.preferencex:preferencex-datetimepicker:1.1.0'
  401. // AndroidX / Jetpack support libraries
  402. implementation "androidx.preference:preference:1.1.1"
  403. implementation 'androidx.legacy:legacy-support-v13:1.0.0'
  404. implementation 'androidx.recyclerview:recyclerview:1.1.0'
  405. implementation 'androidx.palette:palette:1.0.0'
  406. implementation 'androidx.appcompat:appcompat:1.2.0'
  407. implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
  408. implementation 'androidx.biometric:biometric:1.0.1'
  409. implementation "androidx.work:work-runtime:2.4.0"
  410. implementation 'androidx.fragment:fragment:1.2.5'
  411. implementation 'androidx.activity:activity:1.1.0'
  412. implementation 'androidx.sqlite:sqlite:2.1.0'
  413. implementation "androidx.concurrent:concurrent-futures:1.1.0"
  414. implementation "androidx.camera:camera-camera2:1.0.0-rc02"
  415. implementation "androidx.camera:camera-lifecycle:1.0.0-rc02"
  416. implementation "androidx.camera:camera-view:1.0.0-alpha21"
  417. implementation 'androidx.multidex:multidex:2.0.1'
  418. implementation "androidx.lifecycle:lifecycle-viewmodel:2.2.0"
  419. implementation "androidx.lifecycle:lifecycle-livedata:2.2.0"
  420. implementation "androidx.lifecycle:lifecycle-runtime:2.2.0"
  421. implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:2.2.0"
  422. implementation "androidx.lifecycle:lifecycle-service:2.2.0"
  423. implementation "androidx.lifecycle:lifecycle-process:2.2.0"
  424. implementation "androidx.lifecycle:lifecycle-common-java8:2.2.0"
  425. implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
  426. implementation 'androidx.legacy:legacy-support-v4:1.0.0'
  427. implementation "androidx.paging:paging-runtime:2.1.2"
  428. implementation 'com.google.android.material:material:1.2.1'
  429. implementation 'com.google.android.exoplayer:exoplayer-core:2.12.1'
  430. implementation 'com.google.android.exoplayer:exoplayer-ui:2.12.1'
  431. implementation 'com.google.mlkit:image-labeling:17.0.1'
  432. implementation 'com.google.protobuf:protobuf-javalite:3.9.1'
  433. implementation 'com.google.zxing:core:3.3.3' // zxing 3.4 crashes on kitkat
  434. implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.13'
  435. // webclient dependencies
  436. implementation 'org.msgpack:msgpack-core:0.8.20'
  437. implementation 'com.neovisionaries:nv-websocket-client:2.9'
  438. // Backport of Streams and CompletableFuture. Remove once API level 24 is supported.
  439. implementation 'net.sourceforge.streamsupport:streamsupport-cfuture:1.7.2'
  440. // Google Assistant Voice Action verification library
  441. implementation(name:'libgsaverification-client', ext:'aar')
  442. implementation('org.saltyrtc.client:saltyrtc-client:0.14.1') {
  443. exclude group: 'org.json'
  444. }
  445. implementation 'org.saltyrtc.chunked-dc:chunked-dc:1.0.0'
  446. implementation 'ch.threema.webrtc:webrtc-android:84.2.0'
  447. implementation('org.saltyrtc.tasks.webrtc:saltyrtc-task-webrtc:0.18.0') {
  448. exclude module: 'saltyrtc-client'
  449. }
  450. // Room components
  451. implementation 'androidx.room:room-runtime:2.2.6'
  452. annotationProcessor 'androidx.room:room-compiler:2.2.6'
  453. androidTestImplementation 'androidx.room:room-testing:2.2.6'
  454. // Glide components
  455. implementation 'com.github.bumptech.glide:glide:4.11.0'
  456. annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
  457. // use leak canary in debug builds
  458. debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.5'
  459. // test dependencies
  460. testImplementation 'junit:junit:4.12'
  461. // use powermock instead of mockito. it support mocking static classes.
  462. def mockitoVersion = '2.0.7'
  463. testImplementation "org.powermock:powermock-api-mockito2:${mockitoVersion}"
  464. testImplementation "org.powermock:powermock-module-junit4-rule-agent:${mockitoVersion}"
  465. testImplementation "org.powermock:powermock-module-junit4-rule:${mockitoVersion}"
  466. testImplementation "org.powermock:powermock-module-junit4:${mockitoVersion}"
  467. // add JSON support to tests without mocking
  468. testImplementation 'org.json:json:20160212'
  469. androidTestImplementation 'androidx.test:rules:1.2.0'
  470. androidTestImplementation 'tools.fastlane:screengrab:2.0.0', {
  471. exclude group: 'androidx.annotation', module: 'annotation'
  472. }
  473. androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0', {
  474. exclude group: 'androidx.annotation', module: 'annotation'
  475. }
  476. androidTestImplementation 'androidx.test:runner:1.1.0', {
  477. exclude group: 'androidx.annotation', module: 'annotation'
  478. }
  479. androidTestImplementation 'androidx.test.ext:junit:1.1.1'
  480. androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.1.0', {
  481. exclude group: 'androidx.annotation', module: 'annotation'
  482. exclude group: 'androidx.appcompat', module: 'appcompat'
  483. exclude group: 'androidx.legacy', module: 'legacy-support-v4'
  484. exclude group: 'com.google.android.material', module: 'material'
  485. exclude group: 'androidx.recyclerview', module: 'recyclerview'
  486. }
  487. androidTestImplementation 'androidx.test.espresso:espresso-intents:3.1.0', {
  488. exclude group: 'androidx.annotation', module: 'annotation'
  489. }
  490. androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0'
  491. }
  492. sonarqube {
  493. properties {
  494. property "sonar.projectKey", "android-client"
  495. property "sonar.projectName", "Threema for Android"
  496. property "sonar.sources", "src/main/, ../scripts/, ../scripts-internal/"
  497. // Exclusion notes:
  498. // - Protobuf code is generated
  499. // - Java Client code (including jnacl) is already being checked by SonarQube separately
  500. property "sonar.exclusions", "src/main/java/ch/threema/protobuf/**, src/main/java/ch/threema/client/**, src/test/java/ch/threema/client/**, src/main/java/ch/threema/base/**, src/main/java/ch/threema/localcrypto/**, src/test/java/ch/threema/localcrypto/**, src/main/java/com/neilalexander/jnacl/**"
  501. property "sonar.tests", "src/test/"
  502. property "sonar.sourceEncoding", "UTF-8"
  503. property "sonar.verbose", "true"
  504. }
  505. }
  506. // Set up Gradle tasks to fetch screenshots on UI test failures
  507. // See https://medium.com/stepstone-tech/how-to-capture-screenshots-for-failed-ui-tests-9927eea6e1e4
  508. def reportsDirectory = "$buildDir/reports/androidTests/connected"
  509. def screenshotsDirectory = "/sdcard/testfailures/screenshots/"
  510. def clearScreenshotsTask = task('clearScreenshots', type: Exec) {
  511. executable "${android.getAdbExe().toString()}"
  512. args 'shell', 'rm', '-r', screenshotsDirectory
  513. }
  514. def createScreenshotsDirectoryTask = task('createScreenshotsDirectory', type: Exec, group: 'reporting') {
  515. executable "${android.getAdbExe().toString()}"
  516. args 'shell', 'mkdir', '-p', screenshotsDirectory
  517. }
  518. def fetchScreenshotsTask = task('fetchScreenshots', type: Exec, group: 'reporting') {
  519. executable "${android.getAdbExe().toString()}"
  520. args 'pull', screenshotsDirectory + '.', reportsDirectory
  521. finalizedBy {
  522. clearScreenshotsTask
  523. }
  524. dependsOn {
  525. createScreenshotsDirectoryTask
  526. }
  527. doFirst {
  528. new File(reportsDirectory).mkdirs()
  529. }
  530. }
  531. tasks.whenTaskAdded { task ->
  532. if (task.name == 'connectedDebugAndroidTest') {
  533. task.finalizedBy {
  534. fetchScreenshotsTask
  535. }
  536. }
  537. }