LoginSignup
0
0

More than 1 year has passed since last update.

KMMプロジェクトを作ってバージョンカタログが利用できるスタート地点に立つまで

Last updated at Posted at 2022-04-24

はじめに

設定が複雑で設定やちゃんと動くようにするだけで一苦労。
とりあえず現時点での環境でプロジェクトが動くようになるまでまとめておく。後々別環境とかで動かす機会があったら、最初から環境構築から書きたい。
ライブラリのバージョンカタログ、バージョン管理ができるようになるまでします。

環境

  • Macbook Air M1 2020
  • iOS 12.1 Monterey
  • Android Studio Bumblebee | 2021.1.1 Patch 1
  • Kotlin Multiplatform Mobile plugin 0.3.2
  • Xcode 13.2.1

プロジェクトが動くようになるまでの手順

  1. Android StudioでNew Project->Kotlin Multiplatform App
  2. 名前を任意で決めて、OSバージョンは29〜
  3. アプリ名は、androidApp,iosApp,shared
  4. iOS frameworkは、 CocoaPods dependency frameworkを利用
  5. Android Studioから、シミュレータで、Androidアプリ起動
  6. iOSは、XcodeからiosApp/iosApp.workspaceから開き、シミュレータ起動(Android Studioからは、なぜか開けない)

gradleの設定(必要な人だけ)

  • gradle-wapper.properties(初期のまま)
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
  • gradle.properties(初期のまま)
#Gradle
org.gradle.jvmargs=-Xmx2048M -Dkotlin.daemon.jvm.options\="-Xmx2048M"

#Kotlin
kotlin.code.style=official

#Android
android.useAndroidX=true

#MPP
kotlin.mpp.enableGranularSourceSetsMetadata=true
kotlin.native.enableDependencyPropagation=false
kotlin.mpp.enableCInteropCommonization=true
  • settings.gradle.kts
    バージョンカタログを導入します。
pluginManagement {
    repositories {
        google()
        gradlePluginPortal()
        mavenCentral()
    }
}

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
    }
}

rootProject.name = "appName"
include(":androidApp")
include(":shared")

enableFeaturePreview("VERSION_CATALOGS")
  • libs.versions.toml
    gradleディレクトリに作成します。
    バージョンカタログに利用します。
[versions]
plugin-android = "7.1.1"
plugin-kotlin = "1.6.10"
plugin-gver = "0.42.0"

androidx-compose = "1.1.0"
kotlinx-serialization = "1.3.2"
kotlinx-coroutines = "1.6.0-native-mt"
ktor = "2.0.0-beta-1"
napier = "2.4.0"
multiplatform-settings = "0.8.1"
voyager = "1.0.0-beta15"
koin = "3.1.5"
accompanist = "0.23.0"
coil = "2.0.0-alpha08"
activity-compose = "1.4.0"
work-runtime-ktx = "2.7.1"
desugar-jdk-libs = "1.1.5"

[libraries]
[versions]
plugin-android = "7.1.1"
plugin-kotlin = "1.6.10"
plugin-gver = "0.42.0"

androidx-compose = "1.1.0"
kotlinx-serialization = "1.3.2"
kotlinx-coroutines = "1.6.0-native-mt"
ktor = "2.0.0-beta-1"
napier = "2.4.0"
multiplatform-settings = "0.8.1"
voyager = "1.0.0-beta15"
koin = "3.1.5"
accompanist = "0.23.0"
coil = "2.0.0-alpha08"
activity-compose = "1.4.0"
work-runtime-ktx = "2.7.1"
desugar-jdk-libs = "1.1.5"
appcompat = "1.3.1"
androidx-core = "1.7.0"
androidx-lifecycle = "2.4.1"

[libraries]
plugin-android = { module = "com.android.tools.build:gradle", version.ref = "plugin-android" }
plugin-kotlin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "plugin-kotlin" }
plugin-kotlin-serialization = { module = "org.jetbrains.kotlin:kotlin-serialization", version.ref = "plugin-kotlin" }
plugin-gver = { module = "com.github.ben-manes:gradle-versions-plugin", version.ref = "plugin-gver" }

androidx-core = {module = "androidx.core:core-ktx", version.ref = "androidx-core"}
androidx-compose-ui = { module = "androidx.compose.ui:ui", version.ref = "androidx-compose" }
androidx-compose-ui-tooling = { module = "androidx.compose.ui:ui-tooling", version.ref = "androidx-compose" }
androidx-compose-foundation = { module = "androidx.compose.foundation:foundation", version.ref = "androidx-compose" }
androidx-compose-material = { module = "androidx.compose.material:material", version.ref = "androidx-compose" }
androidx-compose-material-icons-core = {module = "androidx.compose.material:material-icons-core", version.ref = "androidx-compose"}
androidx-compose-material-icons-extended = {module = "androidx.compose.material:material-icons-extended", version.ref = "androidx-compose"}
androidx-compose-runtime-livedata = {module = "androidx.compose.runtime:runtime-livedata", version.ref = "androidx-compose"}
androidx-compose-runtime-rxjava2 = {module = "androidx.compose.runtime:runtime-rxjava2", version.ref = "androidx.compose"}
androidx-compose-ui-test = {module = "androidx.compose.ui:ui-test-junit4", version.ref = "androidx.compose"}
androidx-lifecycle = {module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "androidx-lifecycle"}

