plugins { id 'com.android.application' } final COMPILE_WITH_DEPRECATION_LINT = false // Load signing config only if needed def signingEnabled = gradle.startParameter.taskNames.any { it.toLowerCase().contains("signedrelease") } def props = loadSigningConfig(signingEnabled) android { namespace 'fr.ralala.hexviewer' compileSdk = 36 defaultConfig { applicationId "fr.ralala.hexviewer" minSdk 23 //noinspection OldTargetApi targetSdk 35 // F-Droid seems not to appreciate the use of variables versionCode 15909 versionName '1.59.9' vectorDrawables { useSupportLibrary true } } buildFeatures { buildConfig = true viewBinding = true } compileOptions { sourceCompatibility JavaVersion.VERSION_17 targetCompatibility JavaVersion.VERSION_17 coreLibraryDesugaringEnabled true } signingConfigs { github { if (signingEnabled) { storeFile rootProject.file(props['storeFile'].trim()) storePassword props['storePassword'].trim() keyAlias props['keyAlias'].trim() keyPassword props['keyPassword'].trim() v1SigningEnabled true v2SigningEnabled true enableV4Signing true } } } buildTypes { release { minifyEnabled true shrinkResources true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } debug { // to debug ProGuard rules minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } signedRelease { initWith release matchingFallbacks = ['release'] if (signingEnabled) { signingConfig signingConfigs.github } } } lint { abortOnError false } } dependencies { implementation 'org.apache.commons:commons-collections4:4.5.0' implementation "androidx.appcompat:appcompat:1.7.1" implementation "androidx.preference:preference:1.2.1" implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.2.0" implementation "androidx.emoji2:emoji2:1.6.0" implementation "androidx.documentfile:documentfile:1.1.0" implementation "androidx.emoji2:emoji2-bundled:1.6.0" implementation "com.google.android.material:material:1.14.0" coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.5' testImplementation "junit:junit:4.13.2" } if(COMPILE_WITH_DEPRECATION_LINT) { tasks.withType(JavaCompile).configureEach { options.compilerArgs += ["-Xlint:deprecation", "-Xlint:unchecked"] } } /* Tasks */ tasks.withType(Test).configureEach { testTask -> testLogging { events "passed", "skipped", "failed" exceptionFormat "full" showStandardStreams = true } def totalDuration = 0L def list = new ArrayList() doLast { logger.lifecycle("Tests finished.") } addTestListener(new TestListener() { @Override void beforeSuite(TestDescriptor desc) {} @Override void beforeTest(TestDescriptor descriptor) {} @Override void afterTest(TestDescriptor descriptor, TestResult result) { long duration = result.endTime - result.startTime list << "Test ${descriptor.name} took ${duration} ms" totalDuration += duration } @Override void afterSuite(TestDescriptor desc, TestResult result) { if (!desc.parent) { // root suite logger.lifecycle("") list.each { li -> logger.lifecycle(li) } logger.lifecycle("Test summary: ${result.testCount} tests, ${result.successfulTestCount} succeeded, ${result.failedTestCount} failed, ${result.skippedTestCount} skipped") logger.lifecycle("Total time: ${totalDuration} ms") } } }) } // versionCode <-> versionName ///////////////////////////////////////////////////////////////////// // I got the idea (code) below from the repository https://github.com/sal0max/currencie /** * Checks if versionCode and versionName match. * Needed because of F-Droid: both have to be hard-coded and can't be assigned dynamically. * So at least check during build for them to match. */ tasks.register('checkVersion') { int versionCode = android.defaultConfig.versionCode int correctVersionCode = generateVersionCode(android.defaultConfig.versionName) if (versionCode != correctVersionCode) throw new GradleException( "versionCode and versionName don't match: " + "versionCode should be $correctVersionCode. Is $versionCode." ) } assemble.dependsOn checkVersion /** * Checks if a fastlane changelog for the current version is present. */ tasks.register('checkFastlaneChangelog') { int versionCode = android.defaultConfig.versionCode File changelogFile = file("$rootDir/fastlane/metadata/android/en-US/changelogs/${versionCode}.txt") if (!changelogFile.exists()) throw new GradleException( "Fastlane changelog missing: expecting file '$changelogFile'" ) } build.dependsOn checkFastlaneChangelog /* functions */ private Properties loadSigningConfig(boolean signingEnabled) { if (signingEnabled) { def props = new Properties() def propsFile = rootProject.file("keystore.properties") if (!propsFile.exists()) { throw new GradleException("Missing 'keystore.properties' file.") } propsFile.withInputStream { props.load(it) } def requiredKeys = ['storeFile', 'storePassword', 'keyAlias', 'keyPassword'] requiredKeys.each { if (!props.containsKey(it) || props[it].trim().isEmpty()) { throw new GradleException("Missing or empty property: '${it}' in 'keystore.properties'.") } } def keystorePath = rootProject.file(props['storeFile'].trim()) if (!keystorePath.exists()) { throw new GradleException("Keystore file not found at: ${keystorePath}") } return props } return null } /** * Generates a versionCode based on the given semVer String. * @param semVer e.g. 1.27 * @return e.g. 127 (-> 1 27) * * 1.58 -> 158 * 1.58.0 -> 15800 * 1.0.0 -> 10000 */ private static int generateVersionCode(String semVer) { def parts = semVer.tokenize('.').collect { it.toInteger() } parts.inject(0) { code, part -> code * 100 + part } }