buildscript { repositories { google() mavenCentral() maven { url "https://devserver3.ustadmobile.com/maven" } maven { url 'https://jitpack.io/' } } dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$version_kotlin" classpath "org.jetbrains.kotlin:kotlin-serialization:$version_kotlin" } } plugins { id "com.ustadmobile.adbscreenrecorder" id 'maven-publish' } apply plugin: 'com.android.library' apply plugin: "kotlin-android" //Jacoco on Android is persistently getting stuck - see https://github.com/arturdm/jacoco-android-gradle-plugin/issues/60. // Should be disabled until this is fixed or excluded unless we are specifically running tests for coverage. //apply plugin: "jacoco" apply plugin: 'kotlinx-serialization' apply plugin: "kotlin-kapt" //As Per https://developer.android.com/studio/publish/app-signing.html#release-mode def keyStorePropertiesExists = rootProject.file("keystore.properties").exists() def keystoreProperties = new Properties() if (keyStorePropertiesExists) { keystoreProperties.load(new FileInputStream(rootProject.file("keystore.properties"))) } configurations.all { exclude group: "net.sf.kxml", module: "kxml2" exclude group: "org.json", module: "json" /* * mockito-android's transient dependency objensis v2.7+ causes R8 to fail. * See * https://stackoverflow.com/questions/63612606/com-android-tools-r8-errors-a-methodhandle-invoke-and-methodhandle-invokeexact */ resolutionStrategy.force 'org.objenesis:objenesis:2.6' } kapt { javacOptions { // Increase the max count of errors from annotation processors. // Default is 100. option("-Xmaxerrs", 500) } } afterEvaluate { android.libraryVariants.all { variant -> variant.javaCompileProvider.get().dependsOn(generateCoreStringToAndroidResMap) } } //Start the test server that Espresso tests can use when we need to test communicating with a real server /* Disabled 10/Mar/22 as this is not in use, but will be restored in the near future tasks.whenTaskAdded { task -> if (task.name.toLowerCase().startsWith("connected") && task.name.toLowerCase().endsWith("androidtest")) { task.dependsOn(":lib-http-testserver:startServer") task.finalizedBy(":lib-http-testserver:stopServer") } } */ android { buildFeatures { dataBinding true } kotlinOptions { // Setup the Kotlin compiler options for the 'main' compilation: jvmTarget = "$version_kotlin_jvmTarget" freeCompilerArgs += "-Xopt-in=kotlinx.serialization.InternalSerializationApi" } sourceSets { main.assets.srcDirs += "../core/src/main/assets/" main.res.srcDirs += "../core/locale/main/" main.java.srcDirs += "build/generated/source/umlocale/" } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 coreLibraryDesugaringEnabled true } testOptions { execution 'ANDROIDX_TEST_ORCHESTRATOR' animationsDisabled true unitTests { includeAndroidResources = true returnDefaultValues = true } } dexOptions { javaMaxHeapSize "2g" } signingConfigs { release { keyAlias keyStorePropertiesExists ? keystoreProperties['keyAlias'] : "default" keyPassword keyStorePropertiesExists ? keystoreProperties['keyPassword'] : "default" storeFile keyStorePropertiesExists ? file(keystoreProperties['storeFile']) : new File("keystore.ks") storePassword keyStorePropertiesExists ? keystoreProperties['storePassword'] : "default" } } compileSdkVersion rootProject.ext.version_android_compile_sdk defaultConfig { testInstrumentationRunnerArguments clearPackageData: 'true', notAnnotation: 'com.ustadmobile.test.core.annotation.PeerServerRequiredTest,com.ustadmobile.test.core.annotation.ImplementationRequiredTest' //When using variables the build analyzer reports that major tasks reran because of a // 'chnage' in the value of minSdkVersion, hence hardcoding them here. minSdkVersion 21 targetSdkVersion 31 multiDexEnabled true //required for all variants to use java library desugaring vectorDrawables.useSupportLibrary = true testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" buildConfigField "String", "TEST_HOST", "\"" + rootProject.ext.buildConfigProperties["test.um_http_testserver"] + "\"" buildConfigField "String", "TEST_PORT", "\"" + rootProject.ext.buildConfigProperties["test.um_http_testserver_controlport"] + "\"" //see https://proandroiddev.com/current-issues-with-kotlin-multiplatform-and-how-to-fix-them-5ae62822a546 packagingOptions { pickFirst "META-INF/io.netty.versions.properties" excludes += ['META-INF/INDEX.LIST', "**/*.kotlin_metadata", "META-INF/*.kotlin_module"] } } buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' signingConfig signingConfigs.release } debug { minifyEnabled false testCoverageEnabled = false } } lint { abortOnError false } namespace 'com.toughra.ustadmobile' kotlinOptions { jvmTarget = JavaVersion.VERSION_1_8 } } /* * Disable running tests of the vanilla build (this requires multidex, so we use vanillamultidex instead) */ gradle.taskGraph.useFilter { task -> if (task.name.equals("connectedVanillaDebugAndroidTest") || task.name.equals("createVanillaDebugCoverageReport") || task.name.equals("testVanillaDebugUnitTest") || task.name.equals("testVanillaReleaseUnitTest") || task.name.equals("processVanillaDebugAndroidTestManifest") || task.name.equals("transformDexArchiveWithExternalLibsDexMergerForVanillaDebugAndroidTest")) { return false } return true } task generateCoreStringToAndroidResMap { inputs.files("../core/locale/main/values/*.xml") onlyIf { /* Only run this task if the input files have been updated since the task was last run. upToDateWhen was not having the expected effect. */ long inputLastModified = 0L rootProject.fileTree(dir: "core/locale/main", include: "values/*.xml").each() { File file -> if (file.lastModified() > inputLastModified) inputLastModified = file.lastModified() } File outputFile = project.file("build/generated/source/umlocale/com/ustadmobile/port/android/generated/MessageIDMap.kt") return outputFile.lastModified() < inputLastModified; } doLast { Map messageIds = new HashMap<>() String genSrcHeader, genSrcFooter String genSrcBody = "" genSrcHeader = "package com.ustadmobile.port.android.generated\n" genSrcHeader += "import com.ustadmobile.core.generated.locale.MessageID\n" genSrcHeader += "import com.toughra.ustadmobile.R\n" genSrcHeader += "import java.util.HashMap\n" genSrcHeader += "object MessageIDMap {\n" genSrcHeader += "\tval ID_MAP = HashMap()\n" genSrcHeader += "\tinit {\n" System.out.println("Looking in: core/locale/main") rootProject.fileTree(dir: "core/locale/main", include: "values/*.xml").each() { File file -> System.out.println("Found: " + file.getAbsolutePath()) def xmlDoc = new XmlSlurper().parseText(file.getText("UTF-8")) xmlDoc.string.each() { str -> String msgName = str.@name if (!messageIds.containsKey(msgName)) { messageIds.put(msgName, msgName) } } } Iterator nameIterator = messageIds.keySet().iterator(); while (nameIterator.hasNext()) { String strName = nameIterator.next() genSrcBody += "\tID_MAP[MessageID." + strName + "] = R.string." + strName + "\n" } genSrcFooter = "\t}\n" genSrcFooter += "}\n" File oldMessageIdFile = project.file("build/generated/source/umlocale/com/ustadmobile/port/android/generated/MessageIDMap.kt") if (oldMessageIdFile.exists()) { oldMessageIdFile.delete() } File outDir = project.file("build/generated/source/umlocale/com/ustadmobile/port/android/generated") if (!outDir.isDirectory()) { outDir.mkdirs() } File outFile = new File(outDir, "MessageIDMap.kt") outFile.setText(genSrcHeader + genSrcBody + genSrcFooter, "UTF-8") } } tasks.whenTaskAdded { task -> if (task.name.startsWith("compile") || task.name.startsWith("assemble")) { //TODO: Fix lib-content-editor to track up to date correctly, then add ":lib-content-editor:build" dependency task.dependsOn(generateCoreStringToAndroidResMap) } // TODO remove after merge with replication if (task.name.equals("lint")) { task.enabled = false } } configurations.all { resolutionStrategy { force "androidx.lifecycle:lifecycle-livedata-core:$version_androidx_lifecycle" force "androidx.lifecycle:lifecycle-runtime:$version_androidx_lifecycle" force "androidx.arch.core:core-runtime:$version_androidx_arch" } } dependencies { coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:$version_android_desugar_jdk_libs" implementation project(':core') implementation project(':sharedse') implementation "com.github.UstadMobile.door:door-runtime:$version_door" implementation project(':lib-database-android') implementation project(":lib-database-entities") implementation project(':lib-util') implementation "io.github.aakira:napier:$version_napier" implementation "androidx.constraintlayout:constraintlayout:$version_android_constraint_layout" implementation "androidx.activity:activity:$version_androidx_activity" implementation "androidx.activity:activity-ktx:$version_androidx_activity" implementation "androidx.fragment:fragment:$version_androidx_fragment" implementation "androidx.legacy:legacy-support-v4:$version_androidx_legacy_support" implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:$version_kotlinx_serialization" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$version_coroutines" implementation "commons-io:commons-io:$version_commons_io" //ViewModel and LiveData implementation "androidx.lifecycle:lifecycle-livedata-ktx:$version_androidx_lifecycle" implementation "androidx.lifecycle:lifecycle-runtime-ktx:$version_androidx_lifecycle" implementation "androidx.lifecycle:lifecycle-common-java8:$version_androidx_lifecycle" //Provides ProcessLifecycleOwner implementation "androidx.lifecycle:lifecycle-process:$version_androidx_lifecycle" //Provides findViewTreeLifecycleOwner useful for two-way data binding that uses prepareCall (e.g. images/files) implementation "androidx.lifecycle:lifecycle-runtime-ktx:$version_androidx_lifecycle" // Room (annotation processing takes place only on lib-database-android to improve build times) implementation "androidx.room:room-runtime:$version_android_room" implementation "androidx.core:core-ktx:$version_androidx_core" // Paging implementation "androidx.paging:paging-runtime:$version_androidx_paging" //Work manager implementation "androidx.work:work-runtime:$version_android_workmanager" //Klock implementation "com.soywiz.korlibs.klock:klock-android:$version_klock" //Crash reporting implementation "ch.acra:acra-http:$version_android_acra" implementation "com.linkedin.android.litr:litr:$version_android_litr" implementation "androidx.legacy:legacy-support-core-utils:$version_androidx_legacy" implementation "androidx.appcompat:appcompat:$version_androidx_appcompat" implementation "androidx.cardview:cardview:$version_androidx_cardview" implementation "com.google.android.material:material:$version_android_material" implementation "androidx.legacy:legacy-support-v4:$version_androidx_legacy" implementation "androidx.recyclerview:recyclerview:$version_androidx_recyclerview" //Image loading library implementation "com.squareup.picasso:picasso:$version_android_picasso" //Page indicator // Should be replaced with https://github.com/tommybuonomo/dotsindicator //implementation 'com.romandanylyk:pageindicatorview:1.0.0@aar' // shake detector implementation "com.squareup:seismic:$version_android_seismic" implementation "de.hdodenhof:circleimageview:$version_android_circleimageview" implementation "com.google.android.exoplayer:exoplayer:$version_exo_player" //used for learner progress view - needs removed because this clashes with material dependency. //implementation 'com.txusballesteros:FitChart:1.0' //Chart library implementation "com.github.PhilJay:MPAndroidChart:$version_mpandroidchart" implementation "com.google.android.flexbox:flexbox:$version_android_flexbox" //Gson for JSON serializing and deserializing implementation "com.google.code.gson:gson:$version_gson" //KTOR implementation "io.ktor:ktor-client-gson:$version_ktor" implementation "io.ktor:ktor-client-okhttp:$version_ktor" implementation "io.ktor:ktor-client-cio:$version_ktor" //http server implementation "org.nanohttpd:nanohttpd:$version_nanohttpd" implementation "org.nanohttpd:nanohttpd-nanolets:$version_nanohttpd" //image compressor implementation "id.zelory:compressor:$version_compressor" //Android play core for update support within the application implementation "com.google.android.play:core:$version_play_core" implementation "androidx.navigation:navigation-fragment-ktx:$version_android_navigation" implementation "androidx.navigation:navigation-ui:$version_android_navigation" implementation "androidx.navigation:navigation-ui-ktx:$version_android_navigation" //dependency injection implementation "org.kodein.di:kodein-di-framework-android-x:$version_kodein_di" //HTML editor implementation "org.wordpress:aztec:$version_android_aztec" // Dependencies of Aztec: Versions must be fixed to ensure that they point to versions available // on mavenCentral after jcenter shutdown. //implementation "org.wordpress:utils:$version_android_wordpress_utils" implementation "com.android.volley:volley:$version_android_volley" //Persian-Date-Picker implementation 'com.github.varunasingh:Persian-Date-Picker-Dialog-Strings:primary-SNAPSHOT' implementation 'com.ernestoyaquello.dragdropswiperecyclerview:drag-drop-swipe-recyclerview:1.1.1' //Better Link Movement Method implementation "me.saket:better-link-movement-method:$version_better_link_movement" testImplementation project(":lib-test-common") testImplementation "org.mockito:mockito-core:$version_android_mockito" testImplementation "androidx.test:core:$version_android_junit_runner" testImplementation "androidx.test:runner:$version_android_junit_runner" testImplementation "androidx.test.ext:junit:$version_androidx_test_ext_junit" testImplementation "androidx.fragment:fragment-testing:$version_androidx_fragment" testImplementation "androidx.navigation:navigation-testing:$version_android_navigation" testImplementation "org.robolectric:robolectric:$version_android_roboelectric" testImplementation "junit:junit:$version_junit" testImplementation "com.squareup.okhttp3:okhttp:$version_okhttp" testImplementation "org.mockito.kotlin:mockito-kotlin:$version_kotlin_mockito" testImplementation "androidx.test.espresso:espresso-core:$version_android_espresso" testImplementation "androidx.test.espresso:espresso-contrib:$version_android_espresso" //Required for databinding to work using JVM tests kaptTest "androidx.databinding:databinding-compiler:$version_androidx_databinding" androidTestImplementation project(":lib-test-common") androidTestImplementation "androidx.test:core:$version_android_junit_runner" androidTestImplementation "androidx.test:core-ktx:$version_android_junit_runner" /* * 15/Apr/2022 * If we do not exclude checkerframework there are duplicate class errors as per: * https://github.com/android/android-test/issues/861 * See also: * https://github.com/google/ExoPlayer/issues/10007 */ androidTestImplementation ("com.kaspersky.android-components:kaspresso:$version_kaspresso") { exclude group: "org.checkerframework", module: "checker" exclude group: "org.checkerframework", module: "check-qual" } androidTestImplementation "io.ktor:ktor-server-servlet:$version_ktor" androidTestImplementation "junit:junit:$version_junit" androidTestImplementation group: 'androidx.annotation', name: 'annotation', version: "$version_androidx_annotation" //As per: https://developer.android.com/topic/libraries/testing-support-library/packages.html#gradle-dependencies androidTestImplementation "androidx.test:runner:$version_android_junit_runner" androidTestImplementation "androidx.test:rules:$version_android_junit_runner" androidTestUtil "androidx.test:orchestrator:$version_android_junit_runner" //As per androidTestImplementation ("androidx.test.espresso:espresso-core:$version_android_espresso") { exclude group: "org.checkerframework", module: "checker" exclude group: "org.checkerframework", module: "check-qual" } androidTestImplementation("androidx.test.espresso:espresso-contrib:$version_android_espresso") { exclude group: "org.checkerframework", module: "checker" exclude group: "org.checkerframework", module: "check-qual" } androidTestImplementation ("androidx.test.espresso:espresso-intents:$version_android_espresso") { exclude group: "org.checkerframework", module: "checker" exclude group: "org.checkerframework", module: "check-qual" } androidTestImplementation ("androidx.test.espresso:espresso-web:$version_android_espresso") { exclude group: "org.checkerframework", module: "checker" exclude group: "org.checkerframework", module: "check-qual" } androidTestImplementation "androidx.fragment:fragment-testing:$version_androidx_fragment" androidTestImplementation "androidx.navigation:navigation-testing:$version_android_navigation" androidTestImplementation "androidx.test.ext:junit:$version_androidx_test_ext_junit" //See https://github.com/xabaras/recyclerview-child-actions - used for Espresso tests to click / check items inside a recycler view androidTestImplementation "it.xabaras.android.espresso:recyclerview-child-actions:$version_android_espresso_recyclerviewchildactions" androidTestImplementation "androidx.test.uiautomator:uiautomator:$version_android_uiautomator" androidTestImplementation "org.mockito:mockito-android:$version_android_mockito" androidTestImplementation "org.mockito.kotlin:mockito-kotlin:$version_kotlin_mockito" androidTestImplementation "com.squareup.okhttp3:mockwebserver:$version_mockwebserver" androidTestImplementation "commons-io:commons-io:$version_commons_io" androidTestImplementation "com.github.UstadMobile.AdbScreenRecorder:lib-client:$version_android_adbscreenrecorder" kaptAndroidTest "androidx.databinding:databinding-compiler:$version_androidx_databinding" } task sourceJar(type: Jar) { from android.sourceSets.main.java.srcDirs classifier "source" } afterEvaluate { publishing { publications { release(MavenPublication) { // Applies the component for the release build variant. from components.release // You can then customize attributes of the publication as shown below. groupId = rootProject.group artifactId = project.name version = rootProject.version } // Creates a Maven publication called “debug”. debug(MavenPublication) { // Applies the component for the debug build variant. from components.debug groupId = rootProject.group artifactId = project.name version = rootProject.version } } repositories { maven { url rootProject.ext.buildConfigProperties['repo.dir'] } } } }