import groovy.json.JsonSlurper buildscript { repositories { google() mavenCentral() jcenter() } dependencies { classpath "com.android.tools.build:gradle:$androidGradlePluginVersion" classpath "com.testdroid:gradle:$testdroidGradlePluginVersion" classpath 'org.apache.httpcomponents:httpclient-android:4.3.3' } } apply plugin: 'com.android.application' apply plugin: 'checkstyle' apply plugin: 'testdroid' repositories { google() mavenCentral() maven { url 'https://maven.google.com' } jcenter() } String[] archs = ['arm64-v8a', 'armeabi', 'mips', 'mips64', 'x86', 'x86_64'] dependencies { // Get kiwixlib online if it is not populated locally if (file("../kiwixlib/src/main").list().length == 1) { implementation 'org.kiwix.kiwixlib:kiwixlib:1.0.11' } else { implementation project(':kiwixlib') archs = file("../kiwixlib/src/main/jniLibs").list() } // Storage Devices implementation 'eu.mhutti1.utils.storage:android-storage-devices:0.6.2' // Android Support implementation "androidx.appcompat:appcompat:$appCompatVersion" implementation "com.google.android.material:material:$materialVersion" implementation "androidx.cardview:cardview:$cardViewVersion" implementation "androidx.multidex:multidex:$multidexVersion" implementation "androidx.constraintlayout:constraintlayout:$constraintLayoutVersion" implementation "androidx.test.espresso:espresso-idling-resource:$espressoVersion" androidTestImplementation("androidx.test.espresso:espresso-core:$espressoVersion") androidTestImplementation "androidx.test.espresso:espresso-web:$espressoVersion" androidTestImplementation "androidx.test.espresso:espresso-intents:$espressoVersion" androidTestImplementation("androidx.test.espresso:espresso-contrib:$espressoVersion") { exclude group: 'androidx.legacy', module: 'legacy-support-core-utils' exclude group: 'androidx.viewpager', module: 'viewpager' exclude group: 'com.google.android.material', module: 'material' exclude group: 'androidx.recyclerview', module: 'recyclerview' } androidTestImplementation("com.schibsted.spain:barista:$baristaVersion") { exclude group: 'com.android.support' } androidTestImplementation "androidx.annotation:annotation:$annotationVersion" androidTestImplementation "androidx.test.ext:junit:1.1.0" androidTestImplementation 'androidx.test:runner:1.1.1' androidTestImplementation 'androidx.test:rules:1.1.1' androidTestImplementation 'androidx.test:core:1.1.0' // Tab indicator implementation "com.pacioianu.david:ink-page-indicator:$inkPageIndicatorVersion" // Dagger compileOnly "javax.annotation:javax.annotation-api:$javaxAnnotationVersion" androidTestCompileOnly "javax.annotation:javax.annotation-api:$javaxAnnotationVersion" implementation "com.google.dagger:dagger:$daggerVersion" implementation "com.google.dagger:dagger-android:$daggerVersion" annotationProcessor "com.google.dagger:dagger-compiler:$daggerVersion" annotationProcessor "com.google.dagger:dagger-android-processor:$daggerVersion" androidTestAnnotationProcessor "com.google.dagger:dagger-compiler:$daggerVersion" // SquiDB implementation 'com.yahoo.squidb:squidb:2.0.0' implementation 'com.yahoo.squidb:squidb-annotations:2.0.0' annotationProcessor 'com.yahoo.squidb:squidb-processor:2.0.0' // Apache androidTestImplementation "commons-io:commons-io:$apacheCommonsVersion" // Square implementation "com.squareup.okhttp3:okhttp:$okHttpVersion" implementation "com.squareup.okhttp3:logging-interceptor:$okHttpVersion" implementation "com.squareup.retrofit2:retrofit:$retrofitVersion" implementation "com.squareup.retrofit2:adapter-rxjava2:$retrofitVersion" implementation("com.squareup.retrofit2:converter-simplexml:$retrofitVersion") { exclude group: 'xpp3', module: 'xpp3' exclude group: 'stax', module: 'stax-api' exclude group: 'stax', module: 'stax' } androidTestImplementation 'com.squareup.okhttp3:mockwebserver:3.6.0' // ButterKnife implementation "com.jakewharton:butterknife:$butterKnifeVersion" annotationProcessor "com.jakewharton:butterknife-compiler:$butterKnifeVersion" // RxJava implementation "io.reactivex.rxjava2:rxandroid:$rxAndroidVersion" implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion" // JUnit testImplementation "junit:junit:$jUnitVersion" androidTestImplementation "junit:junit:$jUnitVersion" // Mockito testImplementation "org.mockito:mockito-core:$mockitoVersion" androidTestImplementation "org.mockito:mockito-android:$mockitoVersion" // PowerMockito testImplementation "org.powermock:powermock:$powerMockVersion" testImplementation "org.powermock:powermock-module-junit4:$powerMockJUnitVersion" testImplementation "org.powermock:powermock-api-mockito2:$powerMockJUnitVersion" // Leak canary implementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.4' // Only enable leak canary in debug builds configurations.all { config -> if (config.name.contains('debug') || config.name.contains("Debug")) { config.resolutionStrategy.eachDependency { details -> if (details.requested.group == 'com.squareup.leakcanary' && details.requested.name == 'leakcanary-android-no-op') { details.useTarget(group: details.requested.group, name: 'leakcanary-android', version: details.requested.version) } } } } } // Set custom app import directory def map = [:] def custom = new File("app/src") if (project.hasProperty('customDir')) { custom = file(project.property('customDir')) } // Set up flavours for each custom app in the directory if (custom.listFiles()) { custom.eachFile() { file -> def fileName = file.getName() if (fileName.startsWith(".") || fileName.contains("test") || fileName == "main" || fileName.contains("Test")) { return } map.put(fileName, file.getAbsolutePath()) } } android { compileSdkVersion 28 defaultConfig { minSdkVersion 14 targetSdkVersion 28 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" // See https://github.com/linkedin/dexmaker/issues/65 for why we need the following line. testInstrumentationRunnerArguments.notClass = 'com.android.dex.DexIndexOverflowException' multiDexEnabled true vectorDrawables.useSupportLibrary = true } aaptOptions { cruncherEnabled true } testBuildType "coverage" lintOptions { // Treat lint seriously abortOnError true // Hardcoded strings in xml error 'HardcodedText' // Hardcoded strings in setText error 'SetTextI18n' // Strings.xml issues warning 'ExtraTranslation' warning 'MissingTranslation' // Warnings warning 'InvalidPackage' warning 'StringFormatInvalid' } flavorDimensions "default" buildTypes { // Main build type for debugging debug { buildConfigField "String", "KIWIX_DOWNLOAD_URL", "\"http://download.kiwix.org/\"" // True breaks local variables being shown in breakpoints testCoverageEnabled false // Needed for instrumentation tests on Pre 5.0 multiDexKeepProguard file('multidex-instrumentation-config.pro') } mock_network { initWith(buildTypes.debug) matchingFallbacks = ['debug', 'release'] // TODO add DI for the mock network } local_download_server { initWith(buildTypes.debug) buildConfigField "String", "KIWIX_DOWNLOAD_URL", "\"http://kiwix-download-server/\"" matchingFallbacks = ['debug', 'release'] } // Used to assess code coverage coverage { initWith debug testCoverageEnabled true matchingFallbacks = ['debug', 'release'] } // Release Type release { buildConfigField "String", "KIWIX_DOWNLOAD_URL", "\"http://download.kiwix.org/\"" } } productFlavors { // Vanilla Kiwix app kiwix { println "Configuring Kiwix" // Set vanilla config buildConfigField "boolean", "IS_CUSTOM_APP", "false" buildConfigField "boolean", "HAS_EMBEDDED_ZIM", "false" buildConfigField "String", "ZIM_FILE_NAME", "\"\"" buildConfigField "long", "ZIM_FILE_SIZE", "0" buildConfigField "int", "CONTENT_VERSION_CODE", "0" buildConfigField "String", "ENFORCED_LANG", "\"\"" resValue "string", "app_name", "Kiwix" resValue "string", "app_search_string", "Search Kiwix" if (project.hasProperty('version_code')) { def version_code = project.property('version_code') versionCode version_code.toInteger() } else { versionCode 55 } if (project.hasProperty('version_name')) { versionName project.property('version_name') } else { versionName "2.4" } } // Custom apps built from a json file, zim file and icon set map.each { name, directory -> "$name" { println "Configuring $name" if (file(directory + "/build.gradle").exists()) { apply from: directory + "/build.gradle" } def jsonFile if (project.hasProperty('jsonFile')) { // Read json file from properties e.g command line jsonFile = file(project.property('jsonFile')) } else { // If no file provided use the test file jsonFile = file(directory + '/info.json') } def parsedJson = new JsonSlurper().parseText(jsonFile.text) def sourceFile = file(parsedJson.zim_file) if (!sourceFile.exists()) { sourceFile = file(directory + "/" + parsedJson.zim_file) } if (parsedJson.embed_zim) { // Place content in each lib directory for embeded zims for (String archName : archs) { copy { from sourceFile into file(directory + "/jniLibs/" + archName) rename { String filename -> "libcontent.so" } } } parsedJson.zim_file = "libcontent.so" } // Set custom config from json applicationId "$parsedJson.package" buildConfigField "boolean", "IS_CUSTOM_APP", "true" buildConfigField "boolean", "HAS_EMBEDDED_ZIM", "$parsedJson.embed_zim" def filename if (parsedJson.zim_file.lastIndexOf('/') >= 0) { filename = parsedJson.zim_file.substring(parsedJson.zim_file.lastIndexOf('/') + 1) } else { filename = parsedJson.zim_file } buildConfigField "String", "ZIM_FILE_NAME", "\"$filename\"" if (project.hasProperty('zim_file_size')) { def length = Long.parseLong(project.property('zim_file_size')) buildConfigField "long", "ZIM_FILE_SIZE", "${length}L" } else { long length = sourceFile.length() buildConfigField "long", "ZIM_FILE_SIZE", "${length}L" } if (project.hasProperty('version_code')) { def version_code = project.property('version_code') versionCode version_code.toInteger() } else { versionCode parsedJson.version_code.toInteger() } if (project.hasProperty('version_name')) { versionName project.property('version_name') } else { versionName parsedJson.version_name } if (project.hasProperty('content_version_code')) { def content_version_code = project.property('content_version_code') buildConfigField "int", "CONTENT_VERSION_CODE", "$content_version_code" } else if (parsedJson.content_version_code != null) { buildConfigField "int", "CONTENT_VERSION_CODE", "$parsedJson.content_version_code" } else if (project.hasProperty('version_code')) { def version_code = project.property('version_code') buildConfigField "int", "CONTENT_VERSION_CODE", "$version_code" } else if (parsedJson.version_code != null) { buildConfigField "int", "CONTENT_VERSION_CODE", "$parsedJson.version_code" } buildConfigField "String", "ENFORCED_LANG", "\"$parsedJson.enforced_lang\"" resValue "string", "app_name", "$parsedJson.app_name" resValue "string", "app_search_string", 'Search ' + "$parsedJson.app_name" } } } // Set each custom apps respective source directory sourceSets { map.each { name, directory -> "$name" { setRoot directory jni.srcDirs = [] jniLibs.srcDir directory + '/jniLibs' } } } compileOptions { encoding = "UTF-8" sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } dexOptions { javaMaxHeapSize "4g" } /* Add back once proguard is configured buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt') } } */ } // Testdroid deployment configuration def buildNumber = System.getenv('TRAVIS_BUILD_NUMBER') def findJar(prefix) { configurations.runtime.filter { it.name.startsWith(prefix) } } testdroid { authorization "APIKEY" apiKey System.getenv('BITBAR_API_KEY') deviceGroup 'Kiwix' projectName "Kiwix" testRunName "Auto Test " + buildNumber fullRunConfig { instrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } }