Premiers pas avec Kotlin Multiplatform

1. Avant de commencer

Prérequis

  • Vous devez savoir créer des applications Jetpack Compose.
  • Vous maîtrisez le langage Kotlin.
  • Vous disposez de connaissances de base concernant la syntaxe Swift.

Ce dont vous avez besoin

Points abordés

  • Comprendre les principes de base de Kotlin Multiplatform.
  • Comment partager du code entre les plates-formes.
  • Comment associer le code partagé sur Android et iOS.

2. Configuration

Pour commencer, procédez comme suit :

  1. Clonez le dépôt GitHub :
$ git clone https://github.com/android/codelab-android-kmp.git

Vous pouvez aussi télécharger le dépôt sous forme de fichier ZIP :

  1. Dans Android Studio, ouvrez le projet get-started, qui contient les branches suivantes :
  • main : contient le code de démarrage de ce projet, que vous allez modifier tout au long de l'atelier.
  • end : contient le code de solution pour cet atelier.

Cet atelier de programmation commence par la branche main. Vous pouvez suivre l'atelier de programmation étape par étape, à votre propre rythme.

  1. Si vous souhaitez voir le code de solution, exécutez la commande suivante :
$ git clone -b end https://github.com/android/codelab-android-kmp.git

Vous pouvez également télécharger le code de solution :

Installer XCode

Pour créer et exécuter la partie iOS de cet atelier de programmation, vous avez besoin de Xcode et d'un simulateur iOS :

  1. Installez Xcode depuis l'App Store pour Mac (vous avez besoin d'un compte Apple).
  2. Une fois l'installation terminée, lancez Xcode.
  3. Une boîte de dialogue s'affiche pour indiquer quels composants sont intégrés et lesquels vous devez télécharger. c4aba94d795dabee.png
  4. Vérifiez que vous disposez d'iOS 18.4 (ou version ultérieure).
  5. Cliquez sur "Télécharger et installer".
  6. Attendez que les composants soient installés.

Cet atelier de programmation a été testé avec Xcode 16.3. Si vous utilisez une autre version de Xcode et que vous rencontrez des problèmes, nous vous recommandons de télécharger la version exacte mentionnée dans cet atelier de programmation.

Application exemple

Ce codebase contient à la fois une application Android créée avec Jetpack Compose et une application iOS créée avec SwiftUI. Le projet Android se trouve dans le dossier androidApp/, tandis que le projet iOS se trouve dans le dossier iosApp/, qui contient également le fichier KMPGetStartedCodelab.xcodeproj à exécuter avec Xcode.

3. Présentation de Kotlin Multiplatform

Kotlin Multiplatform (KMP) vous permet d'écrire du code une seule fois et de le partager sur plusieurs plates-formes cibles, telles qu'Android, iOS, le Web et les ordinateurs. En utilisant KMP, vous pouvez réduire la duplication de code, assurer la cohérence et réduire considérablement le temps et les efforts de développement.

KMP ne dicte pas la quantité ni les parties de votre codebase que vous devez partager. C'est à vous de décider quelles parties du code valent la peine d'être partagées.

Choisir les éléments à partager

Ce code partagé vous permet de garantir la cohérence et de réduire les duplications sur les différentes plates-formes. De nombreuses équipes mobiles commencent par partager un ensemble distinct de logiques métier (par exemple, accès à la base de données, accès au réseau, etc.) et les tests associés, puis partagent du code supplémentaire au fil du temps.

De nombreuses bibliothèques Android Jetpack sont compatibles avec KMP. Les bibliothèques Jetpack qui ont été rendues multiplateformes offrent plusieurs niveaux de compatibilité en fonction de la plate-forme cible. Pour obtenir la liste complète des bibliothèques et de leurs niveaux de compatibilité, consultez la documentation.

Par exemple, l'une des bibliothèques compatibles, la bibliothèque de base de données Room, est compatible avec Android, iOS et les ordinateurs. Cela vous permet de transférer la création de la base de données et la logique de base de données associée vers un module KMP partagé commun tout en conservant l'autre code natif sur les deux plates-formes.

Une autre étape possible après la migration de la base de données consiste à partager d'autres logiques de domaine. Vous pouvez également envisager d'utiliser la bibliothèque multiplateforme ViewModel d'Android Jetpack.

