From 2424e7272d48c97819bdd6b07b32209a261f3f88 Mon Sep 17 00:00:00 2001 From: Ilya Evtushenko Date: Fri, 11 Jul 2025 19:31:26 +0200 Subject: [PATCH 1/2] Apply wizard changes --- .gitignore | 19 ++++- README.md | 7 +- build.gradle.kts | 4 +- composeApp/build.gradle.kts | 34 +++------ .../src/androidMain/AndroidManifest.xml | 17 +++-- .../drawable/compose-multiplatform.xml | 0 .../kotlin/com/jetbrains/basicsample/App.kt | 75 +++++++++++++++++++ .../com/jetbrains/basicsample/MainActivity.kt | 67 +---------------- .../src/androidMain/res/values/colors.xml | 9 --- .../src/androidMain/res/values/themes.xml | 14 ---- gradle/libs.versions.toml | 51 ++++++------- gradle/wrapper/gradle-wrapper.properties | 2 +- shared/build.gradle.kts | 7 +- .../jetbrains/basicsample}/CalculatorTest.kt | 0 14 files changed, 147 insertions(+), 159 deletions(-) rename composeApp/src/{commonMain => androidMain}/composeResources/drawable/compose-multiplatform.xml (100%) create mode 100644 composeApp/src/androidMain/kotlin/com/jetbrains/basicsample/App.kt delete mode 100644 composeApp/src/androidMain/res/values/colors.xml delete mode 100644 composeApp/src/androidMain/res/values/themes.xml rename shared/src/commonTest/kotlin/{com.jetbrains.basicsample => com/jetbrains/basicsample}/CalculatorTest.kt (100%) diff --git a/.gitignore b/.gitignore index 185ad67..7d9c0e4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,18 @@ *.iml -.gradle/ -build/ -.idea/ -.DS_STORE .kotlin +.gradle +**/build/ +xcuserdata +!src/**/build/ local.properties +.idea +.DS_Store +captures +.externalNativeBuild +.cxx +*.xcodeproj/* +!*.xcodeproj/project.pbxproj +!*.xcodeproj/xcshareddata/ +!*.xcodeproj/project.xcworkspace/ +!*.xcworkspace/contents.xcworkspacedata +**/xcshareddata/WorkspaceSettings.xcsettings diff --git a/README.md b/README.md index a6ba919..411953c 100644 --- a/README.md +++ b/README.md @@ -12,12 +12,13 @@ This sample demonstrates basic KMP features: ## How to use -With the [KMP plugin for Android Studio](https://plugins.jetbrains.com/plugin/14936-kotlin-multiplatform-mobile) you can run, test, and debug shared code on both platforms without switching IDEs. Run and debug the application by selecting the corresponding configuration in the **Run configuration** menu. Run and debug shared module tests by pressing the gutter icon on a test class or method. +With the [Kotlin Multiplatform plugin](https://plugins.jetbrains.com/plugin/14936-kotlin-multiplatform-mobile) you can run, test, and debug shared code on both platforms without switching IDEs. Run and debug the application by selecting the corresponding configuration in the **Run configuration** menu. Run and debug shared module tests by pressing the gutter icon on a test class or method. ## Related links -* Visit [Kotlin Multiplatform Developer Portal](https://kotlinlang.org/lp/mobile/) to learn more about the technology -* Check out the [Networking and data storage with KMP hands-on](https://play.kotlinlang.org/hands-on/Networking%20and%20Data%20Storage%20with%20Kotlin%20Multiplatfrom%20Mobile/) lab to learn how to create a mobile application for Android and iOS with a shared codebase with Ktor and SQLDelight. +* Visit the [Kotlin Multiplatform landing page](https://www.jetbrains.com/kotlin-multiplatform/) to learn more about the technology +* Get started with [Kotlin Multiplatform on developer portal](https://www.jetbrains.com/help/kotlin-multiplatform-dev/get-started.html) +* Check out the [Networking and data storage with KMP hands-on](https://www.jetbrains.com/help/kotlin-multiplatform-dev/multiplatform-ktor-sqldelight.html) lab to learn how to create a mobile application for Android and iOS with a shared codebase with Ktor and SQLDelight. diff --git a/build.gradle.kts b/build.gradle.kts index 14f9573..cf780d5 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -3,7 +3,7 @@ plugins { // in each subproject's classloader alias(libs.plugins.androidApplication) apply false alias(libs.plugins.androidLibrary) apply false - alias(libs.plugins.jetbrainsCompose) apply false - alias(libs.plugins.compose.compiler) apply false + alias(libs.plugins.composeMultiplatform) apply false + alias(libs.plugins.composeCompiler) apply false alias(libs.plugins.kotlinMultiplatform) apply false } \ No newline at end of file diff --git a/composeApp/build.gradle.kts b/composeApp/build.gradle.kts index 0e69335..2fbcb84 100644 --- a/composeApp/build.gradle.kts +++ b/composeApp/build.gradle.kts @@ -4,8 +4,8 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget plugins { alias(libs.plugins.kotlinMultiplatform) alias(libs.plugins.androidApplication) - alias(libs.plugins.jetbrainsCompose) - alias(libs.plugins.compose.compiler) + alias(libs.plugins.composeMultiplatform) + alias(libs.plugins.composeCompiler) } kotlin { @@ -20,26 +20,21 @@ kotlin { androidMain.dependencies { implementation(compose.preview) implementation(libs.androidx.activity.compose) - implementation(project(":shared")) - implementation(libs.androidx.material) - implementation(libs.androidx.appcompat) - implementation(libs.androidx.constraintlayout) - - implementation(platform("androidx.compose:compose-bom:2024.06.00")) - implementation(libs.activity.compose) - implementation(libs.androidx.ui) - implementation(libs.androidx.ui.graphics) - implementation(libs.androidx.material3) } commonMain.dependencies { implementation(compose.runtime) implementation(compose.foundation) - implementation(compose.material) + implementation(compose.material3) implementation(compose.ui) implementation(compose.components.resources) implementation(compose.components.uiToolingPreview) + implementation(libs.androidx.lifecycle.viewmodel) + implementation(libs.androidx.lifecycle.runtimeCompose) implementation(projects.shared) } + commonTest.dependencies { + implementation(libs.kotlin.test) + } } } @@ -47,10 +42,6 @@ android { namespace = "com.jetbrains.basicsample" compileSdk = libs.versions.android.compileSdk.get().toInt() - sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") - sourceSets["main"].res.srcDirs("src/androidMain/res") - sourceSets["main"].resources.srcDirs("src/commonMain/resources") - defaultConfig { applicationId = "com.jetbrains.basicsample" minSdk = libs.versions.android.minSdk.get().toInt() @@ -72,11 +63,8 @@ android { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 } - buildFeatures { - compose = true - } - dependencies { - debugImplementation(compose.uiTooling) - } } +dependencies { + debugImplementation(compose.uiTooling) +} diff --git a/composeApp/src/androidMain/AndroidManifest.xml b/composeApp/src/androidMain/AndroidManifest.xml index 49840a6..95a7478 100644 --- a/composeApp/src/androidMain/AndroidManifest.xml +++ b/composeApp/src/androidMain/AndroidManifest.xml @@ -2,16 +2,19 @@ + android:allowBackup="true" + android:icon="@mipmap/ic_launcher" + android:roundIcon="@mipmap/ic_launcher_round" + android:label="@string/app_name" + android:supportsRtl="true" + android:theme="@android:style/Theme.Material.Light.NoActionBar"> + android:name="com.jetbrains.basicsample.MainActivity" + android:exported="true"> - + - + diff --git a/composeApp/src/commonMain/composeResources/drawable/compose-multiplatform.xml b/composeApp/src/androidMain/composeResources/drawable/compose-multiplatform.xml similarity index 100% rename from composeApp/src/commonMain/composeResources/drawable/compose-multiplatform.xml rename to composeApp/src/androidMain/composeResources/drawable/compose-multiplatform.xml diff --git a/composeApp/src/androidMain/kotlin/com/jetbrains/basicsample/App.kt b/composeApp/src/androidMain/kotlin/com/jetbrains/basicsample/App.kt new file mode 100644 index 0000000..2eb7750 --- /dev/null +++ b/composeApp/src/androidMain/kotlin/com/jetbrains/basicsample/App.kt @@ -0,0 +1,75 @@ +package com.jetbrains.basicsample + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.material3.TextField +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.unit.dp +import org.jetbrains.compose.ui.tooling.preview.Preview + +@Composable +@Preview +fun App() { + MaterialTheme { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center + ) { + Column( + horizontalAlignment = Alignment.Start, + ) { + Text(greet(), Modifier.padding(8.dp)) + + var firstNumber by rememberSaveable { mutableStateOf("") } + var secondNumber by rememberSaveable { mutableStateOf("") } + + Row(verticalAlignment = Alignment.CenterVertically) { + TextField( + value = firstNumber, + onValueChange = { firstNumber = it }, + modifier = Modifier.width(100.dp), + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), + ) + Text(text = "+", modifier = Modifier.padding(4.dp)) + TextField( + value = secondNumber, + onValueChange = { secondNumber = it }, + modifier = Modifier.width(100.dp), + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), + ) + + val first = firstNumber.toIntOrNull() + val second = secondNumber.toIntOrNull() + Text( + text = if (first != null && second != null) { + "= ${Calculator.sum(first, second)}" + } else { + "= \uD83E\uDD14" + }, + modifier = Modifier + .width(100.dp) + .padding(4.dp) + ) + } + } + } + } +} + +fun greet(): String { + return Greeting().greeting() +} \ No newline at end of file diff --git a/composeApp/src/androidMain/kotlin/com/jetbrains/basicsample/MainActivity.kt b/composeApp/src/androidMain/kotlin/com/jetbrains/basicsample/MainActivity.kt index cb9b1d3..47cf25c 100644 --- a/composeApp/src/androidMain/kotlin/com/jetbrains/basicsample/MainActivity.kt +++ b/composeApp/src/androidMain/kotlin/com/jetbrains/basicsample/MainActivity.kt @@ -3,74 +3,15 @@ package com.jetbrains.basicsample import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.text.KeyboardOptions -import androidx.compose.material3.Text -import androidx.compose.material3.TextField -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.text.input.KeyboardType -import androidx.compose.ui.unit.dp - -fun greet(): String { - return Greeting().greeting() -} +import androidx.activity.enableEdgeToEdge class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { + enableEdgeToEdge() super.onCreate(savedInstanceState) - setContent { - Box( - modifier = Modifier.fillMaxSize(), - contentAlignment = Alignment.Center - ) { - Column( - horizontalAlignment = Alignment.Start, - ) { - Text(greet(), Modifier.padding(8.dp)) - var firstNumber by rememberSaveable { mutableStateOf("") } - var secondNumber by rememberSaveable { mutableStateOf("") } - - Row(verticalAlignment = Alignment.CenterVertically) { - TextField( - value = firstNumber, - onValueChange = { firstNumber = it }, - modifier = Modifier.width(100.dp), - keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), - ) - Text(text = "+", modifier = Modifier.padding(4.dp)) - TextField( - value = secondNumber, - onValueChange = { secondNumber = it }, - modifier = Modifier.width(100.dp), - keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), - ) - - val first = firstNumber.toIntOrNull() - val second = secondNumber.toIntOrNull() - Text( - text = if (first != null && second != null) { - "= ${Calculator.sum(first, second)}" - } else { - "= \uD83E\uDD14" - }, - modifier = Modifier - .width(100.dp) - .padding(4.dp) - ) - } - } - } + setContent { + App() } } } diff --git a/composeApp/src/androidMain/res/values/colors.xml b/composeApp/src/androidMain/res/values/colors.xml deleted file mode 100644 index f2fa444..0000000 --- a/composeApp/src/androidMain/res/values/colors.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - #FF6200EE - #FF3700B3 - #FF03DAC5 - #FF018786 - #FF000000 - #FFFFFFFF - \ No newline at end of file diff --git a/composeApp/src/androidMain/res/values/themes.xml b/composeApp/src/androidMain/res/values/themes.xml deleted file mode 100644 index 325cb01..0000000 --- a/composeApp/src/androidMain/res/values/themes.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5337e80..a142669 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,38 +1,35 @@ [versions] -agp = "8.2.2" -android-compileSdk = "34" +agp = "8.7.3" +android-compileSdk = "35" android-minSdk = "24" -android-targetSdk = "34" -androidx-activityCompose = "1.9.0" -androidx-appcompat = "1.7.0" -androidx-constraintlayout = "2.1.4" -androidx-core-ktx = "1.13.1" -androidx-espresso-core = "3.6.0" -androidx-material = "1.12.0" -androidx-test-junit = "1.2.0" -compose-plugin = "1.6.10" +android-targetSdk = "35" +androidx-activity = "1.10.1" +androidx-appcompat = "1.7.1" +androidx-constraintlayout = "2.2.1" +androidx-core = "1.16.0" +androidx-espresso = "3.6.1" +androidx-lifecycle = "2.9.1" +androidx-testExt = "1.2.1" +composeMultiplatform = "1.8.2" junit = "4.13.2" -kotlin = "2.0.0" +kotlin = "2.2.0" [libraries] -activity-compose = { module = "androidx.activity:activity-compose" } -androidx-material3 = { module = "androidx.compose.material3:material3" } -androidx-ui = { module = "androidx.compose.ui:ui" } -androidx-ui-graphics = { module = "androidx.compose.ui:ui-graphics" } kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" } -kotlin-test-junit = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref = "kotlin" } -junit = { group = "junit", name = "junit", version.ref = "junit" } -androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "androidx-core-ktx" } -androidx-test-junit = { group = "androidx.test.ext", name = "junit", version.ref = "androidx-test-junit" } -androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "androidx-espresso-core" } -androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "androidx-appcompat" } -androidx-material = { group = "com.google.android.material", name = "material", version.ref = "androidx-material" } -androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "androidx-constraintlayout" } -androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activityCompose" } +kotlin-testJunit = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref = "kotlin" } +junit = { module = "junit:junit", version.ref = "junit" } +androidx-core-ktx = { module = "androidx.core:core-ktx", version.ref = "androidx-core" } +androidx-testExt-junit = { module = "androidx.test.ext:junit", version.ref = "androidx-testExt" } +androidx-espresso-core = { module = "androidx.test.espresso:espresso-core", version.ref = "androidx-espresso" } +androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "androidx-appcompat" } +androidx-constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "androidx-constraintlayout" } +androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activity" } +androidx-lifecycle-viewmodel = { module = "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel", version.ref = "androidx-lifecycle" } +androidx-lifecycle-runtimeCompose = { module = "org.jetbrains.androidx.lifecycle:lifecycle-runtime-compose", version.ref = "androidx-lifecycle" } [plugins] androidApplication = { id = "com.android.application", version.ref = "agp" } androidLibrary = { id = "com.android.library", version.ref = "agp" } -jetbrainsCompose = { id = "org.jetbrains.compose", version.ref = "compose-plugin" } -compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } +composeMultiplatform = { id = "org.jetbrains.compose", version.ref = "composeMultiplatform" } +composeCompiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index b82aa23..09523c0 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index 428e3e4..7322963 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -30,12 +30,7 @@ kotlin { // put your Multiplatform dependencies here } commonTest.dependencies { - implementation(kotlin("test")) - } - val androidUnitTest by getting { - dependencies { - implementation(libs.junit) - } + implementation(libs.kotlin.test) } } } diff --git a/shared/src/commonTest/kotlin/com.jetbrains.basicsample/CalculatorTest.kt b/shared/src/commonTest/kotlin/com/jetbrains/basicsample/CalculatorTest.kt similarity index 100% rename from shared/src/commonTest/kotlin/com.jetbrains.basicsample/CalculatorTest.kt rename to shared/src/commonTest/kotlin/com/jetbrains/basicsample/CalculatorTest.kt From a379659e3e319ad2513385e042a35012abdee48e Mon Sep 17 00:00:00 2001 From: Ilya Evtushenko Date: Fri, 11 Jul 2025 20:23:13 +0200 Subject: [PATCH 2/2] Bump AGP version --- gradle/libs.versions.toml | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a142669..0e6a192 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -agp = "8.7.3" +agp = "8.10.0" android-compileSdk = "35" android-minSdk = "24" android-targetSdk = "35" diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 09523c0..37f853b 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME