2
0
mirror of https://github.com/KDE/kdeconnect-android synced 2025-08-22 09:58:08 +00:00

Migrate build configuration to kotlin

Migrate build logic to kotlin including use of version catalog
This commit is contained in:
Erik Duisters 2023-08-08 08:01:35 +00:00 committed by Albert Vaca Cintora
parent c5c780b5ce
commit b3b538ff31
6 changed files with 332 additions and 231 deletions

1
.gitignore vendored
View File

@ -7,7 +7,6 @@ bin/
build/
target/
classes/
gradle
*.iml
*.keystore
!debug.keystore

View File

@ -1,227 +0,0 @@
import com.github.jk1.license.render.TextReportRenderer
buildscript {
ext.kotlin_version = '1.8.22'
dependencies {
classpath 'com.android.tools.build:gradle:8.1.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
plugins {
id 'com.github.jk1.dependency-license-report' version '1.16'
}
def licenseResDir = new File("$projectDir/build/dependency-license-res")
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
/**
* This is a special on-demand Gradle object.
*
* Its value will not be determined until someone calls one of the gitHashProvider.getXXX() methods.
*
* If it does not encounter an explicit 'return' statement, getHashProvider.isPresent() will return false.
*/
Provider<String> gitHashProvider = project.provider {
Process gitCommand = null
try {
// This invokes 'git' immediately, but does not wait for it to finish
gitCommand = 'git rev-parse --short HEAD'.execute([], project.rootDir)
} catch (IOException ignored) {
}
if (gitCommand == null) {
logger.warn("Could not make use of the 'git' command-line tool. Output filenames will not be customized.")
} else if (gitCommand.waitFor() == 0) {
// This call to '::getText' (using the 'text' Groovy accessor syntax) collects the
// output stream
return '-' + gitCommand.text.trim()
} else {
logger.warn("Could not determine which commit is currently checked out -" +
" did you download this code without the .git directory?"
)
}
}
android {
namespace 'org.kde.kdeconnect_tp'
compileSdk 33
defaultConfig {
minSdkVersion 21
targetSdkVersion 32
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
buildFeatures {
viewBinding true
compose true
}
composeOptions {
kotlinCompilerExtensionVersion = "1.4.8"
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
// Flag to enable support for the new language APIs
coreLibraryDesugaringEnabled true
}
kotlinOptions {
jvmTarget = '1.8'
}
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src']
resources.srcDirs = ['resources']
res.srcDirs = [licenseResDir, 'res']
assets.srcDirs = ['assets']
}
test {
java.srcDirs = ['tests']
}
}
packagingOptions {
resources {
merges += ['META-INF/DEPENDENCIES', 'META-INF/LICENSE', 'META-INF/NOTICE']
}
}
signingConfigs {
debug {
storeFile file("debug.keystore")
storePassword 'android'
keyAlias 'androiddebugkey'
keyPassword 'android'
}
}
buildTypes {
debug {
minifyEnabled true
shrinkResources true
signingConfig signingConfigs.debug
}
// keep minifyEnabled false above for faster builds; set to 'true'
// when testing to make sure ProGuard/R8 is not deleting important stuff
release {
minifyEnabled true
shrinkResources true
}
}
lint {
abortOnError false
checkReleaseBuilds false
}
testOptions {
unitTests.all {
jvmArgs += [
"--add-opens", "java.base/java.lang=ALL-UNNAMED",
"--add-opens", "java.base/java.security=ALL-UNNAMED",
"--add-opens", "java.base/sun.security.rsa=ALL-UNNAMED",
"--add-opens", "java.base/sun.security.x509=ALL-UNNAMED",
"--add-opens", "java.base/java.util=ALL-UNNAMED",
"--add-opens", "java.base/java.lang.reflect=ALL-UNNAMED"
]
}
}
applicationVariants.configureEach { variant ->
logger.quiet("Found a variant called ${variant.name}")
if (variant.buildType.debuggable) {
variant.outputs.each { output ->
if (output.outputFile.name.endsWith(".apk")) {
// Default output filename is "${project.name}-${v.name}.apk". We want
// the Git commit short-hash to be added onto that default filename.
def newName = "${project.name}-${variant.name}${gitHashProvider.getOrElse("")}.apk"
logger.quiet(" Found an output file ${output.outputFile.name}, renaming to ${newName}")
output.outputFileName = newName
}
}
}
}
}
ext {
coroutines_version = '1.7.1'
}
dependencies {
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3'
implementation 'androidx.compose.material3:material3:1.1.1'
implementation 'androidx.compose.ui:ui-tooling-preview:1.4.3'
implementation 'androidx.activity:activity-compose:1.7.2'
implementation 'com.google.accompanist:accompanist-themeadapter-material3:0.31.0-alpha'
implementation 'androidx.constraintlayout:constraintlayout-compose:1.0.1'
implementation 'androidx.compose.ui:ui-tooling-preview:1.4.3'
debugImplementation 'androidx.compose.ui:ui-tooling:1.4.3'
implementation 'androidx.media:media:1.6.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'androidx.core:core-ktx:1.10.1'
implementation 'androidx.preference:preference-ktx:1.2.0'
implementation 'androidx.recyclerview:recyclerview:1.3.1'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
implementation 'androidx.documentfile:documentfile:1.0.1'
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1"
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.1'
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
implementation 'androidx.lifecycle:lifecycle-common-java8:2.6.1'
implementation 'androidx.gridlayout:gridlayout:1.0.0'
implementation 'com.google.android.material:material:1.9.0'
implementation 'com.jakewharton:disklrucache:2.0.2' //For caching album art bitmaps
implementation 'org.apache.sshd:sshd-core:0.14.0'
implementation 'org.apache.mina:mina-core:2.0.19' //For some reason, makes sshd-core:0.14.0 work without NIO, which isn't available until Android 8 (api 26)
//implementation('com.github.bright:slf4android:0.1.6') { transitive = true } // For org.apache.sshd debugging
implementation 'org.bouncycastle:bcpkix-jdk15on:1.70' //For SSL certificate generation
implementation 'org.atteo.classindex:classindex:3.13'
annotationProcessor 'org.atteo.classindex:classindex:3.13'
// The android-smsmms library is the only way I know to handle MMS in Android
// (Shouldn't a phone OS make phone things easy?)
// This library was originally authored as com.klinkerapps at https://github.com/klinker41/android-smsmms.
// However, that version is under-loved. I have therefore made "some fixes" and published it.
// Please see https://invent.kde.org/sredman/android-smsmms/-/tree/master
implementation 'org.kde.invent.sredman:android-smsmms:kdeconnect-1-21-0'
implementation 'com.klinkerapps:logger:1.0.3'
implementation 'commons-io:commons-io:2.11.0'
implementation 'org.apache.commons:commons-collections4:4.4'
implementation 'org.apache.commons:commons-lang3:3.12.0'
implementation 'com.univocity:univocity-parsers:2.9.1'
// Kotlin
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
// Testing
testImplementation 'junit:junit:4.13.2'
testImplementation 'org.powermock:powermock-core:2.0.0'
testImplementation 'org.powermock:powermock-module-junit4:2.0.0'
testImplementation 'org.powermock:powermock-api-mockito2:2.0.0'
testImplementation 'org.mockito:mockito-core:3.12.4' // powermock isn't compatible with mockito 4
testImplementation 'org.skyscreamer:jsonassert:1.5.1'
// For device controls
implementation 'org.reactivestreams:reactive-streams:1.0.4'
implementation 'io.reactivex.rxjava2:rxjava:2.2.21'
}
licenseReport {
configurations = ALL
renderers = [new TextReportRenderer()]
}
generateLicenseReport.doLast {
def target = new File(licenseResDir, "raw/license")
target.parentFile.mkdirs()
target.text =
files("COPYING", "$projectDir/build/reports/dependency-license/THIRD-PARTY-NOTICES.txt")
.collect { it.getText() }.join('\n')
}
preBuild.dependsOn(generateLicenseReport)

238
build.gradle.kts Normal file
View File

@ -0,0 +1,238 @@
import com.github.jk1.license.LicenseReportExtension
import com.github.jk1.license.render.ReportRenderer
import com.github.jk1.license.render.TextReportRenderer
buildscript {
dependencies {
classpath(libs.android.gradlePlugin)
classpath(libs.kotlin.gradlePlugin)
}
}
@Suppress("DSL_SCOPE_VIOLATION") // TODO: remove once https://youtrack.jetbrains.com/issue/KTIJ-19369 is fixed
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.dependencyLicenseReport)
}
val licenseResDir = File("$projectDir/build/dependency-license-res")
fun String.runCommand(
workingDir: File = File("."),
timeoutAmount: Long = 60,
timeoutUnit: TimeUnit = TimeUnit.SECONDS
): String = ProcessBuilder(split("\\s(?=(?:[^'\"`]*(['\"`])[^'\"`]*\\1)*[^'\"`]*$)".toRegex()))
.directory(workingDir)
.redirectOutput(ProcessBuilder.Redirect.PIPE)
.redirectError(ProcessBuilder.Redirect.PIPE)
.start()
.apply { waitFor(timeoutAmount, timeoutUnit) }
.run {
val error = errorStream.bufferedReader().readText().trim()
if (error.isNotEmpty()) {
throw Exception(error)
}
inputStream.bufferedReader().readText().trim()
}
android {
namespace = "org.kde.kdeconnect_tp"
compileSdk = 33
defaultConfig {
minSdk = 21
targetSdk = 32
proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")
}
buildFeatures {
viewBinding = true
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion = "1.5.1"
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
// Flag to enable support for the new language APIs
isCoreLibraryDesugaringEnabled = true
}
kotlinOptions {
jvmTarget = "1.8"
}
sourceSets {
getByName("main") {
manifest.srcFile("AndroidManifest.xml")
java.setSrcDirs(listOf("src"))
resources.setSrcDirs(listOf("resources"))
res.setSrcDirs(listOf(licenseResDir, "res"))
assets.setSrcDirs(listOf("assets"))
}
getByName("test") {
java.setSrcDirs(listOf("tests"))
}
}
packaging {
resources {
merges += listOf("META-INF/DEPENDENCIES", "META-INF/LICENSE", "META-INF/NOTICE")
}
}
signingConfigs {
getByName("debug") {
storeFile = file("debug.keystore")
storePassword = "android"
keyAlias = "androiddebugkey"
keyPassword = "android"
}
}
buildTypes {
getByName("debug") {
isMinifyEnabled = true
isShrinkResources = true
signingConfig = signingConfigs.getByName("debug")
}
// keep minifyEnabled false above for faster builds; set to 'true'
// when testing to make sure ProGuard/R8 is not deleting important stuff
getByName("release") {
isMinifyEnabled = true
isShrinkResources = true
}
}
lint {
abortOnError = false
checkReleaseBuilds = false
}
testOptions {
unitTests.all {
it.jvmArgs = it.jvmArgs.orEmpty() + listOf(
"--add-opens=java.base/java.lang=ALL-UNNAMED",
"--add-opens=java.base/java.security=ALL-UNNAMED",
"--add-opens=java.base/sun.security.rsa=ALL-UNNAMED",
"--add-opens=java.base/sun.security.x509=ALL-UNNAMED",
"--add-opens=java.base/java.util=ALL-UNNAMED",
"--add-opens=java.base/java.lang.reflect=ALL-UNNAMED"
)
}
}
applicationVariants.all {
val variant = this
logger.quiet("Found a variant called ${variant.name}")
if (variant.buildType.isDebuggable) {
variant.outputs.all {
val output = this as com.android.build.gradle.internal.api.BaseVariantOutputImpl
if (output.outputFile.name.endsWith(".apk")) {
// Default output filename is "${project.name}-${v.name}.apk". We want
// the Git commit short-hash to be added onto that default filename.
try {
val hash = "git rev-parse --short HEAD".runCommand(workingDir = rootDir)
val newName = "${project.name}-${variant.name}-${hash}.apk"
logger.quiet(" Found an output file ${output.outputFile.name}, renaming to ${newName}")
output.outputFileName = newName
} catch (ignored: Exception) {
logger.warn("Could not make use of the 'git' command-line tool. Output filenames will not be customized.")
}
}
}
}
}
}
dependencies {
coreLibraryDesugaring(libs.android.desugarJdkLibs)
implementation(libs.androidx.compose.material3)
implementation(libs.androidx.compose.ui.tooling.preview)
implementation(libs.androidx.activity.compose)
implementation(libs.accompanist.themeadapter.material3)
implementation(libs.androidx.constraintlayout.compose)
implementation(libs.androidx.compose.ui.tooling.preview)
debugImplementation(libs.androidx.compose.ui.tooling)
implementation(libs.androidx.media)
implementation(libs.androidx.appcompat)
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.preference.ktx)
implementation(libs.androidx.recyclerview)
implementation(libs.androidx.swiperefreshlayout)
implementation(libs.androidx.documentfile)
implementation(libs.androidx.lifecycle.viewmodel.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.lifecycle.extensions)
implementation(libs.androidx.lifecycle.common.java8)
implementation(libs.androidx.gridlayout)
implementation(libs.material)
implementation(libs.disklrucache) //For caching album art bitmaps
implementation(libs.apache.sshd.core)
implementation(libs.apache.mina.core) //For some reason, makes sshd-core:0.14.0 work without NIO, which isn't available until Android 8 (api 26)
//implementation("com.github.bright:slf4android:0.1.6") { transitive = true } // For org.apache.sshd debugging
implementation(libs.bcpkix.jdk15on) //For SSL certificate generation
implementation(libs.classindex)
annotationProcessor(libs.classindex)
// The android-smsmms library is the only way I know to handle MMS in Android
// (Shouldn't a phone OS make phone things easy?)
// This library was originally authored as com.klinkerapps at https://github.com/klinker41/android-smsmms.
// However, that version is under-loved. I have therefore made "some fixes" and published it.
// Please see https://invent.kde.org/sredman/android-smsmms/-/tree/master
implementation(libs.android.smsmms)
implementation(libs.logger)
implementation(libs.commons.io)
implementation(libs.commons.collections4)
implementation(libs.commons.lang3)
implementation(libs.univocity.parsers)
// Kotlin
implementation(libs.kotlin.stdlib.jdk8)
implementation(libs.kotlinx.coroutines.core)
implementation(libs.kotlinx.coroutines.android)
// Testing
testImplementation(libs.junit)
testImplementation(libs.powermock.core)
testImplementation(libs.powermock.module.junit4)
testImplementation(libs.powermock.api.mockito2)
testImplementation(libs.mockito.core) // powermock isn't compatible with mockito 4
testImplementation(libs.jsonassert)
// For device controls
implementation(libs.reactive.streams)
implementation(libs.rxjava)
}
licenseReport {
configurations = LicenseReportExtension.ALL
renderers = arrayOf<ReportRenderer>(TextReportRenderer())
}
tasks.named("generateLicenseReport") {
doLast {
val target = File(licenseResDir, "raw/license")
target.parentFile.mkdirs()
target.writeText(
files(
layout.projectDirectory.file("COPYING"),
layout.buildDirectory.file("reports/dependency-license/THIRD-PARTY-NOTICES.txt")
).joinToString(separator = "\n") {
it.readText()
}
)
}
}
tasks.named("preBuild") {
dependsOn("generateLicenseReport")
}