Écrire du code spécifique à une plate-forme

Kotlin Multiplatform introduit de nouvelles techniques pour implémenter des fonctionnalités spécifiques à la plate-forme.

Déclarations attendues et réelles

La fonctionnalité de langage Kotlin expect actual est conçue pour prendre en charge le codebase multiplate-forme Kotlin avec une compatibilité IDE complète.

Cette approche est idéale lorsque le comportement propre à la plate-forme peut être encapsulé dans une seule fonction ou classe. Il s'agit d'un mécanisme flexible et puissant. Par exemple, une classe expect commune peut avoir des équivalents actual spécifiques à la plate-forme avec des modificateurs de visibilité plus ouverts, des super-types supplémentaires, ou différents types de paramètres ou modificateurs. Ces types de variations ne serait pas possible avec une API d'interface stricte. De plus, expect actual est résolu de manière statique, ce qui signifie que l'implémentation spécifique à la plate-forme est appliquée au moment de la compilation.

Interface et implémentations en Kotlin

Si les deux plates-formes doivent suivre des API similaires, mais avec des implémentations différentes, vous pouvez définir une interface dans le code partagé comme alternative aux déclarations attendues et réelles. Cette approche vous permet d'utiliser différentes implémentations de test ou de passer à une autre implémentation au moment de l'exécution.

De plus, les interfaces ne nécessitent aucune connaissance spécifique en Kotlin, ce qui rend cette option accessible aux développeurs qui connaissent les interfaces dans d'autres langages.

Interface en code partagé commun, implémentation en code natif (Android ou Swift).

Dans certains cas, vous devez écrire du code qui n'est pas disponible à partir du code KMP. Dans ce cas, vous pouvez définir une interface dans le code partagé, l'implémenter pour Android en Kotlin et fournir un équivalent iOS en Swift. En règle générale, les implémentations natives sont ensuite injectées dans le code partagé, soit par injection de dépendances, soit directement. Cette stratégie permet de personnaliser l'expérience sur chaque plate-forme tout en conservant une interface commune pour le code partagé.

4. Ouvrir le projet Xcode depuis Android Studio

Une fois Xcode installé, assurez-vous de pouvoir exécuter l'application iOS.

Vous pouvez ouvrir le projet iOS directement depuis Android Studio.

  1. Passez au volet "Projet" pour utiliser la vue Projet. 4f1a2c2ad988334c.png
  2. Recherchez le fichier KmpGetStartedCodelab.xcodeproj dans le dossier [root]/iosApp/ 1357ffb58fe05180.png
  3. Effectuez un clic droit sur le fichier, puis sélectionnez Ouvrir dans et Ouvrir dans l'application associée. L'application iOS s'ouvre alors dans Xcode. f93dee415dfd40e9.png
  4. Exécutez le projet dans Xcode en appuyant sur ⌘+R ou en accédant au menu "Produit" et en sélectionnant "Exécuter".

fff7f322c13ccdc0.png.

5. Ajouter un module KMP

Pour ajouter la prise en charge de KMP à votre projet, commencez par créer un module shared pour le code qui sera réutilisé sur plusieurs plates-formes (Android, iOS).

Android Studio permet d'ajouter un module Kotlin Multiplatform à l'aide de son modèle de module partagé KMP.

Pour créer le module KMP dans Android Studio :

  1. Accédez à File > New > New Module > Kotlin Multiplatform Shared Module (Fichier > Nouveau > Nouveau module > Module partagé Kotlin Multiplatform).
  2. Remplacez le package par com.example.kmp.shared.
  3. Cliquez sur Finish (Terminer). 4ef605dcc1fe6301.png
  4. Une fois la création du module terminée et la synchronisation de Gradle terminée, un nouveau module shared apparaît dans le projet. Pour voir la vue ci-dessous, vous devrez peut-être passer de la vue Android à la vue Projet.

eb58eea4e534dab2.png

Le module partagé généré par le modèle de module partagé KMP inclut des fonctions et des tests d'espace réservé de base. Ces espaces réservés permettent de s'assurer que le module est compilé et exécuté correctement dès le début.

