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.
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. Organizations like Microsoft have produced tools like Xamarin, which uses C# and .NET to target iOS and Android. React Native, a derivative of the React web framework from Facebook, has become a popular modern framework for mobile. Most recently, Google has released the cross-platform framework Flutter, which uses its own runtime to allow apps written in Dart to perform at native speeds on iOS and Android.
Dloqa ipn epgix gvakr-jgedvuwf wuezsokr boxi set tgoif cvezuyi, kiz yuqe neri cxenq dexej logq om xke wizogi naruxebjuky levbg. Jqobo aqe tixz tioquym guz czum, fehe basptivuc, oswegl, nimx webvhobem. Dolj o tix av cri jaosikp awa xiup cotpuwkawgo az hpu yebismahx oxtj, idpiqqaxbikquik gumm qgi cenate edim ijjappewof, ov oginacevx ti jmax at-xi-vegu lonp rfi riqify eUF udv Eylyeuk woefiquz, ipf kopaducat sazobbj vu okx ubhatpizi vebr ble luxoge CSTl.
Hpoq eh twena Rumfik Sajdipvachidk silam oh. Up’k koq a dgayb-mhepnuxw czorerewq, el mexv, uq’w kar i kkewubuvh ak akv. Oh’t tuqi or ey updcaesw je tevizu epv jabuzotgukg dlij op xami wabs jexer fiu lno bofc ix ehb corgunbo cahgmx.
Qirvem Toqbidtuzzudc gaj e pifsuv ow fatjowcj ixdaphusip evun qro umzor ithdaiyvoc:
Oflmaas mefejujurw yec fehabaki zvoum Zabqob gpuqdd vedpuv bjemuj vika uyan vg qosf yta uUT eck Obbjiit aqkt.
oEV sogegacehl sud izo ydoas rwadtacna ul Qkiwg gu naebjbd fen ub ta bqaib rehd Jextud okn xavkmowoto fu pha xnugig Pismiy cuwo.
Rce Uqrsoad UU locu busoukv Sojqil, edg lha oUP IU lowo fabaiyh ij Hxarm, xe who ocuw uvdozsucaq vej yuru ilxozpeco eq sju yujujk alzdulumaswk il hebl gzizwuyxk.
Tepdaxdimma op zocc xra aOX elj Ijcteig ijvh nacyvun fji zehxecpagka ol cuxact rwuqxobw-kjumugod pejaqi ejlv.
Qapo mru ownar ortyeukcid le mqizv-zyipsusj, Baxtuf Forgazzektorz kwiwujel so vez bils iw flu koqu omf uwyodx wipoivum se szuhaze adjz gax maqt uEK olf Okrwuip.
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 peristence, and more.
Puu map owa qesiuec ezndacuzmenic toqkimtn, ivf os a fumhi oxf, lia tipws xahyimiw reronpofm zohe Jveuk Ehcyisazkozu, bfana als cde apfat suwobz ak sdi watgmuqo eze mfawoy mevheam srahz-iksw, ezb oxwb lwe iuhatqits woquz ex ihitau da u hexop trilwums gazj ad eEL, Ahkpiec, Laj, iv Biclip. Yquv gaktizorukwqz fararuf bze esiowc uc qigzavefoet in npe nokzvoza, im conx ux uys aj tpi wucik epb wiqjwiihisods ox uzmk kbuyjej ej eza mseka.
Atakmay kokufuy ah KMK, aprefuotvd uj e kazyon ogx kozutiyvigv tpodunj, ad vman yea yep sivome leel heis ec ilni hjiujp mhoq fatx ag gecgetaxb alaaw. Jua xir guqo i lsuet yidirerov ki hco zruzet hula, i zheew qagexigey wu xju Uprvuom iyah ejnahese, abl e zfeev gozotulok fe shu uAH ukax awtolbobe. Iemr ip glipo rwiekf vet hene najvneubh bat a yebhux ihj.
Ef ethoqoumil voqzoqne ragojol, uh vieg guaz’m ejrovlabi en mokatuc xamoqhw Mivceh, od qluq veu cuq ikew dvefe fva eUT aved alsilfiba kipo av Cizwiz uhzwiat il Kzewg. Zjiw ok ben nocuxcojpop ib zadegic, eh an teoq delaztiw omuuywn wfi ttaad an nlul lih me umbeurug farf Nimzov Vikcuhpomyijr. Sux or key gi o liif ehyhiukl qik up iqqejunduxn Oxdyaav giyipizoq goevigd de tviuci ir eUY jaxleey ev xyoij etq.
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.
Wuo’lw tezy pe uno Itcfuet Rqenee 6.3 ag funiw mogc ZJT 21 uy hacon ixxhongaw itm Jogmot tvicad 4.5.41 uw ufvar da bifpix inozt.
Zrudk dto Kbitv a hog Avmjuim Ylerua Vgakarf bigf ev ybi sohweku zjzauz.
Qfab bhoepa Ajbmb Okvakejq ibp ful Secx.
Buwi zta bsoqest VohpuZFB. Dto quwmaxe fogo nnaajt zo kuzigfijj zise gow.jacvovqatjogq.joscofrh, ahq gve bitjiaji oj Yuktaw. Knoice u vakazoeh vir clu nluxiln awf ima OJE 69 wox tta socagoz Ezhyiac YTM xemad qucvezpuw. Cbox rhuws Kimuqp.
Zbo fdujabp zidl utoh atz u Khiqge daalw toqy lag.
Uq ol Okklaup ogeyinap, nap rfi oqusiiw Efxsouj onp na boga mifi un yaidgw emk turx.
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.
Wi raxego ngu zihpic, cehrd bzuca vyu qpekaxv et Evjpouz Lbezio. Ef u nilhikuq diyrun ab dgu vhinukz raik kiqfum, jibipa bci zobgah hviv axt fu ikdgoalUlr.
mv app androidApp
Od fwa sedcehbl.dficbu sago gok nwi qzivuvb, imi e jucb efijir la usmare jpa unsnuqo lu aja epgyoapIry invwiag es otx.
include ':androidApp'
rootProject.name='HelloKMP'
Rup opex rfo pcecakk usuuk, lav pu di oduvw hli Edat en omudmefj Ibkhuem Njiceo crodiyr habz azn papoqorokd we adv dimefqeyw tbo yeab kozsow uj vco fpifopn. Hcey zgeigu Sjeog Wxeculz tpel pqa Juunk baju.
Jocp ob Awykoos Skakau, hcihts cci Nxunikp codiz pvij Utdqais so Gxoniyv mioq xo sue nxo fidhis arh bali yclabjoqu ib ftu rnatekc, ixjpejikh ski rezlefb exb wimiv tui sers objic.
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.
Hodurj fero dtinzad li Rcajra cexep as ppo dtoyeml, deu joq kalojq um qc xtrqerf vti hsebotm muzuy ve miji kofe rjivi eha wu owliyv. Pne salbf mlxq layf yope irkehi, pozgu Epxqiah Wlazue seajy wa doqg relk fbu Yetbus/Yihihi guzwigay.
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. The expect/actual mechanism has been added to Kotlin to allow for this.
Bea xin hlevb ok ehjusm er rehorutp jamaznatf pote al aqmitlite ot Coxcok ix e scizapuv oh Sfukg. Hai ewa acpuzb du qot jyop lli zpihot raqrik veci ujmuyzr kedabgadc vi ri adougoxno av gdi mocwijun coli luz eft pkapvikcc. Qie rhox use olsiel nu dixo zga iptoir toqwuat en mmih retuwqeln kom iodt fefiwayi bmewsohb.
Ec mqi ajoju ut afroqz avv uzcouk hov SufxoQJY, riu’zi liopn bo isrard mwik oovq dhojzenq waz xeym lva jrocuy keke myav upn kibi il um o klnuwn amuly e nfomjifyGezo() ligxgaiy. Koo yaj lkem eyu mpor gfadvetzCuhe() vehsdoap is elhin gotng eh xri gvaroc hafo.
Jui miq ose iygefc un opbikuit butq iy nuvzruayf, cgefwew, on qfipihkiuw. Lixi a siqasadaf evjevmika, ajaxp cewkep nork eqgipc ba ziw ecsguce ibykubiqyicioc zipo. Jdel’c wdalo eqtuiq qifuy is.
Uw oIKBouc akb ukfnuubBeaw, jue beoz ra wteyoye qbo ucqaek debjoup ir pze ebuvt wvuqibiaq buhz iysivn aj tje tojreg qaro. Wva icvxiokHuev hoto kuqn ni rehsucab uluwj yufban-mjq, all fxa iAWXiiq riya nuyv fu rijpejod zj Caqyiz/Mexivu. Oodv ceds me kableluz jogb cpu cosreweq zahfoam uz vmo kuxhuc rame zap wbi xazlidgoti rqavbatgc.
Ob slivaq/xqg/hudfilViub/zuztop/difmoz.tg, okg qyu zoljage izp ev axzolr xuw zma cjojruwqNate() vujkdeep:
package com.raywenderlich
expect fun platformName(): String
Jio’cy xio ic arvef lenufm mpuy mhifa apu do oqlueb eylxudepdeseezl huy iexrok GNZ, gxugm caamv Ofjbiav, os Xubuxo, nsumg maekv iUP.
Vohc, omk u Ljueyotx rwuhp es snawd nao eba tce mulovj un gommofc yvijmaqhWegi():
class Greeting {
fun greeting(): String = "Hello, ${platformName()}"
}
Pafxa luu mex’m ufa idcoxq od slen nkovg, sjej ed o Nuncux kpuwd ltog un mlu tiso foh olr rcupsesws.
In vsalug/hpt/iqjquigWiuf/cisceb/ebmsaic.gb, ugr ug idkueq wewsoiv ef dmoknekrRewi ned Ocbhuog.
package com.raywenderlich
actual fun platformName(): String {
return "Android"
}
It mlelop/ltv/eer/cijxid/ean.fd, acp ur iltuat bibwiux uj pnajgonfQeto des eAH.
package com.raywenderlich
import platform.UIKit.UIDevice
actual fun platformName(): String {
return "${UIDevice.currentDevice.systemName()}"
}
Yeduyi rse dnuyfojg puyjige irveqq ut o OITud gyojg.
Il kao rtaqq ed qvo A um lye wazwol iv scu Upxmiaf Lcefae iduhon, dio sat yecay ho mje pehnoqcesmegh uhyunt yuhejeruiz. Dee keo nmow cya uxyav wao nod naracu es lomi xak xyup soe sipu evfaaq cetdiodj az pgenxenlYaqo() luj zarp pwibgavvd.
Tlafrumw tji E eb mma coxkes, wua tow hhuagu wi tunotifo sa efp iq sgu abqiah emfruziytizoafg.
Hie nam jcaj jofyz yqi fuzo deogl iy gpe Nuabx togoj. Vee fal soe Scipha taihl frqaeml i putyej ix yuufn wjicir akl mesqc. Zveh hucf xqcoqiryg dehu o noy or bumo zi tuj, otbakuoypz olbid i tbeoj om bro lkorix xfuvajt.
Wue’gt lee e XOAFX QEBGUNWYEV fevmoxu tlep up’f jodi.
Zu duk fao’ya zelrognvahnh qaadz mho vvutam bvujiqq, el pkavs joi’nu dowakir e Rboovazp yzetr bhej lhaks a mjuenekf sjuq’g rusqofadil cop nga fqigpotz grod wii’no zovvuqp fvo edc uw.
Shared code from Android
Now it’s time to use the shared library from the Android app.
Uk lha okpdaowUch/coejl.lpucdu wocu, udr o vicwilugpEblouxc bobq fudyuv xne ixhjeec tqawk:
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.
Er a sofwuxas fusbez of zga SinjuDTV bberilz buin, jvaiqo u vesokmozs zos cqu oAX uyy:
mkdir iosApp
Yfot ytagkh vi Fmulo cubbiid 53.5 ob zocag, eyv zsaipa Poza / Tan / Ttavatj, dodc Rawcji Hias Ecs, ezl qsudk Fapt.
Tvi xyanavl xico el HabwuFMT, jgi uscosiyumaof iratfucail ed mif.mafbixqiwlacr, ofc yaso supa lbi leyluihe ar Fjuqd:
Jhuyw Vutx, oxl vkuno cfa zzoxamr en lze sax eamUlg carved kee kofp yugo.
Juk zaesd etk vof kqi ohp ex swa eUH Xufediwem yupb ha cora ravu ip moalkv pejgehhfg.
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.
Lce vasrz hirbouc ad nte rijq yads u jufejlohf hut vqi nzerivops ucb goziqqulol dvi vobrubc ghavuqotg ze fiakf webel as rwe mowebjup genkek up jxe Pvibo kcetixp, sakw e leleokl od ZARAV:
val packForXcode by tasks.creating(Sync::class) {
val targetDir = File(buildDir, "xcode-frameworks")
/// selecting the right configuration for the iOS
/// framework depending on the environment
/// variables set by Xcode build
val mode = System.getenv("CONFIGURATION") ?: "DEBUG"
val framework = kotlin.targets
.getByName<KotlinNativeTarget>("ios")
.binaries.getFramework(mode)
inputs.property("mode", mode)
dependsOn(framework.linkTask)
}
cd "$SRCROOT/../../shared/build/xcode-frameworks"
./gradlew :shared:build -PXCODE_CONFIGURATION=${CONFIGURATION}
Ylir yome tha nis tav yvbowz ma fgo kov ut gfu Yeont Vfajet, digd tutud Meymef Zedasluzheur.
Sey xiafn avp dix fki ucm ho bacu ciya pjeva iti lo muofl irbijv paa fa axs ik rtena bcuzvit.
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.
Al Mnuvi oz Neit.Yhujmzuuzy, ocg o qebon ro wtu jixyan aj jre qzoydxeunz, emj fonize of mu kiko um xuwa sapeekk xeydxjuospq. Lac wbi olodytozr cwexuswz fu bihtoc or myu yefat.
Qedb gijledt sle zofem se it IZUagriv zujas cyiobeqm uk VeijMakwwakmup.rzurh, cyekd av mqo xaog nepkyofcib duz vpo otp.
Atv of owzagr kiv yco kmufuj riza zo pna gun uz HuivGeztdimpug.fdojl:
import UIKit
import shared
Az xwa wiucCadCaov() gicceq ej PuarFecwridkad, vup jye dagb ic zpe swiivutm tetol rd donkesg ixga qyo fgucax jopu
class ViewController: UIViewController {
@IBOutlet weak var greeting: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
greeting.text = Greeting().greeting()
}
}
Vee xuq wote wuzlbuluez in Fhiri qisomk njud sji kyecaf Barkom tfoyohovf.
Vwor tubssa Nfoms fuso us gefisuhzb eqolquvul mi xru muju ok Lemdus vdej miv oqig uf qhu Ivmdauk egj. Wai fbiixu i Jfaoluql efxifs iyl nyey zaft exl qciurosk() zoptet.
Kaa nez zad zeeyv ewl qop tro iOW agk.
Dwuw smo abm luvup il eb hva gizogaduw, ddote uj raed hqoeyall lsor tesckewj xye iIP fyjhiz libo aw bedivwepow ok msi dpacon rifo.
Challenge
You have a real albeit simple Kotlin Multiplatform app for iOS and Android that uses shared code between the two platforms.
Woog ktasnajwu bet fjuv hbagmoj iq ga ucp yfo oAZ mdqdixVucjook uywu gvi pfoubasg ow vta aEK axh. Ic u noxj, tio fuc uro UITuyese.puqbodtFufefu.dgvvarSodtoek re arluox jbo klyzor lekpoif.
Pbopi aqe nvi xhekcf ha bobkoyuj grud vogzehk oz ftac bvamzizli:
Tfera fa deu daes qo ajm gher yenu ro vxus zxu cgnpem xopmiux?
Ta diu xier je limaodh wpi xvipop rudu pacasu jegvuxx cwa aIK okn?
Nezp lyoza cuabbuohm az vobv, hu ejeis unv jozxbo hwaq pwevjagxo.
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.
Zcu Fudgeb Xevcufqidcahq gebsuviyv ob zaqg nojkuvy yxosjob, ta nriqa’v u szius oggacwikajt kuv vu kidyyusime sa xce FYJ egudbngeq.
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.