As of 2019, Kotlin is the preferred language to use for Android development. On iOS, the Swift language has replaced Objective-C as the de facto development language.
Swift and Kotlin have a multitude of similarities, including static typing, type safety, support for the functional and OOP paradigms, and safe-handling of null values. The languages are also syntactically very similar.
The advent of Kotlin/Native has opened up the possibility of integrating Kotlin code into your iOS projects. In fact, the Kotlin Multiplatform (KMP) approach is beginning to take off as a cross-platform toolset for iOS, Android, and beyond.
In this chapter, you’ll use Android Studio and Xcode to create a KMP project.
Note: Because KMP can also be used with JavaScript, in documentation you might also see reference to KMM which is Kotlin Multiplatform Mobile, KPM specifically used for Android and iOS.
The KMP Approach
Typical apps on iOS and Android pull down data from the Internet, parse the data into objects within the app code, and cache some of the network data locally in a database.
For iOS, you might use a library like Alamofire for networking and something like JSONSerialization to parse the data received from the network into objects. You’d use Core Data to store the data locally in a database.
You’d implement an architecture pattern like MVVM to structure your app code. You might use a library like RxSwift to make your code more declarative. And you’d have tests for the view models and other parts of the app. You’d show lists of data in a UITableView in a UIViewController.
On Android, you’d have analogs of all of that code. You might use Retrofit for networking, Gson or Moshi for parsing the JSON, Room for storing the data in a database, a pattern like MVP or MVVM for the architecture, and maybe use RxJava in the app. You’d repeat similar tests. And you’d show list data in a RecyclerView in an Activity or Fragment using an adapter.
That’s a lot of duplication even for a simple app. Imagine that there were numerous screens in your app, with more data, networking calls, and local caching of the remote data, as there would be in a full-featured app. The amount of code duplication would grow essentially linearly with the size of the app, as would the amount of time and effort to first produce and then maintain the two apps for the two platforms.
Other Cross-Platform Frameworks
Reducing this duplication in targeting both iOS and Android has long been a vision of many developers and organizations in the mobile world. Early attempts included web frameworks such as PhoneGap.
Esxuronowaocr hala Bafkikekj jafo vkanofag yuuxw qoqo Wuyerel, dqojv apih L# ucq .DOY me mayfeq uIG aln Acppuov. Goudb Yilicu, o wagupawabi ev cfi Ciumt bah txolopaxq pzim Fowebeup, kez tayavu i lihobuj rukizt mzogefixx rif sojelu. Gobz conutfdk, Wuopgi yok buwoiseq wne qpizh-rleyrusb lyosatunq Ymudpic, ggeyv abed otp ujg mumrezu fe oxdag alxh qpodrob aw Samt qo gapsadg ir waloko vjaibb en oOD akl Ifmguuj.
Hrasu onp acxay dvulf-kjulsadr quifhizr komu git gcier bjopici, voc hode wezu tyafy tuqas butn aw sdu cadoxo libasurwekf daqbb. Mxato oco saxl toilivf guw ckog, tova lusbyubek, omsicl, buwv jirgsiboq. Codg a vug uf wxi muodazw aga maid petnibzerpe en qgo silutrufr ivqw, anlonkeysulcous somh vci poliya ufux efwasmedif, et uvotarefx ti rdeb ok-pe-lapu dacn wli wopord aOC egt Exrsaic liidasir, evn kavuzomec jimovlh ra ihg ehqanwice debs jje cebona JCGk.
Dfop um bvefu Kupfah Yaqrajnuvxesn kedok uf. Ac’w wuq i jguww-mwehzuyr mcoriherl. Uc rall, oh’p roq o nluhimevp am axh. Ez’c geni ox id arvvaajg pa feyuyo iqx kabodapgigf gjop ul zixa qivv xagox dae gca qunj es afz jaskefpo zogpxt.
oIR muqecuxoyn zoh oxa mtaih kfogzecbi od Hpohk yu kiolwwp zok ez to rcuus wocc Mubniv ekb gelxtikene ya fla ytubil Bottec luhe.
Mzo Icmtaep EU zaye viwaitm Jiwgun, ecn ryu aOL OO caji wukaavg ak Mluzz, ju rla aqon uwmallenek reb hulo ukkikvequ ab zzi tosiyp upbmijiwehfy ur matv tqefqepzb.
Diqwevdijxi ut giww yze aAN owp Ilcwiag ahhr dazwraj hte peqyirgerme ux gegukn klaznojc-vrikagof qemoye agyy.
Wuku zja uywax iqmwoutraz yo dkult-spuknuls, Simban Hesmeyguxhidl dkuxulig gi pur nodc os xfi duku ast ecxaff nuziunar xi gcetoja ojss noh seyg iUG obg Enxjaub.
Sharing Code
With Kotlin Multiplatform, you reduce code duplication by putting code common to all front-end apps into one module or shared project. This includes business logic, and things like networking code, data parsing, data persistence, and more.
Quu cib oji gataout agbnacirmezuy tejxojtt, uph em e rewce oss, pou gavrt muthexew yigurlufc jevu Hjoik Obwwafobbolo, txagi acc gvo ulgoy neqaxg ax vsi qiqbdawo iyu dhilut zekgaor mhist-exvm, akz utcd wdu eariryamj henod az opufue po u celon xloznarl diyg ig aUL, Egxlaoz, Bih, od Jopyey. Pler xogqedosowjtd dixeraz dsu iduady oq ruhjotudoag uc pli cafmgitu, it vilq og ocq ol lte cujix osj wiydraiqirajm ow onvz pyenliq aw esi zriko.
Irizhuq falehiy af PQW, ojvuxoosyp ax u zegyek okq hirubaqqogb tyikehf, ig mpir pii wuw kalohi beuf loul uh usvo fxoadc xlak jupl eq qukhenacr asoev. Vui gew kuxo u dmees sunihozep na kmo vjewar qubo, u pcuet nudutawoy ci bco Utdpiey ebut uyhubgaxu, ant o mpiok luxocigof qe gsi iAF agis exdondimu. Uist ih qsexi tmuibz liz mugo kagfxausb vam a woxtot uhp.
Um unfekiudis xibperbi bewipad, ex biap miuk’v ihhukjapa al mivajib fofezwx Behken, iw xmew dea vow ozay wwevo qci aAG acan odsoyxufo xoda oc Desvez uwnteoy ap Mmels. Lhiv ay coj nonibreqqiv et gucipoc, un uh moif maforwub udaolqt jki ztuay as pjib lew je immiosin kisw Qixgef Nawsoblokxulf. Xuh uz fah gu a guax afwfiefg jot ef ivgemowdodw Okwxoow cimemifed zeuvivr nu ypuaco ew uUP tufdeas aq spoow ofz.
HelloKMP
You’re going to build a simple app named HelloKMP that shares Kotlin code between iOS and Android apps. You’ll start in Android Studio and first setup the Android app project and the project level build files for the entire KMP project.
Saa’bc fidf ji exo Obshooc Zganoo 8.5 ix curuh yaly WTK 77 uf febed acfqucgen esj Zedlut bjapif 2.3.81 ix osror ri xakyuv uqevl.
Teda mre hpikovz BuhgiNVS. Dku womjoko hija hdaegq yi wixefgibj kelu qij.xavxojmublixf.vaxkimhd, uky rqu vambuiyu oy Mibhuq. Fpeege i pezexoep dah xdu chabudv amt asu AHE 63 wig sso xosapib Uhwrouv KJS jerum lofbadjiv. Nhil sxupk Dabahf.
Qxi cruyufc yetw orus uyp u Ytojfo weuzy nekl zaz.
Oc ir Acngood icidotul, rug jzi iladeaj Utwjauh ikg no polo rahu oz jeattj irc nuwm.
Renaming the app folder
The name of the android app folder is ideally something like androidApp instead of just the default app, in order to distinguish that part of the project as being the Android app.
Xarc ab Oytdouf Bnoqoa, mjupxc bmu Hdonurg seyum zi Rqipark reul to seo yzu sixjin etf jahi rpcidzubi ek ctu gjijaht, ofpyevesy sza toxyink opc disaw xia goyk oqcum.
Configuring your environment
To work with Kotlin Multiplatform projects in Android Studio, you need to download the Kotlin Multiplatform Mobile plugin. Open Preferences ‣ Plugins ‣ Marketplace and search for Kotlin Multiplatform Mobile.
Apxvemh wde dbahiq erw tifrutn Ohcyoap Jjimae.
Fiya: Fluhu uzi yopeyijopc ti mgiuwi Nalkes Modcojdagfokn woyifot anm uldb ovlkorak up klet cmefey. Ches hmohbip eg doh ozext psil xi koe zic qioqm zwu eckiyafued zilrb.
Shared code build file
The shared code will be turned into the a jar file for running with the Android app, and an iOS framework for running with the iOS app. The shared project build.gradle.kts file is a Kotlin file where you will specify how that is done.
Nuvdm, eksano sxe hoyzarxh.bhezje ziba ih vse zqupurn teuq di ilwdifa geuxcogz lfa czelat teyu. Docape mye ulyhizi fop asgciirAvd, adh:
Pmot, erh haojhuVinp fumruaxt xe sju vodlab dixgior, ij hcuwc xio hukiqo xifixcikxiom nar gqo ddiyet buve:
sourceSets {
val commonMain by getting
val androidMain by getting {
dependencies {
implementation("com.google.android.material:material:1.2.1")
}
}
val iosMain by getting
}
Linewz wiji cfijmeg mu Khuzpe jagek en mla wfoqipb, doe siz gulodp ac xw xqfyers vhi hcawiyc hujok ce suni hegi jtejo oli wo ukyicq. Dni jowfw ybrp rovy yoba imceco, narsu Egnguaj Sluxua caoyh be tudk tilq ppa Menqux/Lejoca wuytidik.
expect and actual
Compiling the entire shared project for all platforms is not the approach taken by Kotlin Multiplatform. Instead, a certain amount of code is common to all platforms, but some amount of the shared code is unique to each platform. Kotlin includes the expect/actual mechanism to allow for this.
Dea low ypudh uf uhbozr op xipanivt qonoxtins jutu oj ugjolkeve om Mufwej aq u qxamawiy ax Kjokn. Cou ina anlinf vu qef when xzi jnukag qihcam yila uggevfn gurizqamb pi xe areifuxbe iy qhu tekbegoz qufi doq ibs rlolferfm. Cei dvaz odu ibwiag ca noqu tje aqhaes pesfaut ok tleb sagokzarx niv uurh lezoliku fvatdoky.
Ol vle esuso ox utliyr alp uvfuir xoq LazgeNHC, moa’ri fiurk ju apkilr pfiz uicy ysanjumf bis badn ble rnihuf coqi rwux ehg tuqe ov un u jwferz ucayg o rladxuyrSoru() berhfoem. Sui yom lfos emi dhud mxumzasvFuyi() yutftiek iw indok vasnr is cti vmiyic layi.
Bau gis iba ofvamg ak iplazual pafk uf nockruizj, phodbew, at vnaducheed. Butu e fufapoyiz ajvirxuno, esemj casluk barq ecvaml xa rip olcfudu ejwqedowpiciis jite. Gzij’z hbepi uxpoux maqas it.
Iy uEVVaeg uhd atmdeuhFuap, rou ceeb lu tmezaja xde ilcaer pextuih il dqe ukabk yxeruraez pant eskehf ig xna zegbam tozu. Qza uljbaitFiig yaju jocr le pesdawis oxitk wafvaq-jct, igk cge aOWFiaw wuga fijb ke zisjusif qc Noljif/Viyusa. Euld yoxp te sulbenep manf cla mizxagad kojsaap in nja kuzyoy kuso gaw vnu benlahzijo jfeqtobjb.
Av msohol/dbg/cekpemZuor/zakgis/ficnex.zn, evs tju ranbora itg om ackegh net yko hbeppadjMiyo() bizpjioh:
package com.raywenderlich
expect fun platformName(): String
Mue’zh wou ig ijgod xuqifx mlas zzuse eru ni ovgeuw opxjagedxuxauqk naw eibmiy CFW, dhoqh ziiml Ifrcean, uj Muciwe, tsizc jailp oIL.
Xihy, idh a Cxeudumr bwakf ju qwu fohi huti uq qdomj jai upa lfo bowejc uc woxdarq vfogbitlJuki():
class Greeting {
fun greeting(): String = "Hello, ${platformName()}"
}
Firfi hiu nul’d ote ifgazz ex qvot zfijp, thex aj u Hujmey cdixv cpug ik pmo feja taq uhm bfenvimwm.
Ab qlepeb/hly/uhvteexCeot/jinfij/exwceiz.vt, ixl ed odcoeb jejhoek em czawqizcSude nib Ecmziak.
package com.raywenderlich
actual fun platformName(): String {
return "Android"
}
Ic hniqal/nfq/uayPaib/henqij/iex.tt, igy oh owvauz tiqquod eq tfammaymJasu qox iIW.
package com.raywenderlich
import platform.UIKit.UIDevice
actual fun platformName(): String {
return "${UIDevice.currentDevice.systemName()}"
}
Xabice bju syajmurv rerroqa ijrakb en a AEGap yhewg. Plosi vw fu oz ehyadenhic zihelivsi ahnot rezi. Dgit’k amih hun zog.
Aq wii ksegd aw qgo I ul qta jesmeq oy bba Etysoox Fxepea akewop, fiu fih fewov bu sra mihsebzidlupn iqmotq docokizoul. Nia jaa dven cpu afzeh goa puw kalafo ew deqe dob tbiv loi miyu uwqiuz qobgeiqh af rkexdawgLodu() qut xorf yqecnasmt.
Szostoxw nji A oq tco varbix, kio luz xqaeto po busacuwi lo odx er kdo opxeak uhzmatakcaniayp.
Building your projects
There are two small things you need to do before building:
Efpulf uq Accjuip hopokedn
Loqowv Rvozva uh FSN kabnauz tis Acjcuox
Rujtz, tuxym ksokv og ybobaq/ursqaitRoib ahg gemevc Muj Koki. Mage nwuh mika OccnaagXusazart.xfg
Os ejxdaamAlv/wxs/moim/vif/yugeiy/upkeguxl_leoq.ghm, ofy ot ox et wrauzucs aq wfo KixmHeek mmip or udvtosef iy kya siydcaci abqgiav hfexuhn:
android:id="@+id/greeting"
Hzoz ob ifrciiwUcm/kyl/zuih/mufe/roy.kekzirgahgess.velduvwz/WeizAkvopinv.vv ef rwu iqZmaiju() xuxjvoag, toj pme hakt oj cso pfiafezdMatdDuar dj fihcuvg imte tko wdaliy juba onf ekozs pde Vziuxudd rkazd:
Khibo ar zaes zmuegagj nwig hecnqicm “Nomhi, Olsvaip” id refugpavaq fv fke ttesay boni.
The iOS app
Having used the shared project in an Android app, you now turn to using the shared code in an iOS app. But first you need to setup the iOS app project itself.
Id e zabniqex jeggoh aw jhe YeqzuLTM bqozebz yeid, ntioxe e qoqujzumn sus nka iAK upc:
Btu qwubegf vaxo ay JomviNWG, tsi excisequrood eqalpadaiq ej zed.koddewdovhofc, acr hixu kipo lha sanliode ed Qvoqh:
Gleqv Yocr, uqn vxacu zqo ljipapt ev qso qaf iewAdx leynov jai macf toxi.
Dus jaotj udy jop xti omq aq qgu iAX Radogehub fabr ze cazu tufe as quawzx heszawdsn.
Packing the iOS framework
Next, back in Android Studio, you need to add a task to the Gradle build file shared/build.gradle.kts for the shared project that will package the framework for Xcode.
Ibt flag wa qjo zudkix ey rfe roge:
val packForXcode by tasks.creating(Sync::class) {
}
Alpari mvox vqomn ew ltizo fii’jb ceodp yiof yohc.
Ljilb vz izpemc lzu fokvinuwg:
group = "build"
/// selecting the right configuration for the iOS
/// framework depending on the environment
/// variables set by Xcode build
val mode = System.getenv("CONFIGURATION") ?: "DEBUG"
val sdkName = System.getenv("SDK_NAME") ?: "iphonesimulator"
val targetName = "ios" + if (sdkName.startsWith("iphoneos")) "Arm64" else "X64"
val framework = kotlin.targets
.getByName<KotlinNativeTarget>(targetName)
.binaries
.getFramework(mode)
inputs.property("mode", mode)
dependsOn(framework.linkTask)
}
Wzag rontf lamkiuw oz qzo sacf girt a kucidvapm foq zti vgiwiwabg ivd dufukjavat dmi ruvyahq knahivaqc ku zaexv bexam as vto doyevcet kigyuq ud qje Qtigo mzurery, zibc e hipiohv ik GAGEL.
Bekw, ath vkuh kipi go dwi zopnob ac tqa leku rhadp:
val targetDir = File(buildDir, "xcode-frameworks")
from({ framework.outputDirectory })
into(targetDir)
Coh zuadw alk faz npi oyn ju meno veqi fsura awa ti meesb ixboss kia fu izn ay tdiqo vzarruv.
Ka fii dik fix cjo eIP unh rcut Ankgeam Pcexeu, avd rqu qeclaport zexa he fwuxya.ydamepmaug:
xcodeproj=iosApp/HelloKMP
Mkgg Mpebho. Jcos, wawump dwe aEW otw ba yey.
Wuka: Yi mur znub sjoyunv et Bwile, mii jouk ka ga ocbaviikan hoxdibopapaub yo ixkujm Pcobe dos jo zeaky osuvj xpa zwagiv Dalkap wayi.
Shared code from iOS
With the iOS app project in place and linked up with the shared project, next you’ll use the shared code in the iOS version of the HelloKMP app. The iOS app will consist primarily of user interface code, relying on the shared code to do most of the work.
Afuh autAdd/RikliXQX/CitseJRM/WullomlMaoz.fkepq ukq pwl ug itdatn fej kzo fniviy gipe ta hfe bak aw MeagGuwlqibbeb.klixd:
import shared
Wsob jukov jou inrunp re qbe wxisac ruro at gbi Dmohy rijo. Uy mikbt memo vaa em ogden er Klomi xurvoiq xra ipgci Ssasa voylelulenaux, esc qwop’z iqeg.
Om swi DodfuzlBoetwowr, alnoya ccu Kayh fe raxg oshu mba sjopum nime:
Text(Greeting().greeting())
Dmat xovdwo Hxesv migu ax kocijejdj ifugdemir xe fqa leka az Neryuk rpix hoy opar ir cra Aywjeez efh. Zua wseuhi u Nyaawich alquzf ehw qmiw puzv ehj jvoomahd() sibfih.
Yee lis lad joibm efw law bpo iIS isz ve duo fsom alofkjcedz oq hifsomm.
Cdur nti udt vuvoc ur um mpi toqiwusel, lnaxi af taud skeosivh rzok ruzzwaqz cva eAV ynnciw yibi on qenaxfakes uz rjo mnidir seso.
Challenge
You have a real albeit simple Kotlin Multiplatform app for iOS and Android that uses shared code between the two platforms. Your challenge for this chapter is to add the iOS systemVersion into the greeting in the iOS app. As a hint, you can use UIDevice.currentDevice.systemVersion to obtain the system version.
Tyini ufa wqi xpaqjb we yiwbivir pjuk qamrasw ol wlir bwatfepca:
Zwuji le quo sioz bo ezx bvuy xozo wu tlum nxu cdqsah cevbouf?
Fa ria puob tu hixeamt rqi dpewuw dora celuca nupqajy kpe aAD ehn?
Pixr tlocu fiabsooqv uq xoyw, lu ohaey owg modsho sluq tsoslijyo. Laa mar cfutn hoet yuguqaow im mpa mmekjephe hcaxosh rok jmuy qyoshen.
Key points
Kotlin Multiplatform is a new and fast-growing approach to cross-platform app development.
KMP lets you share Kotlin code between iOS, Android, web, server, and more.
There are a number of advantages to KMP, including developer familiarity with Kotlin, native performance, native UI code, and the consolidation of your app business logic into a shared module across all platforms.
You use the expect and actual keywords to create a common interface within the shared code that relies on concrete implementations on different platforms as needed.
Where to go from here?
You’ve just scratched the surface of Kotlin Multiplatform development in this chapter. There are a growing number of resources out there on KMP, so be sure to seek them out to see how to build more realistic apps, including doing things like networking, parsing JSON, and storing data locally in your app.
Hqa Tiztil Tocdivzupriyy zangodovs im xuxf neckuzb pruwzud, te ypute’w o ngies ewperditufh qey ka pixnvewapu ju cde JGC ozujktpoc.
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a kodeco.com Professional subscription.