91
gradle/libs.versions.toml Normal file
View File

@ -0,0 +1,91 @@
[versions]
accompanistThemeadapterMaterial3 = "0.31.0-alpha"
activityCompose = "1.7.2"
androidDesugarJdkLibs = "2.0.3"
androidGradlePlugin = "8.1.0"
androidSmsmms = "kdeconnect-1-21-0"
appcompat = "1.6.1"
bcpkixJdk15on = "1.70"
classindex = "3.13"
commonsCollections4 = "4.4"
commonsIo = "2.11.0"
commonsLang3 = "3.12.0"
constraintlayoutCompose = "1.0.1"
coreKtx = "1.10.1"
disklrucache = "2.0.2"
documentfile = "1.0.1"
gradle = "8.1.0"
gridlayout = "1.0.0"
jsonassert = "1.5.1"
junit = "4.13.2"
dependencyLicenseReport = "1.16"
kotlin = "1.9.0"
kotlinxCoroutinesCore = "1.7.1"
lifecycleExtensions = "2.2.0"
lifecycleRuntimeKtx = "2.6.1"
logger = "1.0.3"
material = "1.9.0"
material3 = "1.1.1"
media = "1.6.0"
minaCore = "2.0.19"
mockitoCore = "3.12.4"
powermockModuleJunit4 = "2.0.0"
preferenceKtx = "1.2.0"
reactiveStreams = "1.0.4"
recyclerview = "1.3.1"
rxjava = "2.2.21"
sshdCore = "0.14.0"
swiperefreshlayout = "1.1.0"
uiToolingPreview = "1.4.3"
univocityParsers = "2.9.1"
[libraries]
accompanist-themeadapter-material3 = { module = "com.google.accompanist:accompanist-themeadapter-material3", version.ref = "accompanistThemeadapterMaterial3" }
android-desugarJdkLibs = { module = "com.android.tools:desugar_jdk_libs", version.ref = "androidDesugarJdkLibs" }
android-smsmms = { module = "org.kde.invent.sredman:android-smsmms", version.ref = "androidSmsmms" }
androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "activityCompose" }
androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompat" }
androidx-compose-material3 = { module = "androidx.compose.material3:material3", version.ref = "material3" }
androidx-compose-ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview", version.ref = "uiToolingPreview" }
androidx-constraintlayout-compose = { module = "androidx.constraintlayout:constraintlayout-compose", version.ref = "constraintlayoutCompose" }
androidx-compose-ui-tooling = { module = "androidx.compose.ui:ui-tooling", version.ref = "uiToolingPreview" }
androidx-core-ktx = { module = "androidx.core:core-ktx", version.ref = "coreKtx" }
androidx-documentfile = { module = "androidx.documentfile:documentfile", version.ref = "documentfile" }
androidx-gridlayout = { module = "androidx.gridlayout:gridlayout", version.ref = "gridlayout" }
androidx-lifecycle-common-java8 = { module = "androidx.lifecycle:lifecycle-common-java8", version.ref = "lifecycleRuntimeKtx" }
androidx-lifecycle-extensions = { module = "androidx.lifecycle:lifecycle-extensions", version.ref = "lifecycleExtensions" }
androidx-lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" }
androidx-lifecycle-viewmodel-ktx = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "lifecycleRuntimeKtx" }
androidx-media = { module = "androidx.media:media", version.ref = "media" }
androidx-preference-ktx = { module = "androidx.preference:preference-ktx", version.ref = "preferenceKtx" }
androidx-recyclerview = { module = "androidx.recyclerview:recyclerview", version.ref = "recyclerview" }
androidx-swiperefreshlayout = { module = "androidx.swiperefreshlayout:swiperefreshlayout", version.ref = "swiperefreshlayout" }
bcpkix-jdk15on = { module = "org.bouncycastle:bcpkix-jdk15on", version.ref = "bcpkixJdk15on" }
classindex = { module = "org.atteo.classindex:classindex", version.ref = "classindex" }
commons-collections4 = { module = "org.apache.commons:commons-collections4", version.ref = "commonsCollections4" }
commons-io = { module = "commons-io:commons-io", version.ref = "commonsIo" }
commons-lang3 = { module = "org.apache.commons:commons-lang3", version.ref = "commonsLang3" }
disklrucache = { module = "com.jakewharton:disklrucache", version.ref = "disklrucache" }
android-gradlePlugin = { module = "com.android.tools.build:gradle", version.ref = "gradle" }
jsonassert = { module = "org.skyscreamer:jsonassert", version.ref = "jsonassert" }
junit = { module = "junit:junit", version.ref = "junit" }
kotlin-gradlePlugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
kotlin-stdlib-jdk8 = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk8", version.ref = "kotlin" }
kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinxCoroutinesCore" }
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinxCoroutinesCore" }
logger = { module = "com.klinkerapps:logger", version.ref = "logger" }
material = { module = "com.google.android.material:material", version.ref = "material" }
apache-mina-core = { module = "org.apache.mina:mina-core", version.ref = "minaCore" }
apache-sshd-core = { module = "org.apache.sshd:sshd-core", version.ref = "sshdCore" }
mockito-core = { module = "org.mockito:mockito-core", version.ref = "mockitoCore" }
powermock-api-mockito2 = { module = "org.powermock:powermock-api-mockito2", version.ref = "powermockModuleJunit4" }
powermock-core = { module = "org.powermock:powermock-core", version.ref = "powermockModuleJunit4" }
powermock-module-junit4 = { module = "org.powermock:powermock-module-junit4", version.ref = "powermockModuleJunit4" }
reactive-streams = { module = "org.reactivestreams:reactive-streams", version.ref = "reactiveStreams" }
rxjava = { module = "io.reactivex.rxjava2:rxjava", version.ref = "rxjava" }
univocity-parsers = { module = "com.univocity:univocity-parsers", version.ref = "univocityParsers" }
[plugins]
android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" }
kotlin-android = { id ="org.jetbrains.kotlin.android", version.ref = "kotlin" }
dependencyLicenseReport = { id = "com.github.jk1.dependency-license-report", version.ref = "dependencyLicenseReport" }

2
proguard-rules.pro vendored
View File

@ -2,7 +2,7 @@
# By default, the flags in this file are appended to flags specified
# in {SDKHOME}/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
# directive in build.gradle.kts.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

View File

@ -5,7 +5,7 @@ pluginManagement {
mavenCentral()
/* Needed for org.apache.sshd debugging
maven {
url "https://jitpack.io"
url = uri("https://jitpack.io")
}
*/
}
@ -16,7 +16,7 @@ dependencyResolutionManagement {
google()
mavenCentral()
maven {
url = "https://jitpack.io"
url = uri("https://jitpack.io")
}
}
}