<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
    productFlavors {
        // make sure to not have any flavour lexicographically smaller than "basic". Android Studio takes the first alphabetical flavor in new installations.
        basic {
            dimension "javaCompilerTime"
            buildConfigField "String", "SPECIAL_BUILD", '""'
        }

        nojit {
            dimension "javaCompilerTime"
            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'

    implementation "com.squareup.leakcanary:plumber-android:$leakCanaryVersion"

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

    // Mapsforge new version
    def mapsforgeVersion = '0.14.0'
    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> Bump locus-api-android from 0.9.21 to 0.9.22

Bumps [locus-api-android](https://github.com/asamm/locus-api-android) from 0.9.21 to 0.9.22.
- [Release notes](https://github.com/asamm/locus-api-android/releases)
- [Commits](https://github.com/asamm/locus-api-android/commits)

Signed-off-by: dependabot[bot] <5bdcd3c0d4d24ae3e71b3b452a024c6324c7e4bb@github.com>
<DFF> @@ -300,7 +300,7 @@ dependencies {
     implementation "com.squareup.leakcanary:plumber-android:$leakCanaryVersion"
 
     // Locus Maps integration
-    implementation "com.asamm:locus-api-android:0.9.21"
+    implementation "com.asamm:locus-api-android:0.9.22"
 
     // Mapsforge new version
     def mapsforgeVersion = '0.14.0'

Bump locus-api-android from 0.9.21 to 0.9.22