Important : N'oubliez pas la différence entre le dossier iosApp et le dossier iosMain. Le dossier iosApp contient le code de l'application iOS autonome, tandis que iosMain fait partie du module KMP partagé que vous venez d'ajouter. iosApp contient du code Swift, tandis que iosMain contient du code KMP spécifique à la plate-forme iOS.

Tout d'abord, vous devez associer le nouveau module partagé en tant que dépendance dans le module Gradle :androidApp pour permettre à l'application d'utiliser le code partagé :

  1. Ouvrez le fichier androidApp/build.gradle.kts.
  2. Ajoutez la dépendance du module shared dans le bloc de dépendances comme suit :
dependencies {
    ...
    implementation(projects.shared)
}
  1. Synchronisez le projet avec ses fichiers Gradle. c4a6ca72cf444e6e.png

Vérifier l'accès au code du module shared

Pour vérifier que l'application Android peut accéder au code du module shared, nous allons effectuer une simple mise à jour de l'application.

  1. Dans le projet KMPGetStartedCodelab, ouvrez le fichier MainActivity à l'emplacement androidApp/src/main/java/com/example/kmp/getstarted/android/MainActivity.kt.
  2. Modifiez le composable Text du contenu pour inclure les informations platform() dans la chaîne affichée.
Text(
  "Hello ${platform()}",
)
  1. Appuyez sur ⌥(option)+return sur votre clavier, puis sélectionnez Import function 'platform'da301d17884eaef9.png.
  2. Créez et exécutez l'application sur un appareil Android ou un émulateur.

Cette mise à jour vérifie si l'application peut appeler la fonction platform() à partir du module shared, qui doit renvoyer "Android" lorsqu'elle s'exécute sur la plate-forme Android.

9828afe63d7cd9da.png

6. Configurer le module partagé dans l'application iOS

Swift ne peut pas utiliser directement les modules Kotlin comme le font les applications Android. Il nécessite la production d'un framework binaire compilé (bundle XCFramework). Un bundle XCFramework est un package binaire qui inclut les frameworks et les bibliothèques nécessaires à la compilation pour plusieurs plates-formes Apple.

Distribution de la bibliothèque partagée

Le nouveau modèle de module dans Android Studio a déjà configuré le module partagé pour produire un framework pour chacune des architectures iOS. Vous trouverez le code suivant dans le fichier build.gradle.kts du module shared.

val xcfName = "sharedKit"

iosX64 {
  binaries.framework {
    baseName = xcfName
  }
}

iosArm64 {
  binaries.framework {
    baseName = xcfName
  }
}

iosSimulatorArm64 {
  binaries.framework {
    baseName = xcfName
  }
}

Cette étape consiste à configurer Xcode pour exécuter un script afin de générer le framework Kotlin et à appeler la fonction platform() dans l'application iOS.

Pour utiliser la bibliothèque partagée, vous devez associer le framework Kotlin au projet iOS en procédant comme suit :

  1. Ouvrez le projet iOS (le répertoire iosApp mentionné précédemment) dans Xcode, puis ouvrez les paramètres du projet en double-cliquant sur le nom du projet dans le navigateur de projets. 94047b06db4a3b6f.png
  2. Dans l'onglet Phases de compilation des paramètres du projet, cliquez sur +, puis sélectionnez Nouvelle phase d'exécution de script. Une nouvelle phase "Exécuter le script" est ajoutée après toutes les autres phases. d4907a9cb0a5ac6e.png
  3. Double-cliquez sur le titre Exécuter le script pour le renommer. Remplacez le nom par défaut Exécuter le script par Compiler le framework Kotlin pour que la fonction de cette phase soit compréhensible.
  4. Développez la phase de compilation, puis saisissez le code du script dans le champ de texte sous Shell :
cd "$SRCROOT/.."
./gradlew :shared:embedAndSignAppleFrameworkForXcode

7b6a393e44ddbe60.png

  1. Faites glisser la phase Compiler le framework Kotlin avant la phase Compiler les sources. 27dbe2cf958c986f.png
  2. Compilez le projet dans Xcode en appuyant sur ⌘+B ou en accédant au menu Produit et en sélectionnant Compiler. Notez que la progression de la compilation s'affiche au-dessus de Xcode. bb0f9cb0f96d1f89.png

Si tout est configuré correctement, le projet sera compilé avec succès.

bb9b12d5f6ad0bac.png

En définissant la phase de compilation du script d'exécution de cette manière, vous pouvez compiler votre projet iOS à partir de Xcode sans avoir à passer à un autre outil pour compiler le module partagé.

Vérifier l'accès au code du module shared

Pour vérifier que l'application iOS peut accéder au code du module shared, vous allez effectuer la même mise à jour simple que pour l'application Android.

  1. Dans le projet iOS, dans Xcode, ouvrez le fichier ContentView.swift dans le répertoire Sources/View/ContentView.swift.
  2. Ajoutez import sharedKit en haut du fichier.
  3. Modifiez la vue Text pour inclure les informations Platform_iosKt.platform() dans la chaîne affichée avec \(Platform_iosKt.platform()).

Voici le résultat final du fichier :

import SwiftUI
import sharedKit 

struct ContentView: View {
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            
            Text("Hello, \(Platform_iosKt.platform())!")
        }
        .padding()
    }
}
  1. Exécutez l'application en appuyant sur ⌘+R ou accédez au menu Produit et cliquez sur Exécuter.

Cette mise à jour vérifie si l'application iOS peut appeler la fonction platform() à partir du module partagé, qui doit renvoyer "iOS" lorsqu'elle s'exécute sur la plate-forme iOS.

8024b5cc4bcd3f84.png

7. Ajouter Swift/Kotlin Interface Enhancer (SKIE)

Par défaut, l'interface native que produit Kotlin est un en-tête Objective-C. Swift est directement compatible avec Objective-C, mais Objective-C n'inclut pas toutes les fonctionnalités modernes de Swift ou de Kotlin.

C'est également la raison pour laquelle, dans l'exemple précédent, vous ne pouviez pas utiliser l'appel platform() directement dans le code Swift. KMP ne peut pas générer de fonction globale, car Objective-C ne prend pas en charge les fonctions globales, mais uniquement les fonctions statiques encapsulées dans une classe. C'est pourquoi vous devez ajouter Platform_iosKt.

Pour rendre l'interface plus adaptée à Swift, vous pouvez utiliser l'outil Swift/Kotlin Interface Enhancer (SKIE) afin d'améliorer l'interface Swift du module :shared.

Les caractéristiques communes de SKIE sont les suivantes :

  • Amélioration de la prise en charge des arguments par défaut
  • Amélioration de la prise en charge des hiérarchies scellées (sealed class, sealed interface)
  • Amélioration de la prise en charge de enum class avec une gestion exhaustive dans les instructions switch.
  • Interopérabilité entre Flow et AsyncSequence
  • Interopérabilité entre suspend fun et async func
  1. Ajoutez le plug-in Gradle co.touchlab.skie au fichier libs.versions.toml :
[versions]
skie = "0.10.1"

[plugins]
skie = { id = "co.touchlab.skie", version.ref = "skie" }
  1. Ajoutez le plug-in au fichier build.gradle.kts racine.
plugins {
   ...
   alias(libs.plugins.skie) apply false
}
  1. Ajoutez le plug-in au fichier build.gradle.kts du module :shared :
plugins {
   ...
   alias(libs.plugins.skie)
}
  1. Gradle synchronise le projet.

Supprimer l'appel de fonction statique

Lorsque vous recréez l'application iOS, vous ne remarquerez peut-être pas immédiatement de changement, mais vous pouvez supprimer le préfixe Platform_iosKt et laisser la fonction platform() agir comme une fonction globale.

Text("Hello, KMP! \(platform())")

Cela fonctionne, car SKIE (entre autres fonctionnalités) exploite les notes de l'API Swift, qui ajoutent des informations sur les API pour mieux les utiliser à partir du code Swift.

8. Félicitations

Félicitations, vous venez d'ajouter le premier code Kotlin Multiplatform partagé à des projets Android et iOS. Bien qu'il ne s'agisse que d'un point de départ minimal, vous pouvez maintenant commencer à découvrir des fonctionnalités et des cas d'utilisation plus avancés pour le partage de code avec KMP.

Étapes suivantes

Découvrez comment utiliser Jetpack Room pour partager une couche de données entre Android et iOS dans le prochain atelier de programmation.

En savoir plus