<NME> build.gradle
<BEF> import org.apache.tools.ant.filters.ReplaceTokens

/*
 * Run "gradlew" or "gradlew cgeoHelp" in the parent directory for a help of how to use this build file.
 */


/*
 * Android plugin, http://developer.android.com/tools/building/plugin-for-gradle.html
 */
apply plugin: 'com.android.application'

/*
 * https://github.com/KeepSafe/dexcount-gradle-plugin
 * dex counting can take several seconds, therefore do this only on the CI server
 */
if (isContinuousIntegrationServer()) {
    apply plugin: 'com.getkeepsafe.dexcount'
}

android {
    compileSdkVersion 31

    compileOptions {
        // use the diamond operator and some other goodies in Android
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    defaultConfig {
        minSdkVersion 21
        //noinspection OldTargetApi
        targetSdkVersion 31
        versionName versionNameFromDate()
        versionCode versionCodeFromDate(0)

        // NOTE: must match the package in the test directory and must be different from the app package
        testApplicationId "cgeo.geocaching.test"

        //testHandlingProfiling true
        testFunctionalTest true

        // set the default test runner to be used by IDE and command line
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

        // by convention, the folder name "main" is used for the APK file name. we want cgeo instead
        archivesBaseName = "cgeo"

        // this is necessary to move .google_measurement_service into a app-specific namespace (see https://github.com/kotmyrevich/analytics-issues/issues/784)
        applicationId = "cgeo.geocaching"

        // include only those language resources from libraries which we actively maintain ourselves in the translation project at https://crowdin.com/project/cgeo
        // not yet enough translations (~50%): "is","iw"(="he"),"lb"
        def locales = [ "en","ar","ca","ceb","cs","da","de","el","es","fi","fil","fr","hu","in","it","ja","ko","lt","lv","nb","nl","pl","pt","ro","ru","sk","sl","sv","tl","tr","uk","zh","zh-rTW" ]

        // needed for in-app language selector
        buildConfigField "String[]", "TRANSLATION_ARRAY", "new String[]{\""+locales.join("\",\"")+"\"}"

        resConfigs locales
    }

    // signing is handled via private.properties
    signingConfigs {
        release
    }

    buildFeatures {
        viewBinding true
    }

    buildTypes {
        debug {
            // debug build name contains git commit for better reproduction of bugs
            versionNameSuffix "-" + GitCommit.currentShort() + " developer build"

            // additional proguard rules just for the test code
            testProguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt', '../tests/proguard-project.txt'

            // code coverage
            testCoverageEnabled isContinuousIntegrationServer()

            // replace in AndroidManifest.xml
            manifestPlaceholders = [
                appIcon:      "@mipmap/ic_launcher_debug",
                appIconRound: "@mipmap/ic_launcher_debug_round"
            ]
        }
        nightly {
            def nightlyName = System.getenv('NB') // NB, NB1, ...
            versionNameSuffix "-$nightlyName-" + GitCommit.currentShort()
            signingConfig signingConfigs.release
            // use release version of source code library dependencies
            matchingFallbacks = ['release']
            manifestPlaceholders = [
                appIcon:      "@mipmap/ic_launcher_nightly",
                appIconRound: "@mipmap/ic_launcher_nightly_round"
            ]
        }
        rc {
            def rcName = System.getenv('RC') // RC, RC1, RC2 ...
            versionNameSuffix "-$rcName"
            signingConfig signingConfigs.release
            // use release version of source code library dependencies
            matchingFallbacks = ['release']
            manifestPlaceholders = [
                appIcon:      "@mipmap/ic_launcher_rc",
                appIconRound: "@mipmap/ic_launcher_rc_round"
            ]
        }
        legacy {
            signingConfig signingConfigs.release
            // use release version of source code library dependencies
            matchingFallbacks = ['release']
            manifestPlaceholders = [
                appIcon:      "@mipmap/ic_launcher",
                appIconRound: "@mipmap/ic_launcher_round"
            ]
        }
        release {
            signingConfig signingConfigs.release
            manifestPlaceholders = [
                appIcon:      "@mipmap/ic_launcher",
                appIconRound: "@mipmap/ic_launcher_round"
            ]
        }
    }

    buildTypes.all { buildType ->
        // as it affects the build speed, do skip some steps for debug builds
        if (buildType.name != 'debug') {
            // enable proguard and remove unused code
            minifyEnabled true

            // remove unused resources in addition to unused code
            shrinkResources true
        }

        // proguard rules
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt'
    }

    testBuildType "debug" //the default BuildType

    sourceSets {
        // application sources in source set "main"
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src', 'thirdparty', '../common/src'] // no need for annotation generated sources
            res.srcDirs = ['res', 'res.maplegends/elevate', 'res.maplegends/fzk', 'res.maplegends/fzk-outdoor']
            assets.srcDirs = ['assets']
            aidl.srcDirs = ['src'] // default src/main/aidl creates package name conflicts in Eclipse
        }
        // local unit tests, which can be executed without a device
        test {
            setRoot("../tests")
            manifest.srcFile '../tests/AndroidManifest.xml'
            java.srcDir '../tests/src'
            resources.srcDirs = ['../tests/src']
            res.srcDirs = ['../tests/res']
        }
        // device/emulator based instrumentation tests in source set "androidTest"
        androidTest{
            // map tests to the Eclipse style test project instead of the default app/src/androidTest/java
            setRoot("../tests")
            manifest.srcFile '../tests/AndroidManifest.xml'
            java {
                srcDir '../tests/src-android'
            }
            resources.srcDirs = ['../tests/src']
            res.srcDirs = ['../tests/res']
        }
        // TODO: the package cgeo.geocaching.test.mock is currently duplicated in both "src" and "src-android". if a shared source folder is used instead, then we get java.lang.VerificationExceptions, because the 2 unit test frameworks modify the classes in different ways
    }

    testOptions {
        resultsDir = "$project.buildDir/build/test-results"
    }

    lintOptions {
        // we do not accept lint errors when building
        abortOnError true
        // Warnings shall not fail build
        warningsAsErrors false

        // abort release builds in case of FATAL errors
        checkReleaseBuilds true

        absolutePaths false

        // ExtraTranslation - old translation will be deleted by the next crowdin import
        disable 'ExtraTranslation'

        // analyze all dependency modules in parallel and produce a single report
        // including issues from the app and all of its dependencies
        checkDependencies true
    }

    packagingOptions {
        // you can double click an APK file in Android Studio 2.2+ to see what's in there
        // license files of libs are not needed in our APK
        exclude 'META-INF/DEPENDENCIES'
        exclude 'META-INF/dependencies'
        exclude 'META-INF/NOTICE'
        exclude 'META-INF/notice'
        exclude 'META-INF/LICENSE'
        exclude 'META-INF/license'
        exclude 'META-INF/LICENSE.txt'
        exclude 'META-INF/license.txt'
        exclude 'META-INF/NOTICE.txt'
        exclude 'META-INF/notice.txt'
        exclude 'COPYING'
        exclude 'COPYING.LESSER'
        exclude '.readme'
        // AndroidAnnotations
        exclude 'androidannotations-api.properties'
        // mapsforge
        exclude 'META-INF/maven/org.mapsforge/mapsforge-map-reader/pom.properties'
        exclude 'META-INF/maven/org.mapsforge/mapsforge-map-reader/pom.xml'
        exclude 'META-INF/maven/org.mapsforge/mapsforge-map/pom.properties'
        exclude 'META-INF/maven/org.mapsforge/mapsforge-map/pom.xml'
        exclude 'COPYING.LESSER.v3'
        exclude 'COPYING.v3'
        // Play Services
        exclude 'build-data.properties'
        // rxjava
        exclude 'META-INF/rxandroid.properties'
        exclude 'META-INF/rxjava.properties'

        // vtm-themes
        resources.pickFirsts.add("assets/symbols/**")
        resources.pickFirsts.add("assets/patterns/**")
    }

    flavorDimensions "javaCompilerTime" // all flavours must be assigned a dimension
    // Android Studio recommended test runner, see https://developer.android.com/tools/testing-support-library/index.html#setup
    androidTestCompile 'com.android.support.test:runner:0.4.1'

    // TODO: this line is only needed to enforce the same version of the support annotations for the main app and the test app. it can be removed when upgrading the support library in our app
    compile 'com.android.support:support-annotations:23.0.1'

    // Junit only needed for local unit tests
    testCompile 'junit:junit:4.12'
            buildConfigField "String", "SPECIAL_BUILD", '"Disabled JIT"'
        }
    }

    // remove the "-basic" flavour name from the generated APK, have the flavor remain only for special builds
    applicationVariants.all { variant ->
        variant.outputs.all { output ->
            outputFileName = outputFileName.replace('-basic-', '-')
        }
    }

    // special version code for nightly and rc builds
    applicationVariants.all { variant ->
        if (variant.buildType.name == 'nightly') {
            variant.outputs.all {
                setVersionCodeOverride(versionCodeFromDate(10000000))
            }
        }
        if (variant.buildType.name == 'rc') {
            variant.outputs.all {
                setVersionCodeOverride(versionCodeFromDate(-1))
            }
        }
        if (variant.buildType.name == 'legacy') {
            def legacyName = System.getenv('LEGACY_VERSION_NAME')
            def legacyVersion = System.getenv('LEGACY_VERSION_CODE') as Integer
            if (legacyName != null && legacyVersion != null) {
                variant.outputs.all {
                    setVersionNameOverride(legacyName)
                    setVersionCodeOverride(legacyVersion)
                }
            }
        }
        // debug and release builds have offset zero, no special handling here
    }

    // tests rely on JUnit-based classes
    useLibrary 'android.test.runner'
    useLibrary 'android.test.base'
}

dependencies {
    // AndroidAnnotations, https://github.com/excilys/androidannotations/wiki/building-project-gradle
    def androidAnnotationsVersion = '4.8.0'
    annotationProcessor "org.androidannotations:androidannotations:$androidAnnotationsVersion"
    implementation "org.androidannotations:androidannotations-api:$androidAnnotationsVersion"

    // Apache Commons
    implementation 'org.apache.commons:commons-collections4:4.4'
    implementation 'org.apache.commons:commons-compress:1.20'
    // commons-lang3 3.12.0 uses StringJoiner which is first contained in Android API24
    // See https://github.com/cgeo/cgeo/issues/12577
    //noinspection GradleDependency
    implementation 'org.apache.commons:commons-lang3:3.11'
    implementation 'org.apache.commons:commons-text:1.9'

    // commons-io 2.6 uses java.nio.file.Path - which is first contained in Android API26
    // could be replaced by Storage Access Framework
    //noinspection GradleDependency
    implementation 'commons-io:commons-io:2.5'

    // License: Apache-2.0. https://github.com/k3b/k3b-geoHelper/
    // decode geo-uris and web-map-service-urls
    implementation('com.github.k3b:k3b-geoHelper:v1.1.11') {
        // do not get transitive 'commons-io:commons-io:2.6' as c:geo uses 2.5 to be compatible with older android versions
        exclude group: 'commons-io', module: 'commons-io'
    }

    // AssertJ for testing, needed both for local unit tests and Android instrumentation tests
    def assertJVersion = '2.9.1'
    testImplementation "org.assertj:assertj-core:$assertJVersion"
    androidTestImplementation "org.assertj:assertj-core:$assertJVersion"

    // SpotBugs (successor of FindBugs)
    implementation 'net.jcip:jcip-annotations:1.0'
    implementation 'com.github.spotbugs:spotbugs-annotations:4.5.3'

    // GeographicLib
    implementation 'net.sf.geographiclib:GeographicLib-Java:1.52'

    // Jackson XML processing
    def jacksonVersion = '2.12.5'
    implementation "com.fasterxml.jackson.core:jackson-core:$jacksonVersion"
    implementation "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion"
    implementation "com.fasterxml.jackson.core:jackson-annotations:$jacksonVersion"

    // Jsoup HTML parsing
    implementation 'org.jsoup:jsoup:1.14.3'

    // Junit only needed for local unit tests
    testImplementation 'junit:junit:4.13.2'

    // Leak Canary, memory leak detection
    def leakCanaryVersion = '2.9.1'
    debugImplementation "com.squareup.leakcanary:leakcanary-android:$leakCanaryVersion"
    implementation "com.squareup.leakcanary:plumber-android:$leakCanaryVersion"

    // Locus Maps integration
    implementation "com.asamm:locus-api-android:0.9.32"

    // Mapsforge official version
    //def mapsforgeSource = 'org.mapsforge'
    //def mapsforgeVersion = '0.18.0'

    // Mapsforge Snapshot from official master branch (via https://jitpack.io/#mapsforge/mapsforge)
    //def mapsforgeSource = 'com.github.mapsforge.mapsforge'
    //def mapsforgeVersion = 'fbc75a4' // master as of 18.07.22

    // Mapsforge Snapshot from cgeo's GitHub repository (via https://jitpack.io/#cgeo/mapsforge)
    def mapsforgeSource = 'com.github.cgeo.mapsforge'
    def mapsforgeVersion = 'fbc75a4' // fix for #12210

    implementation "$mapsforgeSource:mapsforge-core:$mapsforgeVersion"
    implementation "$mapsforgeSource:mapsforge-map:$mapsforgeVersion"
    implementation "$mapsforgeSource:mapsforge-map-android:$mapsforgeVersion"
    implementation "$mapsforgeSource:mapsforge-map-reader:$mapsforgeVersion"
    implementation "$mapsforgeSource:mapsforge-themes:$mapsforgeVersion"

    // Mapsforge VTM implementation
    def mapsforgeVTMSource = 'org.mapsforge'
    def mapsforgeVTMVersion = '0.18.0'

    implementation "$mapsforgeVTMSource:vtm:$mapsforgeVTMVersion"
    implementation "$mapsforgeVTMSource:vtm-themes:$mapsforgeVTMVersion"
    implementation "$mapsforgeVTMSource:vtm-jts:$mapsforgeVTMVersion"
    implementation "org.locationtech.jts:jts-core:1.16.1"

    implementation "$mapsforgeVTMSource:vtm-android:$mapsforgeVTMVersion"
    implementation "$mapsforgeVTMSource:vtm-android:$mapsforgeVTMVersion:natives-armeabi-v7a"
    implementation "$mapsforgeVTMSource:vtm-android:$mapsforgeVTMVersion:natives-arm64-v8a"
    implementation "$mapsforgeVTMSource:vtm-android:$mapsforgeVTMVersion:natives-x86"
    implementation "$mapsforgeVTMSource:vtm-android:$mapsforgeVTMVersion:natives-x86_64"

    implementation "$mapsforgeVTMSource:vtm-http:$mapsforgeVTMVersion"

    configurations {
        all*.exclude group: 'net.sf.kxml', module: 'kxml2' // duplicate XmlPullParser class
    }

    // used by mapsforge
    implementation 'com.caverock:androidsvg:1.4'

    // Maps.ME integration
    implementation project(":mapswithme-api")

    // Metadata Extractor, EXIF location extraction from images
    implementation 'com.drewnoakes:metadata-extractor:2.18.0'

    def okhttpVersion = '4.10.0'
    implementation "com.squareup.okhttp3:okhttp:$okhttpVersion"
    // For local unit tests
    testImplementation "com.squareup.okhttp3:mockwebserver:$okhttpVersion"

    // Play Services
    implementation 'com.google.android.gms:play-services-location:19.0.1'
    implementation 'com.google.android.gms:play-services-maps:17.0.1'
    // somehow there is a transitive play service dependency which we don't want
    configurations.all*.exclude module: "play-services-measurement"

    // Support Library Design
    implementation 'com.google.android.material:material:1.6.1'

    // ProcessPhoenix, reliable process restart
    // implementation 'com.jakewharton:process-phoenix:2.0.0'

    // RxJava
    implementation 'io.reactivex.rxjava3:rxjava:3.1.5'
    implementation "io.reactivex.rxjava3:rxandroid:3.0.0"

    // Support Library Lifecycle Helpers
    def lifecycleVersion = '2.5.1'
    implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycleVersion"
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycleVersion"
    implementation "androidx.lifecycle:lifecycle-livedata:$lifecycleVersion"
    implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycleVersion"
    implementation "androidx.lifecycle:lifecycle-reactivestreams:$lifecycleVersion"

    // Support Library AppCompat
    implementation 'androidx.appcompat:appcompat:1.4.2'

    // Support Library core (used for eg. HtmlCompat)
    implementation 'androidx.core:core:1.8.0'

    // Support Library constraintlayout
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'

    // Support Library ExifInterface
    implementation 'androidx.exifinterface:exifinterface:1.3.4'

    // Support Library GridLayout used by the coordinate calculator
    implementation 'androidx.gridlayout:gridlayout:1.0.0'

    // Support Library RecyclerView
    implementation 'androidx.recyclerview:recyclerview:1.2.1'

    // Settings Library
    implementation 'androidx.preference:preference:1.2.0'

    // Support Annotations. use same version for the main app and the test app
    def annotationVersion = '1.4.0'
    implementation "androidx.annotation:annotation:$annotationVersion"
    androidTestImplementation "androidx.annotation:annotation:$annotationVersion"

    // Testing Support Libraries
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'

    // Drag n drop for listview
    implementation 'asia.ivity.android:drag-sort-listview:1.0'

    // needed for chrome custom tabs
    implementation 'androidx.browser:browser:1.4.0'

    // Zxing barcode reader integration
    implementation 'com.google.zxing:android-integration:3.3.0'

    // MarkDown view
    implementation 'io.noties.markwon:core:4.6.2'

    // Loupe for ImageGallery and zoomable ImageViews
    implementation 'io.github.igreenwood.loupe:loupe:1.2.2'
    //implementation 'io.github.igreenwood.loupe:extensions:1.0.1' //as of now not needed
}

// un-mocking of Android classes that don't depend on the Android device, but are portable Java only, like SparseArray
apply plugin: 'de.mobilej.unmock'

// verify existence of the necessary keys for compilation, instead of waiting for a compile error
project.afterEvaluate{
    preBuild.dependsOn("verifyCgeoKeys")
}

tasks.register('verifyCgeoKeys') {
    group = 'verification'
    description = 'Checks for the existence of keys.xml to successfully compile cgeo.'
    doFirst {
        def keysFile = file("res/values/keys.xml")
        if (!keysFile.exists()) {
            // copy keys from private.properties to keys.xml. used by the CI server at least
            def propertiesFile = rootProject.file("private.properties")
            if (propertiesFile.exists()) {
                copy {
                    from "templates/keys.xml"
                    into ("res/values")
                    def properties = new Properties()
                    propertiesFile.withInputStream {
                        properties.load(it)
                    }
                    filter(ReplaceTokens, tokens: properties)
                    filter { it.replaceAll("@.+?@", "") }
                }
            }
        }
        if (!keysFile.exists()) {
            throw new InvalidUserDataException("You must provide API keys for c:geo to compile successfully. Please read the 'API keys' section in the README.md file for further details.")
        }
    }
}

// version number from the current date, plus an offset defined by the build type (to define which versions overwrite each other)
static def versionCodeFromDate(offset) {
    def date = new Date()
    def formattedDate = date.format('yyyyMMdd')
    return Integer.valueOf(formattedDate) + offset
}

// version name based on current date
static def versionNameFromDate() {
    def date = new Date()
    def formattedDate = date.format('yyyy.MM.dd')
    return formattedDate
}

// get the most recent git commit ID in long and short form
class GitCommit {
    static String commitId

    static String current() {
        if (commitId == null) {
            Process p = ['git', 'rev-parse', 'HEAD'].execute()
            if (p.waitFor() != 0) {
                throw new Error("Unable to get git commit id: " + p.err.text)
            }
            commitId = p.text.trim()
        }
        return commitId
    }

    static String currentShort() {
        return current().substring(0, 7)
    }
}

// check whether this is a local build or a CI server build
static def isContinuousIntegrationServer() {
    return System.getenv('BUILD_NUMBER') != null
}

// have a run task for our builds to launch the app directly from gradle
android.applicationVariants.all { variant ->
    if (variant.installProvider) {
        tasks.register("run${variant.name.capitalize()}") {
            group 'cgeo'
            description "Installs the ${variant.description} and runs the main activity. Depends on 'adb' being on the PATH."
            dependsOn tasks.named(variant.installProvider.name)

            doFirst {
                def classpath = variant.applicationId
                if (variant.buildType.applicationIdSuffix) {
                    classpath -= "${variant.buildType.applicationIdSuffix}"
                }
                def launchClass = "${variant.applicationId}/${classpath}.MainActivity"
                try {
                    project.exec {
                        executable = project.android.getAdbExe().toString()
                        args = ['shell', 'am', 'start', '-n', launchClass]
                    }
                }
                catch (RuntimeException e) {
                    throw new IllegalStateException("Cannot execute 'adb'. Please add %ANDROID_HOME%\\platform-tools to the PATH environment variable and restart your IDE", e)
                }
            }
        }

    }
}

// run device and non device tests together with one task. also fixes the bug that gradle optimizes tests away in repeated runs
// This uses eager task creation API.
tasks.create('testDebug') {
    group 'verification'
    description "Tests the debug build both with device-dependent and device-independent tests."

    dependsOn 'testBasicDebugUnitTest', 'connectedBasicDebugAndroidTest'
}

/*
 * signing of release APK, use a properties file like in templates/private.properties
 */
// dynamically load the signing values from private.properties
File privatePropertiesFile = rootProject.file('private.properties')
if (privatePropertiesFile.exists()) {
    Properties properties = new Properties()
    properties.load(new FileInputStream(privatePropertiesFile))
    android.signingConfigs {
        release {
            storeFile file(properties.getProperty('key.store'))
            storePassword properties.getProperty('key.store.password')
            keyAlias properties.getProperty('key.alias')
            keyPassword properties.getProperty('key.alias.password')
        }
    }
    android.buildTypes.release.signingConfig android.signingConfigs.release
}

// check existence of private properties, show an error message
tasks.register('verifyPrivateProperties') {
    doLast {
        if (!rootProject.file('private.properties').exists()) {
            throw new InvalidUserDataException("For signing the release build you must provide a file private.properties in the root directory. Copy templates/private.properties and change the values.")
        }
    }
}

// copy preferences containing user and password to the device
tasks.register('copyDefaultPreferencesToAndroid') {
    dependsOn 'installBasicDebug'
    doFirst {
        def preferences = file('cgeo.geocaching_preferences.xml')
        if (preferences.exists()) {
            try {
                project.exec {
                    executable = project.android.getAdbExe().toString()
                    args = ['push', 'cgeo.geocaching_preferences.xml', '/data/local/tmp/cgeo.geocaching_preferences.xml']
                }
                project.exec {
                    executable = project.android.getAdbExe().toString()
                    args = ['shell', 'run-as', 'cgeo.geocaching', 'mkdir', '/data/data/cgeo.geocaching/shared_prefs/']
                }
                project.exec {
                    executable = project.android.getAdbExe().toString()
                    args = ['shell', 'run-as', 'cgeo.geocaching', 'cp', '/data/local/tmp/cgeo.geocaching_preferences.xml', '/data/data/cgeo.geocaching/shared_prefs/cgeo.geocaching_preferences.xml']
                }
                project.exec {
                    executable = project.android.getAdbExe().toString()
                    args = ['shell', 'run-as', 'cgeo.geocaching', 'ls', '-l', '/data/data/cgeo.geocaching/shared_prefs/']
                }
                project.exec {
                    executable = project.android.getAdbExe().toString()
                    args = ['shell', 'getprop', 'ro.build.version.release']
                }
            }
            // we might not actually have permission to copy the preferences on actual devices, let's continue running the app then
            catch (RuntimeException e) {
                print(e.message)
            }
        }
    }
}

tasks.whenTaskAdded { theTask ->
    // only verify the existence of private.properties, when the file is really needed
    if (theTask.name == "packageRelease") {
        theTask.dependsOn "verifyPrivateProperties"
    }
    // copy default preferences before starting the app
    if (theTask.name == "runBasicDebug" || theTask.name == "connectedBasicDebugAndroidTest") {
        theTask.dependsOn "copyDefaultPreferencesToAndroid"
    }
}

/*
 * own checkstyle configuration
 * Android plugin doesn't interoperate with the Checkstyle plugin
 */
apply plugin: 'checkstyle'

checkstyle {
    // assign the checkstyle version explicitly here
    // and in AndroidStudio Settings (.idea/checkstyle-idea.xml)
    // and align it with codacy (https://github.com/codacy/codacy-checkstyle)
    toolVersion = '8.44'

    configDirectory = rootProject.projectDir
    configFile = rootProject.file("checkstyle.xml")
}

tasks.register('checkstyle', Checkstyle) {
    group 'verification'
    description 'Check code standard'

    source 'src'
    source '../tests/src'
    source '../tests/src-android'
    include '**/*.java'

    classpath = files()
}

tasks.named('check') {
    mustRunAfter tasks.named('checkstyle')
}

<MSG> releng: use latest support annotations

<DFF> @@ -235,8 +235,9 @@ dependencies {
     // Android Studio recommended test runner, see https://developer.android.com/tools/testing-support-library/index.html#setup
     androidTestCompile 'com.android.support.test:runner:0.4.1'
 
-    // TODO: this line is only needed to enforce the same version of the support annotations for the main app and the test app. it can be removed when upgrading the support library in our app
-    compile 'com.android.support:support-annotations:23.0.1'
+    // enforce same version of the support annotations for the main app and the test app
+    compile 'com.android.support:support-annotations:23.1.1'
+    androidTestCompile 'com.android.support:support-annotations:23.1.1'
 
     // Junit only needed for local unit tests
     testCompile 'junit:junit:4.12'

releng: use latest support annotations