ktor-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" }
ktor-logging = { module = "io.ktor:ktor-client-logging", version.ref = "ktor" }
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" }
kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinx-coroutines" }
napier = { module = "io.github.aakira:napier", version.ref = "napier" }
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization" }
multiplatform-settings = { module = "com.russhwolf:multiplatform-settings", version.ref = "multiplatform-settings" }
ktor-client-okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "ktor" }
ktor-client-ios = { module = "io.ktor:ktor-client-ios", version.ref = "ktor" }
ktor-client-js = { module = "io.ktor:ktor-client-js", version.ref = "ktor" }
voyager-navigator = { module = "cafe.adriel.voyager:voyager-navigator", version.ref = "voyager" }
koin-core = { module = "io.insert-koin:koin-core", version.ref = "koin" }
koin-android = { module = "io.insert-koin:koin-android", version.ref = "koin" }
coil-compose = { module = "io.coil-kt:coil-compose", version.ref = "coil" }
activity-compose = { module = "androidx.activity:activity-compose", version.ref = "activity-compose" }
accompanist-insets = { module = "com.google.accompanist:accompanist-insets", version.ref = "accompanist" }
accompanist-swiperefresh = { module = "com.google.accompanist:accompanist-swiperefresh", version.ref = "accompanist" }
work-runtime-ktx = { module = "androidx.work:work-runtime-ktx", version.ref = "work-runtime-ktx" }
desugar-jdk-libs = { module = "com.android.tools:desugar_jdk_libs", version.ref = "desugar-jdk-libs" }
androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompat"}

[bundles]
plugins = ["plugin-android", "plugin-kotlin",  "plugin-kotlin-serialization", "plugin-gver"]
  • build.gradle.kts
    いろいろとやり方があると思いますが。
    ライブラリのバージョン管理も導入します。(plugins{}でben-manes.versionsを指定)
    ややこしいですが、この辺がややこしいです。
    まず一旦この時点でbuild.gradle(shared)のすべてのコードを削除しておきます。
    import文、tasks.withType、dependencies {classpath(libs.bundles.plugins)}を除してから、syncします。
    次に、import文、tasks.withTypeを加えて、syncします。
    その後dependencies {classpath(libs.bundles.plugins)}を加えてsyncし、build.gradle(shared)を復活させます。
import com.github.benmanes.gradle.versions.updates.DependencyUpdatesTask

buildscript {
    repositories {
        gradlePluginPortal()
        google()
        mavenCentral()
    }
    dependencies {
        classpath(libs.bundles.plugins)
    }
    extra["versions"] = mapOf(
        "compose_version" to "1.0.1"
    )
}

plugins {
    id ("com.android.application") version "7.1.1" apply false
    id ("com.android.library") version "7.1.1" apply false
    kotlin("android") version "1.5.31" apply false
    id ("com.github.ben-manes.versions") version "0.42.0"
}

tasks.register("clean", Delete::class) {
    delete(rootProject.buildDir)
}

fun isNonStable(version: String): Boolean {
    val stableKeyword = listOf("RELEASE", "FINAL", "GA").any { version.toUpperCase().contains(it) }
    val regex = "^[0-9,.v-]+(-r)?$".toRegex()
    val isStable = stableKeyword || regex.matches(version)
    return isStable.not()
}

tasks.withType<DependencyUpdatesTask> {
    rejectVersionIf {
        isNonStable(candidate.version) && !isNonStable(currentVersion)
    }
}

build.gradle(androidApp)

val versions : Map<String, String> by project

plugins {
    id("com.android.application")
    kotlin("android")
}

android {
    compileSdk = 32
    defaultConfig {
        applicationId = "com.example.playground.android"
        minSdk = 29
        targetSdk = 32
        versionCode = 1
        versionName = "1.0"
    }
    buildTypes {
        getByName("release") {
            isMinifyEnabled = false
        }
    }
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = "1.8"
    }
    buildFeatures {
        compose = true
    }
    composeOptions {
        kotlinCompilerExtensionVersion = "1.2.0-alpha04"
    }
    packagingOptions {
        exclude("META-INF/AL2.0")
        exclude("META-INF/LGPL2.1")
    }
}

dependencies {
    implementation(project(":shared"))
    implementation(libs.androidx.appcompat)
    implementation(libs.androidx.compose.ui)
    implementation(libs.androidx.compose.ui.tooling)
    implementation(libs.androidx.compose.foundation)
    implementation(libs.androidx.compose.material)
    implementation(libs.androidx.compose.material.icons.core)
    implementation(libs.androidx.compose.material.icons.extended)
    implementation(libs.androidx.compose.runtime.livedata)
    implementation(libs.androidx.compose.runtime.rxjava2)
    implementation(libs.androidx.compose.ui.test)
    implementation(libs.activity.compose)
    implementation(libs.androidx.core)
    implementation(libs.androidx.lifecycle)
}
  • コードを書く
    自動で生成されるMainActivityのコードはcomposeでないので、composeに直す。
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0