Kotlin MultiplatformでAndroidアプリを作ってみる

## 最初に

これからHotになっていくんじゃないかと思っているKotlin MultiplatformでAndroidアプリを作ってみました。最初の設定で少し躓いたのでまとめようと思いました。

<img width="1153" alt="Screen Shot 2019-04-01 at 0.07.36.png" src="https://qiita-image-store.s3.amazonaws.com/0/152911/22bdc10b-7968-26ff-d4d4-21b7253fcd92.png">

ちょっとずつ来てる・・・？だがしかし、

<img width="1153" alt="Screen Shot 2019-04-01 at 0.14.26.png" src="https://qiita-image-store.s3.amazonaws.com/0/152911/4112db2b-11c9-8f28-e80e-54f7e2518e80.png">

他強すぎワロタwww
だがやっていきます。。。

## Kotlin Multiplatformとは
Kotlinでcross platform開発しましょうというためのツール。似たようなのだとXamarin、React Native、Flutterなど。他のツールは詳しく知らないので、比較は出来ないが自分が思うメリットは

- Android開発者なので、Kotlinベースで何かができるのが嬉しい。（最大の強み）
- そもそもcross platformのために、新しい言語を覚えるのが嫌。（Swiftは少し書けるので、新しい言語学習には当たらなかった。）
- UI部分は、iOS/Androidでテイストがそもそも違うので、そこを一つにする意味をあまり感じてなかった。
- APIを繋ぐ式のcross platformはネイティブのアップデートにすぐ追いつけない気がして、最新のAPIが使えないのは嫌だった。（これどうなんだろう）

です。
こんな感じで、Kotlin Multiplatformに手を出してみました。

## 環境
Kotlinの公式だと、Android Studio 3.2、Gradle 4.7、Kotlin 1.3.21でやってました。
Kotlinは、1.3.21以上じゃないとダメらしい。AndroidのPreferencesからupdate出来ます。

Android Studio
<img width="1124" alt="Screen Shot 2019-04-01 at 0.37.09.png" src="https://qiita-image-store.s3.amazonaws.com/0/152911/c59a3c2a-b228-80b6-7c7e-2b8d7ee092cc.png">

Gradle/Kotlin
<img width="709" alt="Screen Shot 2019-04-01 at 0.45.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/152911/c41be247-ec5a-4db4-eaca-733ef06a9085.png">

## 手順

1. Android StudioでNew Projectする。
2. アプリの初期設定は、こんな感じ。
<img width="1012" alt="Screen Shot 2019-04-01 at 0.39.47.png" src="https://qiita-image-store.s3.amazonaws.com/0/152911/9319dc59-0e47-baa2-0954-244cded9ea17.png">
3. File -> New -> New ModuleでJava Libraryを選択。Library nameは、SharedCodeで、Class nameは、デフォルトのMyClassにしました。
4. Moduleが生成されたあと、SharedCode/build.gradleを下記のように編集。（JavaからKotlinに変更）

```build.gradle
apply plugin: 'kotlin-multiplatform'


kotlin {
    targets {
        final def iOSTarget = System.getenv('SDK_NAME')?.startsWith("iphoneos") \
                              ? presets.iosArm64 : presets.iosX64

        fromPreset(iOSTarget, 'iOS') {
            compilations.main.outputKinds('FRAMEWORK')
        }

        fromPreset(presets.jvm, 'android')
    }

    sourceSets {
        commonMain.dependencies {
            api 'org.jetbrains.kotlin:kotlin-stdlib-common'
        }

        androidMain.dependencies {
            api 'org.jetbrains.kotlin:kotlin-stdlib'
        }
    }
}

// workaround for https://youtrack.jetbrains.com/issue/KT-27170
configurations {
    compileClasspath
}
```

5.<プロジェクトのルートディレクトリ>/SharedCode/src以下に
- androidMain/kotlin
- commonMain/kotlin
- iosMain/kotlin
というディレクトリを作ります。その後、すでにあるmainディレクトリを削除します。
6. actual.ktとcommon.ktを以下のように作成します。
こんな感じ。
<img width="582" alt="Screen Shot 2019-04-01 at 2.52.47.png" src="https://qiita-image-store.s3.amazonaws.com/0/152911/3891f90d-e3db-d358-16d5-8666949e0a8a.png">
それぞれ以下の様に編集。

```androidMain/kotlin/actual.kt
package com.example.sharedcode

actual fun platformName(): String {
    return "Android"
}
```

```commonMain/kotlin/common.kt
package com.example.sharedcode

expect fun platformName(): String

fun createApplicationScreenMessage() : String {
    return "Kotlin Rocks on ${platformName()}"
}
```

```iosMain/kotlin/actual.kt
package com.example.sharedcode

actual fun platformName(): String {
    return "iOS"
}
```

7.プロジェクトビューのappディレクトリ上で右クリック->Open Module SettingsからSharedCodeをimportする。（この図は入れた後なので:SharedCodeがすでに一覧に追加されています。）
<img width="818" alt="Screen Shot 2019-04-01 at 2.58.52.png" src="https://qiita-image-store.s3.amazonaws.com/0/152911/59175231-a9ba-44cd-ae5d-80a351e5c5a9.png">

8.activity_main.xmlのTextViewにid(main_text)を振って、MainActivity.ktを以下の様に編集。

```MainActivity.kt
package com.example.kotlin_multiplatform

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView
import com.example.sharedcode.createApplicationScreenMessage

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)


        findViewById<TextView>(R.id.main_text).text = createApplicationScreenMessage()
    }
}
```
Lintエラーが出ないはず。
9. これでBuildすれば完成！


## 結論

一応動かせるところまでは出来たけど、プロジェクトビュー を綺麗に展開出来なかったり、ライブラリの問題があったりなど、まだまだ発展途上な感じがすごい。
けど引き続き使っていきたいと思います。今度iOS版も出来たらいいかなと思います。

## 参考

- Kotlinの公式Tutorial

<https://kotlinlang.org/docs/tutorials/native/mpp-ios-android.html>

- Mercariのエンジニアさんの記事

<https://tech.mercari.com/entry/2018/12/18/114010>

- Qiita記事

<https://qiita.com/takahirom/items/4df7bfca17928a40922e>
<https://qiita.com/irgaly/items/eebd1273b38e1e671fcf>