diff --git a/.editorconfig b/.editorconfig index 2a368a4..fa68660 100644 --- a/.editorconfig +++ b/.editorconfig @@ -42,3 +42,4 @@ ij_kotlin_wrap_expression_body_functions = 1 indent_style = space indent_size = 4 trim_trailing_whitespace = false +max_line_length = 80 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1acdd1c..98f4081 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -15,19 +15,28 @@ jobs: name: "Validation" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: gradle/wrapper-validation-action@v1 + - uses: actions/checkout@v4 + - uses: gradle/actions/wrapper-validation@v3 build: needs: [validation] runs-on: macOS-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 + with: + distribution: 'zulu' + java-version: '17' + cache: 'gradle' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 - - name: Set up JDK 1.8 - uses: actions/setup-java@v1 + - name: konan cache + uses: actions/cache@v4 with: - java-version: 1.8 + path: ~/.konan + key: ${{ runner.os }}-konan - name: Check run: ./gradlew check @@ -43,9 +52,5 @@ jobs: if: startsWith(github.ref, 'refs/tags/') - name: Upload tag - run: ./gradlew publish --no-daemon --no-parallel -Psigning.secretKeyRingFile=$(echo ~/.gradle/sonatype-appmattus-keys.gpg) - if: startsWith(github.ref, 'refs/tags/') - - - name: Close and release tag - run: ./gradlew closeAndReleaseRepository + run: ./gradlew publishAllPublicationsToMavenCentral -Psigning.secretKeyRingFile=$(echo ~/.gradle/sonatype-appmattus-keys.gpg) if: startsWith(github.ref, 'refs/tags/') diff --git a/.gitignore b/.gitignore index 0cbc28a..dc0db0c 100644 --- a/.gitignore +++ b/.gitignore @@ -300,3 +300,5 @@ fabric.properties !swiftlint-wrapper.jar # End of https://www.toptal.com/developers/gitignore/api/android,androidstudio,xcode,swift,kotlin + +.kotlin diff --git a/README.md b/README.md index 8e4614d..92ce2db 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,17 @@ distinguish between cellular vs WiFi connection. ![badge][badge-android] ![badge][badge-ios] -[ignore-test](ignore-test/README.md): Annotations to ignore tests from -specific platforms. +[ignore-ios](ignore-ios/README.md): Annotations to ignore iOS tests. +![badge][badge-android] +![badge][badge-ios] +![badge][badge-jvm] + +[ignore-junit](ignore-junit/README.md): Annotations to ignore JUnit 4 tests. +![badge][badge-android] +![badge][badge-ios] +![badge][badge-jvm] + +[ignore-junit5](ignore-junit5/README.md): Annotations to ignore JUnit 5 tests. ![badge][badge-android] ![badge][badge-ios] ![badge][badge-jvm] diff --git a/battery/README.md b/battery/README.md index 70aa1ca..3c5f87c 100644 --- a/battery/README.md +++ b/battery/README.md @@ -17,7 +17,7 @@ commonMain { } ``` -Create an instance of Battery +Create an instance of Battery To create a hash first create a digest with `Digest.create` providing the name of the hash you wish to use, then update with `update` and create the hash with @@ -35,8 +35,6 @@ val hash: ByteArray = digest.digest() digest.digest(byteArray) ``` - - --- Inspired by the Flutter [battery](https://pub.dev/packages/battery) package. diff --git a/battery/build.gradle.kts b/battery/build.gradle.kts index 93ce48d..4bd2436 100644 --- a/battery/build.gradle.kts +++ b/battery/build.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright 2021 Appmattus Limited + * Copyright 2021-2025 Appmattus Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,49 +14,52 @@ * limitations under the License. */ -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile - plugins { - kotlin("multiplatform") id("com.android.library") - id("com.vanniktech.maven.publish") - id("org.jetbrains.dokka") + kotlin("multiplatform") + alias(libs.plugins.gradleMavenPublishPlugin) + alias(libs.plugins.dokkaPlugin) } kotlin { - android() - ios() + androidTarget() - sourceSets { - val commonMain by getting { - dependencies { - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core") { - version { - strictly(Versions.coroutinesNative) - } - } - } + iosX64() + iosArm64() + iosSimulatorArm64() + + listOf( + iosX64(), + iosArm64(), + iosSimulatorArm64() + ).forEach { iosTarget -> + iosTarget.binaries.framework { + baseName = "multiplatformutils-battery" + isStatic = true } - val commonTest by getting - val androidMain by getting { - dependencies { - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:${Versions.coroutines}") - } + } + + // Apply the default hierarchy again. It'll create, for example, the iosMain source set: + applyDefaultHierarchyTemplate() + + sourceSets { + commonMain.dependencies { + implementation(libs.kotlinx.coroutines) } - val androidTest by getting - val iosMain by getting - val iosTest by getting + } + + compilerOptions { + jvmToolchain(11) + freeCompilerArgs.add("-Xexpect-actual-classes") } } android { - compileSdkVersion(30) - sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") + namespace = "com.appmattus.multiplatformutils.battery" + compileSdk = 35 + defaultConfig { - minSdkVersion(21) - targetSdkVersion(30) - versionCode = 1 - versionName = "1.0" + minSdk = 21 } buildTypes { getByName("release") { @@ -65,9 +68,7 @@ android { } compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 } } - -tasks.withType { kotlinOptions.jvmTarget = JavaVersion.VERSION_1_8.toString() } diff --git a/battery/src/androidMain/AndroidManifest.xml b/battery/src/androidMain/AndroidManifest.xml deleted file mode 100644 index b6ea9f4..0000000 --- a/battery/src/androidMain/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/battery/src/androidMain/kotlin/com/appmattus/battery/Battery.kt b/battery/src/androidMain/kotlin/com/appmattus/battery/Battery.kt index 54aa8af..44f37fa 100644 --- a/battery/src/androidMain/kotlin/com/appmattus/battery/Battery.kt +++ b/battery/src/androidMain/kotlin/com/appmattus/battery/Battery.kt @@ -1,5 +1,5 @@ /* - * Copyright 2021 Appmattus Limited + * Copyright 2021-2025 Appmattus Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,12 +18,9 @@ package com.appmattus.battery import android.content.BroadcastReceiver import android.content.Context -import android.content.ContextWrapper import android.content.Intent import android.content.IntentFilter import android.os.BatteryManager -import android.os.Build.VERSION -import android.os.Build.VERSION_CODES import com.appmattus.battery.ChargingStatus.Status.Charging import com.appmattus.battery.ChargingStatus.Status.Discharging import com.appmattus.battery.ChargingStatus.Status.Full @@ -35,18 +32,11 @@ import kotlinx.coroutines.flow.callbackFlow actual class Battery(private val context: Context) { actual val batteryLevel: Int - get() = if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { + get() { val batteryManager = context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager - batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY) - } else { - val intent = ContextWrapper(context) - .registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED))!! - @Suppress("MagicNumber") - (intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) * 100 / - intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)) + return batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY) } - @Suppress("EXPERIMENTAL_API_USAGE") actual val chargingStatus: Flow get() = callbackFlow { val receiver = object : BroadcastReceiver() { diff --git a/battery/src/iosMain/kotlin/com/appmattus/battery/Battery.kt b/battery/src/iosMain/kotlin/com/appmattus/battery/Battery.kt index 30d66c9..b844220 100644 --- a/battery/src/iosMain/kotlin/com/appmattus/battery/Battery.kt +++ b/battery/src/iosMain/kotlin/com/appmattus/battery/Battery.kt @@ -1,5 +1,5 @@ /* - * Copyright 2021 Appmattus Limited + * Copyright 2021-2025 Appmattus Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -41,7 +41,6 @@ actual class Battery { } } - @Suppress("EXPERIMENTAL_API_USAGE") actual val chargingStatus: Flow get() = callbackFlow { UIDevice.currentDevice.batteryMonitoringEnabled = true @@ -63,13 +62,18 @@ actual class Battery { } companion object { + @Suppress("REDUNDANT_ELSE_IN_WHEN", "KotlinRedundantDiagnosticSuppress") private val UIDeviceBatteryState.asChargingStatus - get() = if (NSProcessInfo.processInfo.environment["SIMULATOR_DEVICE_NAME"] != null) ChargingStatus(Full) else when (this) { - UIDeviceBatteryState.UIDeviceBatteryStateCharging -> ChargingStatus(Charging) - UIDeviceBatteryState.UIDeviceBatteryStateFull -> ChargingStatus(Full) - UIDeviceBatteryState.UIDeviceBatteryStateUnplugged -> ChargingStatus(Discharging) - UIDeviceBatteryState.UIDeviceBatteryStateUnknown -> ChargingStatus(Unavailable) - else -> ChargingStatus(Unavailable) + get() = if (NSProcessInfo.processInfo.environment["SIMULATOR_DEVICE_NAME"] != null) { + ChargingStatus(Full) + } else { + when (this) { + UIDeviceBatteryState.UIDeviceBatteryStateCharging -> ChargingStatus(Charging) + UIDeviceBatteryState.UIDeviceBatteryStateFull -> ChargingStatus(Full) + UIDeviceBatteryState.UIDeviceBatteryStateUnplugged -> ChargingStatus(Discharging) + UIDeviceBatteryState.UIDeviceBatteryStateUnknown -> ChargingStatus(Unavailable) + else -> ChargingStatus(Unavailable) + } } private const val BATTERY_MAX_VALUE = 100 diff --git a/build.gradle.kts b/build.gradle.kts index a60166f..051f4d2 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright 2021 Appmattus Limited + * Copyright 2021-2025 Appmattus Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,12 +15,13 @@ */ import io.gitlab.arturbosch.detekt.Detekt +import java.time.ZonedDateTime plugins { - id("io.gitlab.arturbosch.detekt") version Versions.detektGradlePlugin - id("com.appmattus.markdown") version Versions.markdownlintGradlePlugin - id("com.vanniktech.maven.publish") version Versions.gradleMavenPublishPlugin apply false - id("org.jetbrains.dokka") version Versions.dokkaPlugin + alias(libs.plugins.detektGradlePlugin) + alias(libs.plugins.markdownlintGradlePlugin) + alias(libs.plugins.gradleMavenPublishPlugin) apply false + alias(libs.plugins.dokkaPlugin) } buildscript { @@ -30,10 +31,10 @@ buildscript { mavenCentral() } dependencies { - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${Versions.kotlin}") - classpath("com.android.tools.build:gradle:${Versions.androidGradlePlugin}") - classpath("com.google.dagger:hilt-android-gradle-plugin:${Versions.Google.dagger}") - classpath("androidx.navigation:navigation-safe-args-gradle-plugin:${Versions.AndroidX.navigation}") + classpath(libs.buildscript.android) + classpath(libs.buildscript.kotlin) + classpath(libs.buildscript.hilt) + classpath(libs.buildscript.safeargs) } } @@ -44,26 +45,26 @@ allprojects { gradlePluginPortal() google() mavenCentral() - maven(url = "https://kotlin.bintray.com/kotlinx/") + maven { url = uri("https://jitpack.io") } } } dependencies { - detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:${Versions.detektGradlePlugin}") + detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:${libs.versions.detektGradlePlugin.get()}") } tasks.withType { - jvmTarget = "1.8" + jvmTarget = "11" } detekt { - input = files(subprojects.map { File(it.projectDir, "src") }) + source.setFrom(files(subprojects.map { File(it.projectDir, "src") })) buildUponDefaultConfig = true autoCorrect = true - config = files("detekt-config.yml") + config.setFrom(files("detekt-config.yml")) } tasks.maybeCreate("check").dependsOn(tasks.named("detekt")) @@ -74,20 +75,24 @@ allprojects { version = System.getenv("GITHUB_REF")?.substring(10) ?: System.getProperty("GITHUB_REF")?.substring(10) ?: "unknown" plugins.withType { - tasks.withType().configureEach { + dokka { dokkaSourceSets { configureEach { - if (name.startsWith("ios")) { - displayName.set("ios") - } - sourceLink { localDirectory.set(rootDir) - remoteUrl.set(java.net.URL("https://github.com/appmattus/multiplatform-utils/blob/main")) + remoteUrl("https://github.com/appmattus/multiplatform-utils/blob/main") remoteLineSuffix.set("#L") } } } + + pluginsConfiguration.html { + footerMessage.set( + provider { + "Copyright © 2021-${ZonedDateTime.now().year} Appmattus Limited" + } + ) + } } } } diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts deleted file mode 100644 index c0633d3..0000000 --- a/buildSrc/build.gradle.kts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2021 Appmattus Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile - -plugins { - `kotlin-dsl` -} - -repositories { - mavenCentral() -} - -kotlinDslPluginOptions { - experimentalWarning.set(false) -} - -tasks.withType(KotlinCompile::class.java).all { - kotlinOptions { - jvmTarget = JavaVersion.VERSION_1_8.toString() - } -} diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt deleted file mode 100644 index a2abbf1..0000000 --- a/buildSrc/src/main/kotlin/Versions.kt +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2021 Appmattus Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -object Versions { - - const val kotlin = "1.5.0" - - const val androidGradlePlugin = "4.2.0" - const val detektGradlePlugin = "1.16.0" - const val gradleVersionsPlugin = "0.36.0" - const val markdownlintGradlePlugin = "0.6.0" - const val gradleMavenPublishPlugin = "0.15.1" - const val dokkaPlugin = "1.4.32" - - const val coil = "1.2.1" - const val coroutines = "1.5.0-RC" - const val coroutinesNative = "1.5.0-RC-native-mt" - const val groupie = "2.9.0" - const val orbitMvi = "3.1.1" - - const val desugar = "1.1.1" - const val leakCanary = "2.7" - - object AndroidX { - const val appCompat = "1.2.0" - const val constraintLayout = "2.1.0-alpha2" - const val fragment = "1.3.3" - const val lifecycle = "2.3.1" - const val navigation = "2.3.5" - const val vectorDrawable = "1.1.0" - } - - object Google { - val dagger = "2.35.1" - val material = "1.3.0" - } -} diff --git a/connectivity/build.gradle.kts b/connectivity/build.gradle.kts index 93ce48d..cb551d5 100644 --- a/connectivity/build.gradle.kts +++ b/connectivity/build.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright 2021 Appmattus Limited + * Copyright 2021-2025 Appmattus Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,49 +14,56 @@ * limitations under the License. */ -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile - plugins { - kotlin("multiplatform") id("com.android.library") - id("com.vanniktech.maven.publish") - id("org.jetbrains.dokka") + kotlin("multiplatform") + alias(libs.plugins.gradleMavenPublishPlugin) + alias(libs.plugins.dokkaPlugin) } kotlin { - android() - ios() + androidTarget() + + iosX64() + iosArm64() + iosSimulatorArm64() + + listOf( + iosX64(), + iosArm64(), + iosSimulatorArm64() + ).forEach { iosTarget -> + iosTarget.binaries.framework { + baseName = "multiplatformutils-connectivity" + isStatic = true + } + } + + // Apply the default hierarchy again. It'll create, for example, the iosMain source set: + applyDefaultHierarchyTemplate() sourceSets { - val commonMain by getting { - dependencies { - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core") { - version { - strictly(Versions.coroutinesNative) - } - } - } + commonMain.dependencies { + implementation(libs.kotlinx.coroutines) } - val commonTest by getting - val androidMain by getting { - dependencies { - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:${Versions.coroutines}") - } + + androidMain.dependencies { + implementation(libs.androidx.annotation) } - val androidTest by getting - val iosMain by getting - val iosTest by getting + } + + compilerOptions { + jvmToolchain(11) + freeCompilerArgs.add("-Xexpect-actual-classes") } } android { - compileSdkVersion(30) - sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") + namespace = "com.appmattus.multiplatformutils.connectivity" + compileSdk = 35 + defaultConfig { - minSdkVersion(21) - targetSdkVersion(30) - versionCode = 1 - versionName = "1.0" + minSdk = 21 } buildTypes { getByName("release") { @@ -65,9 +72,7 @@ android { } compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 } } - -tasks.withType { kotlinOptions.jvmTarget = JavaVersion.VERSION_1_8.toString() } diff --git a/connectivity/src/androidMain/AndroidManifest.xml b/connectivity/src/androidMain/AndroidManifest.xml index c691ac9..611d9ab 100644 --- a/connectivity/src/androidMain/AndroidManifest.xml +++ b/connectivity/src/androidMain/AndroidManifest.xml @@ -1,6 +1,5 @@ - + diff --git a/connectivity/src/androidMain/kotlin/com/appmattus/connectivity/Connectivity.kt b/connectivity/src/androidMain/kotlin/com/appmattus/connectivity/Connectivity.kt index 87dae4f..5fbe6c8 100644 --- a/connectivity/src/androidMain/kotlin/com/appmattus/connectivity/Connectivity.kt +++ b/connectivity/src/androidMain/kotlin/com/appmattus/connectivity/Connectivity.kt @@ -1,5 +1,5 @@ /* - * Copyright 2021 Appmattus Limited + * Copyright 2021-2025 Appmattus Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,6 @@ package com.appmattus.connectivity -import android.annotation.TargetApi import android.content.Context import android.net.ConnectivityManager import android.net.Network @@ -24,6 +23,7 @@ import android.net.NetworkCapabilities import android.net.NetworkRequest import android.os.Build.VERSION import android.os.Build.VERSION_CODES +import androidx.annotation.RequiresApi import com.appmattus.connectivity.ConnectivityStatus.Status.Mobile import com.appmattus.connectivity.ConnectivityStatus.Status.None import com.appmattus.connectivity.ConnectivityStatus.Status.Wifi @@ -50,7 +50,7 @@ actual class Connectivity(private val context: Context) { getNetworkTypeLegacy() } - @TargetApi(VERSION_CODES.M) + @RequiresApi(VERSION_CODES.M) private fun getNetworkTypeApi23(): ConnectivityStatus { val network = connectivityManager.activeNetwork val capabilities = @@ -58,7 +58,7 @@ actual class Connectivity(private val context: Context) { return when { capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) || - capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> ConnectivityStatus(Wifi) + capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> ConnectivityStatus(Wifi) capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> ConnectivityStatus(Mobile) @@ -81,11 +81,11 @@ actual class Connectivity(private val context: Context) { ConnectivityManager.TYPE_MOBILE, ConnectivityManager.TYPE_MOBILE_DUN, ConnectivityManager.TYPE_MOBILE_HIPRI -> ConnectivityStatus(Mobile) + else -> ConnectivityStatus(None) } } - @Suppress("EXPERIMENTAL_API_USAGE") actual val connectivityStatus: Flow get() = callbackFlow { var statusJob: Job? = null diff --git a/connectivity/src/iosMain/kotlin/com/appmattus/connectivity/Connectivity.kt b/connectivity/src/iosMain/kotlin/com/appmattus/connectivity/Connectivity.kt index 27c5303..45c7cd6 100644 --- a/connectivity/src/iosMain/kotlin/com/appmattus/connectivity/Connectivity.kt +++ b/connectivity/src/iosMain/kotlin/com/appmattus/connectivity/Connectivity.kt @@ -1,5 +1,5 @@ /* - * Copyright 2021 Appmattus Limited + * Copyright 2021-2025 Appmattus Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ import com.appmattus.connectivity.ConnectivityStatus.Status.Mobile import com.appmattus.connectivity.ConnectivityStatus.Status.None import com.appmattus.connectivity.ConnectivityStatus.Status.Wifi import kotlinx.cinterop.COpaquePointer +import kotlinx.cinterop.ExperimentalForeignApi import kotlinx.cinterop.StableRef import kotlinx.cinterop.alloc import kotlinx.cinterop.asStableRef @@ -50,6 +51,7 @@ import platform.SystemConfiguration.kSCNetworkReachabilityFlagsInterventionRequi import platform.SystemConfiguration.kSCNetworkReachabilityFlagsIsWWAN import platform.SystemConfiguration.kSCNetworkReachabilityFlagsReachable +@OptIn(ExperimentalForeignApi::class) actual class Connectivity(private val nodename: String = "example.com") { @Suppress("MemberNameEqualsClassName") @@ -67,7 +69,6 @@ actual class Connectivity(private val nodename: String = "example.com") { flags.asConnectivityStatus } - @Suppress("EXPERIMENTAL_API_USAGE") actual val connectivityStatus get() = callbackFlow { val reachability = SCNetworkReachabilityCreateWithName(null, nodename)!! @@ -110,27 +111,21 @@ actual class Connectivity(private val nodename: String = "example.com") { else -> None }.let(::ConnectivityStatus) - @Suppress("EXPERIMENTAL_API_USAGE") private val SCNetworkReachabilityFlags.connectionOnDemand: Boolean get() = (kSCNetworkReachabilityFlagsConnectionOnDemand and this) != 0.toUInt() - @Suppress("EXPERIMENTAL_API_USAGE") private val SCNetworkReachabilityFlags.connectionOnTraffic: Boolean get() = (kSCNetworkReachabilityFlagsConnectionOnTraffic and this) != 0.toUInt() - @Suppress("EXPERIMENTAL_API_USAGE") private val SCNetworkReachabilityFlags.connectionRequired: Boolean get() = (kSCNetworkReachabilityFlagsConnectionRequired and this) != 0.toUInt() - @Suppress("EXPERIMENTAL_API_USAGE") private val SCNetworkReachabilityFlags.interventionRequired: Boolean get() = (kSCNetworkReachabilityFlagsInterventionRequired and this) != 0.toUInt() - @Suppress("EXPERIMENTAL_API_USAGE") private val SCNetworkReachabilityFlags.isWWAN: Boolean get() = (kSCNetworkReachabilityFlagsIsWWAN and this) != 0.toUInt() - @Suppress("EXPERIMENTAL_API_USAGE") private val SCNetworkReachabilityFlags.reachable: Boolean get() = (kSCNetworkReachabilityFlagsReachable and this) != 0.toUInt() } diff --git a/gradle.properties b/gradle.properties index 3247230..25aac11 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,13 +4,6 @@ xcodeproj=./samples/iosApp android.useAndroidX=true -kotlin.mpp.enableGranularSourceSetsMetadata=true -kotlin.mpp.stability.nowarn=true - -kotlin.native.enableDependencyPropagation=false - -kotlin.js.generate.executable.default=false - systemProp.org.gradle.internal.publish.checksums.insecure=true android.defaults.buildfeatures.buildconfig=false @@ -21,6 +14,10 @@ android.defaults.buildfeatures.shaders=false org.gradle.jvmargs=-Xmx2048m +# Enable Dokka Gradle plugin v2 +org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled +org.jetbrains.dokka.experimental.gradle.pluginMode.noWarn=true + # Maven Publishing GROUP=com.appmattus.mpu diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 0000000..d3349d8 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,77 @@ +[versions] + +kotlin = "2.1.20" + +androidGradlePlugin = "8.9.1" +detektGradlePlugin = "1.23.8" +gradleVersionsPlugin = "0.52.0" +markdownlintGradlePlugin = "0.6.0" +gradleMavenPublishPlugin = "0.31.0" +dokkaPlugin = "2.0.0" + +androidx_annotation = "1.9.1" +androidx_appCompat = "1.7.0" +androidx_constraintLayout = "2.2.1" +androidx_fragment = "1.8.6" +androidx_lifecycle = "2.8.7" +androidx_navigation = "2.8.9" +androidx_vectorDrawable = "1.2.0" + +coil = "3.1.0" +desugar = "2.1.5" + +google_dagger = "2.56.1" +google_material = "1.12.0" + +groupie = "2.10.1" + +kotlinx_coroutines = "1.10.2" + +leakCanary = "2.14" +orbitMvi = "9.0.0" + +[libraries] + +androidx_annotation = { module = "androidx.annotation:annotation", version.ref = "androidx_annotation" } +androidx_appcompat = { module = "androidx.appcompat:appcompat", version.ref = "androidx_appCompat" } +androidx_constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "androidx_constraintLayout" } +androidx_fragment = { module = "androidx.fragment:fragment-ktx", version.ref = "androidx_fragment" } +androidx_lifecycle_runtime = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "androidx_lifecycle" } +androidx_lifecycle_viewmodel = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "androidx_lifecycle" } +androidx_navigation_fragment = { module = "androidx.navigation:navigation-fragment-ktx", version.ref = "androidx_navigation" } +androidx_navigation_ui = { module = "androidx.navigation:navigation-ui-ktx", version.ref = "androidx_navigation" } +androidx_vectordrawable = { module = "androidx.vectordrawable:vectordrawable", version.ref = "androidx_vectorDrawable" } + +coil_svg = { module = "io.coil-kt.coil3:coil-svg", version.ref = "coil" } + +desugar = { module = "com.android.tools:desugar_jdk_libs", version.ref = "desugar" } + +google_material = { module = "com.google.android.material:material", version.ref = "google_material" } + +groupie = { module = "com.github.lisawray.groupie:groupie", version.ref = "groupie" } +groupieViewbinding = { module = "com.github.lisawray.groupie:groupie-viewbinding", version.ref = "groupie" } + +hiltAndroid = { module = "com.google.dagger:hilt-android", version.ref = "google_dagger" } +hiltCompiler = { module = "com.google.dagger:hilt-compiler", version.ref = "google_dagger" } + +kotlinx_coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx_coroutines" } + +leakcanary_android = { module = "com.squareup.leakcanary:leakcanary-android", version.ref = "leakCanary" } +leakcanary_plumber = { module = "com.squareup.leakcanary:plumber-android", version.ref = "leakCanary" } + +orbitViewmodel = { module = "org.orbit-mvi:orbit-viewmodel", version.ref = "orbitMvi" } + +buildscript_android = { module = "com.android.tools.build:gradle", version.ref = "androidGradlePlugin" } +buildscript_kotlin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" } +buildscript_hilt = { module = "com.google.dagger:hilt-android-gradle-plugin", version.ref = "google_dagger" } +buildscript_safeargs = { module = "androidx.navigation:navigation-safe-args-gradle-plugin", version.ref = "androidx_navigation" } + + +[plugins] + +androidGradlePlugin = { id = "com.android.library", version.ref = "androidGradlePlugin" } +detektGradlePlugin = { id = "io.gitlab.arturbosch.detekt", version.ref = "detektGradlePlugin" } +gradleVersionsPlugin = { id = "com.github.ben-manes.versions", version.ref = "gradleVersionsPlugin" } +markdownlintGradlePlugin = { id = "com.appmattus.markdown", version.ref = "markdownlintGradlePlugin" } +gradleMavenPublishPlugin = { id = "com.vanniktech.maven.publish", version.ref = "gradleMavenPublishPlugin" } +dokkaPlugin = { id = "org.jetbrains.dokka", version.ref = "dokkaPlugin" } diff --git a/gradle/scripts/dependencyUpdates.gradle.kts b/gradle/scripts/dependencyUpdates.gradle.kts index e96d660..19365b5 100644 --- a/gradle/scripts/dependencyUpdates.gradle.kts +++ b/gradle/scripts/dependencyUpdates.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright 2021 Appmattus Limited + * Copyright 2021-2025 Appmattus Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,14 +23,14 @@ buildscript { maven(url = "https://plugins.gradle.org/m2/") } dependencies { - classpath("com.github.ben-manes:gradle-versions-plugin:${Versions.gradleVersionsPlugin}") + classpath("com.github.ben-manes:gradle-versions-plugin:${libs.versions.gradleVersionsPlugin.get()}") } } apply() fun isNonStable(version: String): Boolean { - val stableKeyword = listOf("RELEASE", "FINAL", "GA").any { version.toUpperCase().contains(it) } + val stableKeyword = listOf("RELEASE", "FINAL", "GA").any { version.uppercase().contains(it) } val regex = "^[0-9,.v-]+(-r)?$".toRegex() return !stableKeyword && !regex.matches(version) } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index e708b1c..a4b76b9 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 3c4101c..37f853b 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 4f906e0..f5feea6 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ -#!/usr/bin/env sh +#!/bin/sh # -# Copyright 2015 the original author or authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -15,69 +15,104 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar @@ -87,9 +122,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -98,88 +133,120 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=`expr $i + 1` + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 107acd3..9d21a21 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -13,8 +13,10 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +27,8 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,13 +43,13 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute +if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -56,11 +59,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -75,13 +78,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/ignore-test/README.md b/ignore-ios/README.md similarity index 84% rename from ignore-test/README.md rename to ignore-ios/README.md index 94a7749..86759c6 100644 --- a/ignore-test/README.md +++ b/ignore-ios/README.md @@ -1,20 +1,19 @@ -# ignore-test +# ignore-ios -A Kotlin Multiplatform Mobile library to add annotations to ignore tests from -specific platforms. +A Kotlin Multiplatform Mobile library to add annotations to ignore iOS tests. ## Getting started ![badge][badge-android] ![badge][badge-ios] ![badge][badge-jvm] -[![Maven Central](https://img.shields.io/maven-central/v/com.appmattus.mpu/ignore-test)](https://search.maven.org/search?q=g:com.appmattus.mpu) +[![Maven Central](https://img.shields.io/maven-central/v/com.appmattus.mpu/ignore-ios)](https://search.maven.org/search?q=g:com.appmattus.mpu) Include the following dependency in your *build.gradle.kts* file: ```kotlin commonMain { - implementation("com.appmattus.mpu:ignore-test:") + implementation("com.appmattus.mpu:ignore-ios:") } ``` diff --git a/ignore-ios/build.gradle.kts b/ignore-ios/build.gradle.kts new file mode 100644 index 0000000..5108a2c --- /dev/null +++ b/ignore-ios/build.gradle.kts @@ -0,0 +1,55 @@ +/* + * Copyright 2025 Appmattus Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +plugins { + kotlin("multiplatform") + alias(libs.plugins.gradleMavenPublishPlugin) + alias(libs.plugins.dokkaPlugin) +} + +kotlin { + jvm() + + iosX64() + iosArm64() + iosSimulatorArm64() + + listOf( + iosX64(), + iosArm64(), + iosSimulatorArm64() + ).forEach { iosTarget -> + iosTarget.binaries.framework { + baseName = "multiplatformutils-ignoreios" + isStatic = true + } + } + + // Apply the default hierarchy again. It'll create, for example, the iosMain source set: + applyDefaultHierarchyTemplate() + + sourceSets { + commonMain.dependencies { + implementation(kotlin("test-common")) + implementation(kotlin("test-annotations-common")) + } + } + + compilerOptions { + jvmToolchain(11) + freeCompilerArgs.add("-Xexpect-actual-classes") + } +} diff --git a/ignore-test/gradle.properties b/ignore-ios/gradle.properties similarity index 73% rename from ignore-test/gradle.properties rename to ignore-ios/gradle.properties index c34238b..32c5d50 100644 --- a/ignore-test/gradle.properties +++ b/ignore-ios/gradle.properties @@ -1,5 +1,5 @@ # -# Copyright 2021 Appmattus Limited +# Copyright 2025 Appmattus Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ # limitations under the License. # -POM_NAME=com.appmattus.mpu:ignore-test -POM_ARTIFACT_ID=ignore-test -POM_DESCRIPTION=Annotations to ignore tests from specific platforms -POM_INCEPTION_YEAR=2021 +POM_NAME=com.appmattus.mpu:ignore-ios +POM_ARTIFACT_ID=ignore-ios +POM_DESCRIPTION=Annotations to ignore iOS tests +POM_INCEPTION_YEAR=2025 diff --git a/ignore-test/src/commonMain/kotlin/com/appmattus/ignore/IgnoreIos.kt b/ignore-ios/src/commonMain/kotlin/com/appmattus/ignore/IgnoreIos.kt similarity index 90% rename from ignore-test/src/commonMain/kotlin/com/appmattus/ignore/IgnoreIos.kt rename to ignore-ios/src/commonMain/kotlin/com/appmattus/ignore/IgnoreIos.kt index 3a6f61d..36e6b5c 100644 --- a/ignore-test/src/commonMain/kotlin/com/appmattus/ignore/IgnoreIos.kt +++ b/ignore-ios/src/commonMain/kotlin/com/appmattus/ignore/IgnoreIos.kt @@ -1,5 +1,5 @@ /* - * Copyright 2021 Appmattus Limited + * Copyright 2025 Appmattus Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,7 @@ package com.appmattus.ignore -@Suppress("EXPERIMENTAL_API_USAGE_ERROR") +@OptIn(ExperimentalMultiplatform::class) @OptionalExpectation @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION) @Retention(AnnotationRetention.BINARY) diff --git a/ignore-test/src/iosMain/kotlin/com/appmattus/ignore/IgnoreIos.kt b/ignore-ios/src/iosMain/kotlin/com/appmattus/ignore/IgnoreIos.kt similarity index 88% rename from ignore-test/src/iosMain/kotlin/com/appmattus/ignore/IgnoreIos.kt rename to ignore-ios/src/iosMain/kotlin/com/appmattus/ignore/IgnoreIos.kt index 542e86f..ae5e53d 100644 --- a/ignore-test/src/iosMain/kotlin/com/appmattus/ignore/IgnoreIos.kt +++ b/ignore-ios/src/iosMain/kotlin/com/appmattus/ignore/IgnoreIos.kt @@ -1,5 +1,5 @@ /* - * Copyright 2021 Appmattus Limited + * Copyright 2025 Appmattus Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,4 +16,5 @@ package com.appmattus.ignore +@Suppress("ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT") actual typealias IgnoreIos = kotlin.test.Ignore diff --git a/ignore-junit/README.md b/ignore-junit/README.md new file mode 100644 index 0000000..bed6e14 --- /dev/null +++ b/ignore-junit/README.md @@ -0,0 +1,30 @@ +# ignore-junit + +A Kotlin Multiplatform Mobile library to add annotations to ignore JUnit 4 +tests. + +## Getting started + +![badge][badge-android] +![badge][badge-ios] +![badge][badge-jvm] +[![Maven Central](https://img.shields.io/maven-central/v/com.appmattus.mpu/ignore-junit)](https://search.maven.org/search?q=g:com.appmattus.mpu) + +Include the following dependency in your *build.gradle.kts* file: + +```kotlin +commonMain { + implementation("com.appmattus.mpu:ignore-junit:") +} +``` + +[badge-android]: http://img.shields.io/badge/platform-android-6EDB8D.svg?style=flat +[badge-ios]: http://img.shields.io/badge/platform-ios-CDCDCD.svg?style=flat +[badge-js]: http://img.shields.io/badge/platform-js-F8DB5D.svg?style=flat +[badge-jvm]: http://img.shields.io/badge/platform-jvm-DB413D.svg?style=flat +[badge-linux]: http://img.shields.io/badge/platform-linux-2D3F6C.svg?style=flat +[badge-windows]: http://img.shields.io/badge/platform-windows-4D76CD.svg?style=flat +[badge-mac]: http://img.shields.io/badge/platform-macos-111111.svg?style=flat +[badge-watchos]: http://img.shields.io/badge/platform-watchos-C0C0C0.svg?style=flat +[badge-tvos]: http://img.shields.io/badge/platform-tvos-808080.svg?style=flat +[badge-wasm]: https://img.shields.io/badge/platform-wasm-624FE8.svg?style=flat diff --git a/ignore-junit/build.gradle.kts b/ignore-junit/build.gradle.kts new file mode 100644 index 0000000..796fda8 --- /dev/null +++ b/ignore-junit/build.gradle.kts @@ -0,0 +1,59 @@ +/* + * Copyright 2025 Appmattus Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +plugins { + kotlin("multiplatform") + alias(libs.plugins.gradleMavenPublishPlugin) + alias(libs.plugins.dokkaPlugin) +} + +kotlin { + jvm() + + iosX64() + iosArm64() + iosSimulatorArm64() + + listOf( + iosX64(), + iosArm64(), + iosSimulatorArm64() + ).forEach { iosTarget -> + iosTarget.binaries.framework { + baseName = "multiplatformutils-ignorejunit" + isStatic = true + } + } + + // Apply the default hierarchy again. It'll create, for example, the iosMain source set: + applyDefaultHierarchyTemplate() + + sourceSets { + commonMain.dependencies { + implementation(kotlin("test-common")) + implementation(kotlin("test-annotations-common")) + } + + jvmMain.dependencies { + compileOnly(kotlin("test-junit")) + } + } + + compilerOptions { + jvmToolchain(11) + freeCompilerArgs.add("-Xexpect-actual-classes") + } +} diff --git a/ignore-junit/gradle.properties b/ignore-junit/gradle.properties new file mode 100644 index 0000000..1ea5518 --- /dev/null +++ b/ignore-junit/gradle.properties @@ -0,0 +1,20 @@ +# +# Copyright 2025 Appmattus Limited +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +POM_NAME=com.appmattus.mpu:ignore-junit +POM_ARTIFACT_ID=ignore-junit +POM_DESCRIPTION=Annotations to ignore JUnit4 tests +POM_INCEPTION_YEAR=2025 diff --git a/ignore-test/src/commonMain/kotlin/com/appmattus/ignore/IgnoreJunit4.kt b/ignore-junit/src/commonMain/kotlin/com/appmattus/ignore/IgnoreJunit.kt similarity index 85% rename from ignore-test/src/commonMain/kotlin/com/appmattus/ignore/IgnoreJunit4.kt rename to ignore-junit/src/commonMain/kotlin/com/appmattus/ignore/IgnoreJunit.kt index 237e28f..57413aa 100644 --- a/ignore-test/src/commonMain/kotlin/com/appmattus/ignore/IgnoreJunit4.kt +++ b/ignore-junit/src/commonMain/kotlin/com/appmattus/ignore/IgnoreJunit.kt @@ -1,5 +1,5 @@ /* - * Copyright 2021 Appmattus Limited + * Copyright 2025 Appmattus Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,8 +16,8 @@ package com.appmattus.ignore -@Suppress("EXPERIMENTAL_API_USAGE_ERROR") +@OptIn(ExperimentalMultiplatform::class) @OptionalExpectation @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION) @Retention(AnnotationRetention.BINARY) -expect annotation class IgnoreJunit4() +expect annotation class IgnoreJunit() diff --git a/ignore-test/src/junit4Main/kotlin/com/appmattus/ignore/IgnoreJunit4.kt b/ignore-junit/src/jvmMain/kotlin/com/appmattus/ignore/IgnoreJunit4.kt similarity index 80% rename from ignore-test/src/junit4Main/kotlin/com/appmattus/ignore/IgnoreJunit4.kt rename to ignore-junit/src/jvmMain/kotlin/com/appmattus/ignore/IgnoreJunit4.kt index 3853d4b..73c690e 100644 --- a/ignore-test/src/junit4Main/kotlin/com/appmattus/ignore/IgnoreJunit4.kt +++ b/ignore-junit/src/jvmMain/kotlin/com/appmattus/ignore/IgnoreJunit4.kt @@ -1,5 +1,5 @@ /* - * Copyright 2021 Appmattus Limited + * Copyright 2025 Appmattus Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,8 +14,11 @@ * limitations under the License. */ +@file:Suppress("Filename") + package com.appmattus.ignore import org.junit.Ignore -actual typealias IgnoreJunit4 = Ignore +@Suppress("ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT") +actual typealias IgnoreJunit = Ignore diff --git a/ignore-junit5/README.md b/ignore-junit5/README.md new file mode 100644 index 0000000..f4986af --- /dev/null +++ b/ignore-junit5/README.md @@ -0,0 +1,30 @@ +# ignore-junit5 + +A Kotlin Multiplatform Mobile library to add annotations to ignore JUnit 5 +tests. + +## Getting started + +![badge][badge-android] +![badge][badge-ios] +![badge][badge-jvm] +[![Maven Central](https://img.shields.io/maven-central/v/com.appmattus.mpu/ignore-junit5)](https://search.maven.org/search?q=g:com.appmattus.mpu) + +Include the following dependency in your *build.gradle.kts* file: + +```kotlin +commonMain { + implementation("com.appmattus.mpu:ignore-junit5:") +} +``` + +[badge-android]: http://img.shields.io/badge/platform-android-6EDB8D.svg?style=flat +[badge-ios]: http://img.shields.io/badge/platform-ios-CDCDCD.svg?style=flat +[badge-js]: http://img.shields.io/badge/platform-js-F8DB5D.svg?style=flat +[badge-jvm]: http://img.shields.io/badge/platform-jvm-DB413D.svg?style=flat +[badge-linux]: http://img.shields.io/badge/platform-linux-2D3F6C.svg?style=flat +[badge-windows]: http://img.shields.io/badge/platform-windows-4D76CD.svg?style=flat +[badge-mac]: http://img.shields.io/badge/platform-macos-111111.svg?style=flat +[badge-watchos]: http://img.shields.io/badge/platform-watchos-C0C0C0.svg?style=flat +[badge-tvos]: http://img.shields.io/badge/platform-tvos-808080.svg?style=flat +[badge-wasm]: https://img.shields.io/badge/platform-wasm-624FE8.svg?style=flat diff --git a/ignore-junit5/build.gradle.kts b/ignore-junit5/build.gradle.kts new file mode 100644 index 0000000..8f388b9 --- /dev/null +++ b/ignore-junit5/build.gradle.kts @@ -0,0 +1,59 @@ +/* + * Copyright 2025 Appmattus Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +plugins { + kotlin("multiplatform") + alias(libs.plugins.gradleMavenPublishPlugin) + alias(libs.plugins.dokkaPlugin) +} + +kotlin { + jvm() + + iosX64() + iosArm64() + iosSimulatorArm64() + + listOf( + iosX64(), + iosArm64(), + iosSimulatorArm64() + ).forEach { iosTarget -> + iosTarget.binaries.framework { + baseName = "multiplatformutils-ignorejunit5" + isStatic = true + } + } + + // Apply the default hierarchy again. It'll create, for example, the iosMain source set: + applyDefaultHierarchyTemplate() + + sourceSets { + commonMain.dependencies { + implementation(kotlin("test-common")) + implementation(kotlin("test-annotations-common")) + } + + jvmMain.dependencies { + compileOnly(kotlin("test-junit5")) + } + } + + compilerOptions { + jvmToolchain(11) + freeCompilerArgs.add("-Xexpect-actual-classes") + } +} diff --git a/ignore-junit5/gradle.properties b/ignore-junit5/gradle.properties new file mode 100644 index 0000000..54cab43 --- /dev/null +++ b/ignore-junit5/gradle.properties @@ -0,0 +1,20 @@ +# +# Copyright 2025 Appmattus Limited +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +POM_NAME=com.appmattus.mpu:ignore-junit5 +POM_ARTIFACT_ID=ignore-junit5 +POM_DESCRIPTION=Annotations to ignore JUnit 5 tests +POM_INCEPTION_YEAR=2025 diff --git a/ignore-test/src/commonMain/kotlin/com/appmattus/ignore/IgnoreJunit5.kt b/ignore-junit5/src/commonMain/kotlin/com/appmattus/ignore/IgnoreJunit5.kt similarity index 90% rename from ignore-test/src/commonMain/kotlin/com/appmattus/ignore/IgnoreJunit5.kt rename to ignore-junit5/src/commonMain/kotlin/com/appmattus/ignore/IgnoreJunit5.kt index ba2cff6..35b746d 100644 --- a/ignore-test/src/commonMain/kotlin/com/appmattus/ignore/IgnoreJunit5.kt +++ b/ignore-junit5/src/commonMain/kotlin/com/appmattus/ignore/IgnoreJunit5.kt @@ -1,5 +1,5 @@ /* - * Copyright 2021 Appmattus Limited + * Copyright 2025 Appmattus Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,7 @@ package com.appmattus.ignore -@Suppress("EXPERIMENTAL_API_USAGE_ERROR") +@OptIn(ExperimentalMultiplatform::class) @OptionalExpectation @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION) @Retention(AnnotationRetention.BINARY) diff --git a/ignore-test/src/junit5Main/kotlin/com/appmattus/ignore/IgnoreJunit5.kt b/ignore-junit5/src/jvmMain/kotlin/com/appmattus/ignore/IgnoreJunit5.kt similarity index 88% rename from ignore-test/src/junit5Main/kotlin/com/appmattus/ignore/IgnoreJunit5.kt rename to ignore-junit5/src/jvmMain/kotlin/com/appmattus/ignore/IgnoreJunit5.kt index 87a6f54..7555c29 100644 --- a/ignore-test/src/junit5Main/kotlin/com/appmattus/ignore/IgnoreJunit5.kt +++ b/ignore-junit5/src/jvmMain/kotlin/com/appmattus/ignore/IgnoreJunit5.kt @@ -1,5 +1,5 @@ /* - * Copyright 2021 Appmattus Limited + * Copyright 2025 Appmattus Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,4 +18,5 @@ package com.appmattus.ignore import org.junit.jupiter.api.Disabled +@Suppress("ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT") actual typealias IgnoreJunit5 = Disabled diff --git a/ignore-test/build.gradle.kts b/ignore-test/build.gradle.kts deleted file mode 100644 index fbdde13..0000000 --- a/ignore-test/build.gradle.kts +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2021 Appmattus Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile - -plugins { - kotlin("multiplatform") - id("com.vanniktech.maven.publish") - id("org.jetbrains.dokka") -} - -kotlin { - jvm("junit4") - jvm("junit5") - ios() - - sourceSets { - val commonMain by getting { - dependencies { - implementation(kotlin("test-common")) - implementation(kotlin("test-annotations-common")) - } - } - val commonTest by getting - val junit4Main by getting { - dependencies { - compileOnly(kotlin("test-junit")) - } - } - val junit4Test by getting - val junit5Main by getting { - dependencies { - compileOnly(kotlin("test-junit5")) - } - } - val junit5Test by getting - val iosMain by getting - val iosTest by getting - } -} - -tasks.withType { kotlinOptions.jvmTarget = JavaVersion.VERSION_1_8.toString() } diff --git a/package-info/build.gradle.kts b/package-info/build.gradle.kts index 8e905cc..1a6e08d 100644 --- a/package-info/build.gradle.kts +++ b/package-info/build.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright 2021 Appmattus Limited + * Copyright 2021-2025 Appmattus Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,37 +14,50 @@ * limitations under the License. */ -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile - plugins { - kotlin("multiplatform") id("com.android.library") - id("com.vanniktech.maven.publish") - id("org.jetbrains.dokka") + kotlin("multiplatform") + alias(libs.plugins.gradleMavenPublishPlugin) + alias(libs.plugins.dokkaPlugin) } kotlin { - android() - ios() + androidTarget() + + iosX64() + iosArm64() + iosSimulatorArm64() + + listOf( + iosX64(), + iosArm64(), + iosSimulatorArm64() + ).forEach { iosTarget -> + iosTarget.binaries.framework { + baseName = "multiplatformutils-packageinfo" + isStatic = true + } + } + + // Apply the default hierarchy again. It'll create, for example, the iosMain source set: + applyDefaultHierarchyTemplate() sourceSets { - val commonMain by getting - val commonTest by getting - val androidMain by getting - val androidTest by getting - val iosMain by getting - val iosTest by getting + + } + + compilerOptions { + jvmToolchain(11) + freeCompilerArgs.add("-Xexpect-actual-classes") } } android { - compileSdkVersion(30) - sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") + namespace = "com.appmattus.multiplatformutils.packageinfo" + compileSdk = 35 + defaultConfig { - minSdkVersion(21) - targetSdkVersion(30) - versionCode = 1 - versionName = "1.0" + minSdk = 21 } buildTypes { getByName("release") { @@ -53,9 +66,7 @@ android { } compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 } } - -tasks.withType { kotlinOptions.jvmTarget = JavaVersion.VERSION_1_8.toString() } diff --git a/package-info/src/androidMain/AndroidManifest.xml b/package-info/src/androidMain/AndroidManifest.xml deleted file mode 100644 index f67065f..0000000 --- a/package-info/src/androidMain/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/package-info/src/androidMain/kotlin/com/appmattus/packageinfo/PackageInfo.kt b/package-info/src/androidMain/kotlin/com/appmattus/packageinfo/PackageInfo.kt index 4c2abfe..67d03b1 100644 --- a/package-info/src/androidMain/kotlin/com/appmattus/packageinfo/PackageInfo.kt +++ b/package-info/src/androidMain/kotlin/com/appmattus/packageinfo/PackageInfo.kt @@ -1,5 +1,5 @@ /* - * Copyright 2021 Appmattus Limited + * Copyright 2021-2025 Appmattus Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,7 +24,7 @@ actual class PackageInfo(context: Context) { private val packageManager = context.packageManager private val info = packageManager.getPackageInfo(context.packageName, 0) - actual val appName: String? = info.applicationInfo.loadLabel(packageManager).toString() + actual val appName: String? = info.applicationInfo?.loadLabel(packageManager)?.toString() actual val packageName: String? = context.packageName diff --git a/samples/androidApp/build.gradle.kts b/samples/androidApp/build.gradle.kts index d9668de..eba0f9a 100644 --- a/samples/androidApp/build.gradle.kts +++ b/samples/androidApp/build.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright 2021 Appmattus Limited + * Copyright 2021-2025 Appmattus Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,59 +20,48 @@ plugins { id("kotlin-parcelize") kotlin("kapt") id("androidx.navigation.safeargs.kotlin") + id("dagger.hilt.android.plugin") } -apply(plugin = "dagger.hilt.android.plugin") - dependencies { implementation(project(":samples:shared")) - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core") { - version { - strictly(Versions.coroutinesNative) - } - } - - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android") { - version { - strictly(Versions.coroutinesNative) - } - } - // Architecture - implementation("androidx.fragment:fragment-ktx:${Versions.AndroidX.fragment}") - implementation("androidx.lifecycle:lifecycle-runtime-ktx:${Versions.AndroidX.lifecycle}") - implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:${Versions.AndroidX.lifecycle}") - implementation("androidx.navigation:navigation-fragment-ktx:${Versions.AndroidX.navigation}") - implementation("androidx.navigation:navigation-ui-ktx:${Versions.AndroidX.navigation}") - implementation("org.orbit-mvi:orbit-viewmodel:${Versions.orbitMvi}") + implementation(libs.kotlinx.coroutines) + implementation(libs.androidx.fragment) + implementation(libs.androidx.lifecycle.runtime) + implementation(libs.androidx.lifecycle.viewmodel) + implementation(libs.androidx.navigation.fragment) + implementation(libs.androidx.navigation.ui) + implementation(libs.orbitViewmodel) // UI - implementation("com.google.android.material:material:${Versions.Google.material}") - implementation("androidx.appcompat:appcompat:${Versions.AndroidX.appCompat}") - implementation("androidx.constraintlayout:constraintlayout:${Versions.AndroidX.constraintLayout}") - implementation("androidx.vectordrawable:vectordrawable:${Versions.AndroidX.vectorDrawable}") - implementation("com.xwray:groupie:${Versions.groupie}") - implementation("com.xwray:groupie-viewbinding:${Versions.groupie}") - implementation("io.coil-kt:coil-svg:${Versions.coil}") + implementation(libs.google.material) + implementation(libs.androidx.appcompat) + implementation(libs.androidx.constraintlayout) + implementation(libs.androidx.vectordrawable) + implementation(libs.groupie) + implementation(libs.groupieViewbinding) + implementation(libs.coil.svg) // Memory leak detection and fixes - debugImplementation("com.squareup.leakcanary:leakcanary-android:${Versions.leakCanary}") - implementation("com.squareup.leakcanary:plumber-android:${Versions.leakCanary}") + debugImplementation(libs.leakcanary.android) + implementation(libs.leakcanary.plumber) // Dependency Injection - implementation("com.google.dagger:hilt-android:${Versions.Google.dagger}") - kapt("com.google.dagger:hilt-compiler:${Versions.Google.dagger}") + implementation(libs.hiltAndroid) + kapt(libs.hiltCompiler) - coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:${Versions.desugar}") + coreLibraryDesugaring(libs.desugar) } android { - compileSdkVersion(30) + namespace = "com.appmattus.multiplatformutils.samples" + compileSdk = 35 defaultConfig { applicationId = "com.appmattus.multiplatformutils.samples" - minSdkVersion(21) - targetSdkVersion(30) + minSdk = 21 + targetSdk = 35 versionCode = 1 versionName = "1.0" vectorDrawables.useSupportLibrary = true @@ -86,12 +75,12 @@ android { compileOptions { isCoreLibraryDesugaringEnabled = true - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 } kotlinOptions { - jvmTarget = JavaVersion.VERSION_1_8.toString() + jvmTarget = JavaVersion.VERSION_11.toString() } buildFeatures { diff --git a/samples/androidApp/src/main/AndroidManifest.xml b/samples/androidApp/src/main/AndroidManifest.xml index a005256..22b0ade 100644 --- a/samples/androidApp/src/main/AndroidManifest.xml +++ b/samples/androidApp/src/main/AndroidManifest.xml @@ -1,7 +1,6 @@ + xmlns:tools="http://schemas.android.com/tools"> @@ -16,7 +15,8 @@ android:theme="@style/AppTheme" android:usesCleartextTraffic="false" tools:ignore="UnusedAttribute"> - + diff --git a/samples/androidApp/src/main/kotlin/com/appmattus/multiplatformutils/samples/SamplesFragment.kt b/samples/androidApp/src/main/kotlin/com/appmattus/multiplatformutils/samples/SamplesFragment.kt index 2542b13..d22aa7c 100644 --- a/samples/androidApp/src/main/kotlin/com/appmattus/multiplatformutils/samples/SamplesFragment.kt +++ b/samples/androidApp/src/main/kotlin/com/appmattus/multiplatformutils/samples/SamplesFragment.kt @@ -24,9 +24,9 @@ import androidx.fragment.app.Fragment import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView +import com.appmattus.multiplatformutils.samples.databinding.RecyclerViewFragmentBinding import com.appmattus.multiplatformutils.samples.ui.component.SingleLineTextHeaderItem import com.appmattus.multiplatformutils.samples.ui.component.SingleLineTextItem -import com.appmattus.multiplatformutils.samples.databinding.RecyclerViewFragmentBinding import com.xwray.groupie.GroupAdapter import com.xwray.groupie.GroupieViewHolder import dagger.hilt.android.AndroidEntryPoint @@ -46,17 +46,23 @@ class SamplesFragment : Fragment() { layoutManager = LinearLayoutManager(requireContext(), RecyclerView.VERTICAL, false) adapter = GroupAdapter().apply { add(SingleLineTextHeaderItem("Samples")) - add(SingleLineTextItem("battery") { - findNavController().navigate(R.id.action_samplesFragment_to_batteryFragment) - }) + add( + SingleLineTextItem("battery") { + findNavController().navigate(R.id.action_samplesFragment_to_batteryFragment) + } + ) - add(SingleLineTextItem("connectivity") { - findNavController().navigate(R.id.action_samplesFragment_to_connectivityFragment) - }) + add( + SingleLineTextItem("connectivity") { + findNavController().navigate(R.id.action_samplesFragment_to_connectivityFragment) + } + ) - add(SingleLineTextItem("package-info") { - findNavController().navigate(R.id.action_samplesFragment_to_packageInfoFragment) - }) + add( + SingleLineTextItem("package-info") { + findNavController().navigate(R.id.action_samplesFragment_to_packageInfoFragment) + } + ) } } } diff --git a/samples/androidApp/src/main/kotlin/com/appmattus/multiplatformutils/samples/battery/BatteryViewModel.kt b/samples/androidApp/src/main/kotlin/com/appmattus/multiplatformutils/samples/battery/BatteryViewModel.kt index 01c86a1..10ec941 100644 --- a/samples/androidApp/src/main/kotlin/com/appmattus/multiplatformutils/samples/battery/BatteryViewModel.kt +++ b/samples/androidApp/src/main/kotlin/com/appmattus/multiplatformutils/samples/battery/BatteryViewModel.kt @@ -1,5 +1,5 @@ /* - * Copyright 2021 Appmattus Limited + * Copyright 2021-2025 Appmattus Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,13 +20,10 @@ import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import com.appmattus.battery.Battery import dagger.hilt.android.lifecycle.HiltViewModel -import javax.inject.Inject -import kotlinx.coroutines.flow.collect import org.orbitmvi.orbit.Container import org.orbitmvi.orbit.ContainerHost -import org.orbitmvi.orbit.syntax.simple.intent -import org.orbitmvi.orbit.syntax.simple.reduce import org.orbitmvi.orbit.viewmodel.container +import javax.inject.Inject @HiltViewModel class BatteryViewModel @Inject constructor( diff --git a/samples/androidApp/src/main/kotlin/com/appmattus/multiplatformutils/samples/connectivity/ConnectivityViewModel.kt b/samples/androidApp/src/main/kotlin/com/appmattus/multiplatformutils/samples/connectivity/ConnectivityViewModel.kt index ea053d5..5b2ba9f 100644 --- a/samples/androidApp/src/main/kotlin/com/appmattus/multiplatformutils/samples/connectivity/ConnectivityViewModel.kt +++ b/samples/androidApp/src/main/kotlin/com/appmattus/multiplatformutils/samples/connectivity/ConnectivityViewModel.kt @@ -1,5 +1,5 @@ /* - * Copyright 2021 Appmattus Limited + * Copyright 2021-2025 Appmattus Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,13 +20,10 @@ import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import com.appmattus.connectivity.Connectivity import dagger.hilt.android.lifecycle.HiltViewModel -import javax.inject.Inject -import kotlinx.coroutines.flow.collect import org.orbitmvi.orbit.Container import org.orbitmvi.orbit.ContainerHost -import org.orbitmvi.orbit.syntax.simple.intent -import org.orbitmvi.orbit.syntax.simple.reduce import org.orbitmvi.orbit.viewmodel.container +import javax.inject.Inject @HiltViewModel class ConnectivityViewModel @Inject constructor( @@ -41,7 +38,7 @@ class ConnectivityViewModel @Inject constructor( private fun loadConnectivity() = intent(registerIdling = false) { connectivity.connectivityStatus.collect { reduce { - state.copy(connectivityStatus = it) + state.copy(connectivityStatus = it) } } } diff --git a/samples/androidApp/src/main/kotlin/com/appmattus/multiplatformutils/samples/packageinfo/PackageInfoViewModel.kt b/samples/androidApp/src/main/kotlin/com/appmattus/multiplatformutils/samples/packageinfo/PackageInfoViewModel.kt index 2a9b8ee..e60bee3 100644 --- a/samples/androidApp/src/main/kotlin/com/appmattus/multiplatformutils/samples/packageinfo/PackageInfoViewModel.kt +++ b/samples/androidApp/src/main/kotlin/com/appmattus/multiplatformutils/samples/packageinfo/PackageInfoViewModel.kt @@ -1,5 +1,5 @@ /* - * Copyright 2021 Appmattus Limited + * Copyright 2021-2025 Appmattus Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,12 +20,10 @@ import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import com.appmattus.packageinfo.PackageInfo import dagger.hilt.android.lifecycle.HiltViewModel -import javax.inject.Inject import org.orbitmvi.orbit.Container import org.orbitmvi.orbit.ContainerHost -import org.orbitmvi.orbit.syntax.simple.intent -import org.orbitmvi.orbit.syntax.simple.reduce import org.orbitmvi.orbit.viewmodel.container +import javax.inject.Inject @HiltViewModel class PackageInfoViewModel @Inject constructor( @@ -34,7 +32,7 @@ class PackageInfoViewModel @Inject constructor( ) : ViewModel(), ContainerHost { override val container: Container = container(PackageInfoState(), savedStateHandle) { - if (it.appName.isEmpty()) loadPackageInfo() + if (state.appName.isEmpty()) loadPackageInfo() } private fun loadPackageInfo() = intent { diff --git a/samples/androidApp/src/main/kotlin/com/appmattus/multiplatformutils/samples/ui/component/TwoLineTextItem.kt b/samples/androidApp/src/main/kotlin/com/appmattus/multiplatformutils/samples/ui/component/TwoLineTextItem.kt index 0faaf4a..0e161ce 100644 --- a/samples/androidApp/src/main/kotlin/com/appmattus/multiplatformutils/samples/ui/component/TwoLineTextItem.kt +++ b/samples/androidApp/src/main/kotlin/com/appmattus/multiplatformutils/samples/ui/component/TwoLineTextItem.kt @@ -32,7 +32,7 @@ data class TwoLineTextItem( override fun hasSameContentAs(other: Item<*>): Boolean { return primaryText == (other as? TwoLineTextItem)?.primaryText && - secondaryText == (other as? TwoLineTextItem)?.secondaryText + secondaryText == (other as? TwoLineTextItem)?.secondaryText } override fun initializeViewBinding(view: View) = TwoLineTextItemBinding.bind(view) diff --git a/samples/androidApp/src/main/kotlin/com/appmattus/multiplatformutils/samples/ui/debounce.kt b/samples/androidApp/src/main/kotlin/com/appmattus/multiplatformutils/samples/ui/debounce.kt index 417d212..6ec50db 100644 --- a/samples/androidApp/src/main/kotlin/com/appmattus/multiplatformutils/samples/ui/debounce.kt +++ b/samples/androidApp/src/main/kotlin/com/appmattus/multiplatformutils/samples/ui/debounce.kt @@ -1,5 +1,5 @@ /* - * Copyright 2021 Appmattus Limited + * Copyright 2021-2025 Appmattus Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,6 +14,8 @@ * limitations under the License. */ +@file:Suppress("Filename") + package com.appmattus.multiplatformutils.samples.ui import kotlinx.coroutines.CoroutineScope diff --git a/samples/iosApp/iosApp.xcodeproj/project.pbxproj b/samples/iosApp/iosApp.xcodeproj/project.pbxproj index 918e947..919e794 100644 --- a/samples/iosApp/iosApp.xcodeproj/project.pbxproj +++ b/samples/iosApp/iosApp.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 52; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -18,12 +18,12 @@ C5D0B56525CD8DB9000FAA1A /* TwoLineTextRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5D0B56425CD8DB9000FAA1A /* TwoLineTextRow.swift */; }; C5D0B57625CD9D4D000FAA1A /* Publisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5D0B57525CD9D4D000FAA1A /* Publisher.swift */; }; C5D0B57A25CD9DB5000FAA1A /* BatteryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5D0B57925CD9DB5000FAA1A /* BatteryView.swift */; }; - C5D0B58225CDA472000FAA1A /* shared.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = C5D0B58125CDA472000FAA1A /* shared.xcframework */; }; - C5D0B58325CDA472000FAA1A /* shared.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = C5D0B58125CDA472000FAA1A /* shared.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; C5D0B58A25CDA73D000FAA1A /* BatteryViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5D0B58925CDA73D000FAA1A /* BatteryViewModel.swift */; }; C5D0B59725CDB183000FAA1A /* ConnectivityView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5D0B59625CDB183000FAA1A /* ConnectivityView.swift */; }; C5D0B59925CDB194000FAA1A /* ConnectivityViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5D0B59825CDB194000FAA1A /* ConnectivityViewModel.swift */; }; C5D0B59B25CEB230000FAA1A /* PackageInfoViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5D0B59A25CEB230000FAA1A /* PackageInfoViewModel.swift */; }; + C627FBC42DA5D99700B1D5AC /* shared.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = C6EB60072DA53CF400FC60C2 /* shared.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + C6E9E6242DA53E4C00500D81 /* shared.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = C6EB60072DA53CF400FC60C2 /* shared.xcframework */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -33,7 +33,7 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( - C5D0B58325CDA472000FAA1A /* shared.xcframework in Embed Frameworks */, + C627FBC42DA5D99700B1D5AC /* shared.xcframework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -55,11 +55,11 @@ C5D0B56425CD8DB9000FAA1A /* TwoLineTextRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoLineTextRow.swift; sourceTree = ""; }; C5D0B57525CD9D4D000FAA1A /* Publisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Publisher.swift; sourceTree = ""; }; C5D0B57925CD9DB5000FAA1A /* BatteryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BatteryView.swift; sourceTree = ""; }; - C5D0B58125CDA472000FAA1A /* shared.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = shared.xcframework; path = "../shared/build/xcode-frameworks/shared.xcframework"; sourceTree = ""; }; C5D0B58925CDA73D000FAA1A /* BatteryViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BatteryViewModel.swift; sourceTree = ""; }; C5D0B59625CDB183000FAA1A /* ConnectivityView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectivityView.swift; sourceTree = ""; }; C5D0B59825CDB194000FAA1A /* ConnectivityViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectivityViewModel.swift; sourceTree = ""; }; C5D0B59A25CEB230000FAA1A /* PackageInfoViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PackageInfoViewModel.swift; sourceTree = ""; }; + C6EB60072DA53CF400FC60C2 /* shared.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = shared.xcframework; path = ../shared/build/XCFrameworks/release/shared.xcframework; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -67,7 +67,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - C5D0B58225CDA472000FAA1A /* shared.xcframework in Frameworks */, + C6E9E6242DA53E4C00500D81 /* shared.xcframework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -121,7 +121,7 @@ 7555FFB0242A642200829871 /* Frameworks */ = { isa = PBXGroup; children = ( - C5D0B58125CDA472000FAA1A /* shared.xcframework */, + C6EB60072DA53CF400FC60C2 /* shared.xcframework */, 446563EA2538941000A6AB4D /* Accessibility.framework */, ); name = Frameworks; @@ -265,7 +265,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "cd \"$SRCROOT/..\"\n./../gradlew :samples:shared:buildXcFramework -PXCODE_CONFIGURATION=${CONFIGURATION}\n"; + shellScript = "cd \"$SRCROOT/..\"\n./../gradlew :samples:shared:assembleXCFramework -PXCODE_CONFIGURATION=${CONFIGURATION}\n"; }; /* End PBXShellScriptBuildPhase section */ diff --git a/samples/shared/build.gradle.kts b/samples/shared/build.gradle.kts index e097066..8bbb205 100644 --- a/samples/shared/build.gradle.kts +++ b/samples/shared/build.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright 2021 Appmattus Limited + * Copyright 2021-2025 Appmattus Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,50 +14,59 @@ * limitations under the License. */ -import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget +import org.jetbrains.kotlin.gradle.plugin.mpp.apple.XCFramework plugins { - kotlin("multiplatform") id("com.android.library") + kotlin("multiplatform") id("kotlin-parcelize") } kotlin { - android() - ios { - binaries { - framework { - export(project(":battery")) - export(project(":connectivity")) - export(project(":package-info")) - baseName = "shared" - } + androidTarget() + + iosX64() + iosArm64() + iosSimulatorArm64() + + val xcf = XCFramework() + + listOf( + iosX64(), + iosArm64(), + iosSimulatorArm64() + ).forEach { iosTarget -> + iosTarget.binaries.framework { + export(project(":battery")) + export(project(":connectivity")) + export(project(":package-info")) + baseName = "shared" + xcf.add(this) } } + + // Apply the default hierarchy again. It'll create, for example, the iosMain source set: + applyDefaultHierarchyTemplate() + sourceSets { - val commonMain by getting { - dependencies { - api(project(":battery")) - api(project(":connectivity")) - api(project(":package-info")) - } + commonMain.dependencies { + api(project(":battery")) + api(project(":connectivity")) + api(project(":package-info")) } - val commonTest by getting - val androidMain by getting - val androidTest by getting - val iosMain by getting - val iosTest by getting + } + + compilerOptions { + jvmToolchain(11) } } android { - compileSdkVersion(30) - sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") + namespace = "com.appmattus.multiplatformutils.shared" + compileSdk = 35 + defaultConfig { - minSdkVersion(21) - targetSdkVersion(30) - versionCode = 1 - versionName = "1.0" + minSdk = 21 } buildTypes { getByName("release") { @@ -66,43 +75,7 @@ android { } compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 } } - -tasks.withType { kotlinOptions.jvmTarget = "1.8" } - -val xcFrameworkPath = "$buildDir/xcode-frameworks/${project.name}.xcframework" - -tasks.create("deleteXcFramework") { delete = setOf(xcFrameworkPath) } - -val buildXcFramework by tasks.registering { - dependsOn("deleteXcFramework") - group = "build" - val mode = "Release" - val frameworks = arrayOf("iosArm64", "iosX64") - .map { kotlin.targets.getByName(it).binaries.getFramework(mode) } - inputs.property("mode", mode) - dependsOn(frameworks.map { it.linkTask }) - doLast { buildXcFramework(frameworks) } -} - -fun Task.buildXcFramework(frameworks: List) { - val buildArgs: () -> List = { - val arguments = mutableListOf("-create-xcframework") - frameworks.forEach { - arguments += "-framework" - arguments += "${it.outputDirectory}/${project.name}.framework" - } - arguments += "-output" - arguments += xcFrameworkPath - arguments - } - exec { - executable = "xcodebuild" - args = buildArgs() - } -} - -tasks.getByName("build").dependsOn(buildXcFramework) diff --git a/samples/shared/src/androidMain/AndroidManifest.xml b/samples/shared/src/androidMain/AndroidManifest.xml deleted file mode 100644 index ac011cc..0000000 --- a/samples/shared/src/androidMain/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/samples/shared/src/iosMain/kotlin/com/appmattus/multiplatformutils/flow/subscribe.kt b/samples/shared/src/iosMain/kotlin/com/appmattus/multiplatformutils/flow/subscribe.kt index 3b4ef6e..4186365 100644 --- a/samples/shared/src/iosMain/kotlin/com/appmattus/multiplatformutils/flow/subscribe.kt +++ b/samples/shared/src/iosMain/kotlin/com/appmattus/multiplatformutils/flow/subscribe.kt @@ -1,5 +1,5 @@ /* - * Copyright 2021 Appmattus Limited + * Copyright 2021-2025 Appmattus Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,6 +14,8 @@ * limitations under the License. */ +@file:Suppress("Filename") + package com.appmattus.multiplatformutils.flow import kotlinx.coroutines.CoroutineScope diff --git a/settings.gradle.kts b/settings.gradle.kts index 208a416..f351603 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,6 +1,8 @@ include(":battery") include(":connectivity") -include(":ignore-test") +include(":ignore-ios") +include(":ignore-junit") +include(":ignore-junit5") include(":package-info") include(":samples:shared") include(":samples:androidApp")