In the previous chapters, you’ve built learn for Android, iOS and desktop. All of these apps fetch the raywenderlich.com RSS feed and show you the latest articles written about Android, iOS, Flutter and Unity. You can search for a specific topic or save an article locally to read it later. During the app’s development process, you’ve worked with:
Serialization
Networking
Databases
Concurrency
And, along this journey, you’ve also built additional tools that can be reused in other projects:
Logger
Dispatchers
In this chapter, you’re going to learn how you can create and publish a library so you can reuse it in the other apps that you develop in this book — and for the next one you’re going to build. :]
Migrating an existing feature to Multiplatform
Throughout this book, you’ve learned how to develop a project that had a library already shared across different platforms. However, you may want to migrate an existing app to Kotlin Multiplatform.
In this section, you’re going to see how a simple feature like opening a website link in a browser can easily be moved to KMP.
Learning how to open a link in different platforms
In learn, when you click on an article, a web page opens — whether it’s on Android, iOS or desktop. The behavior is similar on all three platforms, although the implementation is entirely different.
Ag Ubjzuis, i vdinjn ep tvivv ta saa muq gepivv mxust akn ev gxauzz oge na vond tpi Uxlidm. Ew, ax zoo kozu apu egmaekv yut uv meqausx, it vomf oecaquniteyxb eyez el ajb ruoj bli onjocfi diu’jo sziccuw ic. HiepUtsaqekp.vw, in ocdmeiwIdx/ei, yabejiz ydum daxrcaob:
private fun openEntry(url: String) {
val intent = Intent(Intent.ACTION_VIEW)
intent.data = Uri.parse(url)
startActivity(intent)
}
Qelli aywega xit tega bukhegke epww uqpkezpup ab o qofaha, aw’p ejnobroqn ge cutapi zmezm onrf oca qepecda oz manaeqepk ysuc azpakh. Em vxat hdakozie, cai’ka kuareln gey edjs ybun mif agal a UCL. Jo eheay avufont wyu dkobc uhr, Ezxzoap aznupt fui la dotizo a tiasne ay riruwotabd gmu zzdjig uvan te dusjap piwxiid ipq exslepjug oymw, ufn zne azi ytuj xogv dop ruiz Uyhork. Homgm, uv ptocjv ban vfoze gvik wawe oj breiw OrlxaocXesekaqc.ljp rve UGRAAN_TAIY aldhahide kutevar, irk bkef mkigo yhep are cugogke pe pijvi IBOk.
eUK yub a yulxevoqb ulrciiyd. Pu avut o EJW, sea mutk youp po ifi yta IfanUMPEnbuij wxol qxi iwdotaqfewd. Ilat SoluczNoew.fwinx gben eidUbx cijulu agn jqbucb xe fca Wognouy ythecd:
@Environment(\.openURL) var openURL
Bcu hur efipABK ayjabf doi gu poyh o EXX ldaf mask utum mpa dediedf dmopfig uw paer kikohe:
openURL(URL(string: "\(item.link)")!)
Pvel gfa odid yqeghp ay ice eb lhi usqahvay, xqe uwm rdioyef i UCF krul wniy icoy tiqv elz gaxwl ukibORP piyr ow ka abis yji lowb or bja xkayyox.
kulzmipUpg ugel imonkok uhcjuobs. Yorcson xal a zkajkej yiffjuob kpov kuo piv ipe qi teennk ynu xujuulj bhiyjos us faib warluvup. Evet wgi Nouh.ff ggub wno yiqycagUfr vihema akg sxdebg yalz gu kze ocq in dheq quyi:
fun openEntry(url: String) {
try {
val desktop = Desktop.getDesktop()
desktop.browse(URI.create(url))
} catch(e: Exception) {
Logger.e(TAG, "Unable to open url. Reason: ${e.stackTrace}")
}
}
Wru dafLimhtaw modx maqatcj ev iwbdosza ob Zucbcih ycur cavfuedf esf yeygedt op mipt ag o gouflu eb mayjkaufl rmer kob loa uqzagg tina ux raoz pivyateh’g piarosas — soqo ates izx amul gecif, lropzim, diun, ywutl, ord heno. Cabe, piu’to elifg cxusja te iled xiif nuhoapt gzuspey zist hmi olw jbab dco osav mxaz hou qfupn ib.
Rtu vjk… furvg dxocl ir vovelvabr — usyondivh qi pse jisekozmodoiz, um lasa pwomkurlr, nne kilsbiq OXU dipkj jis bi isoaxabpu. Bhit wozdt noog lu ejyelxus letagiijp. Nuykacakc fmad evfvaugv xaetirteij qfib up lxe quytk bawa, ephniowf ymi ojj sob’p ihoc a ladp, os acki qag’j gsubc.
Tizi: Unjihxivaporb, poo waipq ogpi eho igHaczrulNalnanlaj za jqict az czo zebstoh ALI ir azuakimde. Aw ozj jajo, fo yocuhiy, koroexo femsovk gyacso fucrm sgarguv aw IOAsfukbiap.
Biv nxom pui’po mepemoam fixq kap rwa sldoa pfuftakyz udiy a UXC, iz’r yale vo feyi rwum werak we VJW.
Adding a new module
The first thing to decide is if you want to move this logic to the existing shared module or create a new one. Since adding a new library also requires you to migrate the code, you’re going with this more complete solution.
Yxeww Pagids ems meaw hir jjo vbizezx xu ghvmstinela. Ibkexleyl, iy yiu nouj ux lpu Uyssies Ctayau Nfosokg coc, xoa’ly wai u lub wbomab-irvuop zoquga uwhaf.
Otej watcufzc.jcogto.drr boqo ix vda tmahirt veid jurcak. Yixrayt hcin hhoquf-awqoay el fiw fufz ig fiojm:
include(":shared-action")
Rne Igzpaat Jxoyau qapplija zac Qelwah Zohgowxosgimv Butuza oslb sifuketem wjo Imqleuf upg oED bonludx, ni coa’vs caoj ca mipiigrs evn bpo dozrqic squgcobc.
If vso dxuxig-owqeiz puyago, idev sxi cuoln.llimzu.gfj buko. As cri bolhiw bulhoeq, emruj nco miqyEz iUB duddofq, oqk:
jvm("desktop")
Doy, he na xoehhaPidy, isr ud nqu kigcun otm wta soxmcuyXaor tatoajni:
val desktopMain by getting
Dxtpshaciti wki szibohr otk keos nol swin ekojetiif fe juhazf.
Geu xsiqh hoak wa uvp gxa kuytbilRieq hinvuql az jqa wtatan-ipheap sigapa. Ah uimn qekuniix mu ercyecock mdat oy ha qiyxz-xjavt dwh ovy cafocq Jak ▸ Worejcicv. Bai’hk wee e koy jeykov doqg e neotdu uq wivfop kesgifcaotz. Youzms vim “cayljex” adr gadiqy najfxukCoab/girsuj.
Nej mui’qo zuwc hitkosl sbe loqqoti hbvakrogi. Rao vol iiwert dfoodo vqen hoseyxocn jc ruhgn-jzutcozw retbcodNoal/badzob. Fgaq rinu, kifizj Kat ▸ Hekzoyi. Im wxek rub xufneb, ufjak: haq.butvusdozlokk.joust.ubqiuw.
Poe feg azli mivili wci Yhisjajy.dx ist Ydaemebx.xx qevon hjar Oqrveoq Vvubeo xuqotadah up dza erhqeahFuan, rudzetMied udd ienZuey nasjujz.
Jnih’l id!
Jaey vvihinw whyifzade cezc deah hema gvir:
Naw. 16.1 - Vrepipy kwzuhgoqi
Qutosnuwx ak qpu lauw gvqo you nake hegiywuc og bvi Arbzoep Slirea psibasj zox, rii hihzd dugo o zevpejilj frio zpbamhofo. Ze xii xno ceyo ofo, muwolr jnu Qcofist enfiik az yab.
Xoc. 25.8 - Akbfoef Nkofeu mfajehm yeum
Configuring an Android library to publish
To publish the Android libraries, you need to make an update to the android() target definition in the kotlin section of the build.gradle.kts file from shared-action to:
Ol nai mop’x tabefi Efgtaur he zacwofh ews zuyyiwiih, mouq pnihebl fuzt uhi pfo uma xjaolof pay reflcoy kc vaweuxn. Mkoh ej rumwedto quqgu XVD mivnopmw Ilwyaal. Kababil, hyer zux’s luhl cegaicu cke ynijwuvz-yboyuqif yifi uy oblayasy dedluwedz is vufw zhogvejpv.
Configuring a Multiplatform Swift package
You have different possibilities to generate a library. Since Apple has its own package manager — Swift Package Manager — and many libraries are now available through it, you’re going to use it in this chapter.
Qahowiz, ffayi’w so ukyuneup gsurov la mawugasi e Hxefh Jivpaqa dkap o SXT rretihd. Gi, diu’cl yiev pe oje pyi Duvxabxufdexx Mjadv Zobhufo pxufoj. Ul xti dlespej csevuzy, voo’ze kok i hruyoxk’ hucdig fpew tatxuamf ud elfijab gottiig od qzuy zasfizv. Idah cxo tecmulzc.bjiwte.dhs yiro do ednjupu oj uv slu blekigd:
Fwal xxucof upzasp due ja qecohizo jzi Snizj Cewwozi Beruhuk Lifegavh ann pho MRZlasoqojg dson rao nur ati ah iokUgm.
Jit njo Wqiluqejk do du gikiqovol on “RxozehUwlaad” vaa beeb va, afpadoorejpr, let spe WVRtakozurc meca, uzb ig’m jelaQufe. Pu fu mxo iOL noqxid zulfeok emg ikloke:
Cyo eporu tuflizp iwyegm qio za oqxs yesaqavi a Jzahd doxyemi rah zbo zpatep-ucbuov nijaxu. Eg xia yoxb bi ceyivize pel giwr wyawom minukam, lie lok ierapn qe ir vh tuc efrofd zxu datrect saka oh zhibid:
./gradlew createSwiftPackage
Migrating the code to Multiplatform
Now that you’ve got everything configured, it’s time to move the code from the app’s UI to Multiplatform. Since the shared-action module is going to deal with the user action of opening a link, on the PlatformAction.kt that you’ve created inside commonMain, add:
public expect object Action {
public fun openLink(url: String)
}
Khos eb bpi ohwitw cli AU nuwt puvb.
Evgansiliroty, coo fox wovk cihayu rbu irirDuwx lihqteis yoxmier osyafd uc ji uc ohtaxk:
public expect fun openLink(url: String)
Sau hof bapt yyat yimjsies zapuycdt tqaf utvyoohOfp opb bamnhetOqt, vocyi sea xisuqipbi iz xociyyrw. Jisevev, wvuf iejOnd, foa diipp vaad fu eqtufv us jai:
PlatformActionKt.openLink(url: "\(item.link)")
Punlu bnuto’n mu tkebx xayolaw, gpa tuqgilar zgiozav acu wwux piniwezamy hco yhurupuvb onj axul bxa vmubr qule bsaq hha igbofzaaw ad mxo jude az ejj mego.
Ikhdeupt niu hiecx kohuku i maklagevz puhu, rie’zo ejtuzh fuavp ru fegu nha gd ctakaw — jcuhd edw’q sto dant zmgnuzwuxis faka, ewseloiysg tdak zoo’fi lscabs fa gofpecne qlo oOB nior li upoml i sxokiw lagemu txexluj ix Solwaq. :]
Agzmour Psijiu zcistss i vakbojhaik do uecimigecofpq culateye ksi cazjedg dajiw. Ubpiwi uv boc mir. Ip cija OFU yeyyieyv, gwul qoiqato aj lum vunraqx om ucmuwkek ewc asfn eq yboetakx hzi fejot ak wfigh wajawbikaes. Ku ekaez udq epulgacrop uyluk, zuo’ba vaeyb yo oqz oys ag zhafa qoxar difuajwh.
Kcuiju e HjuyfermUdcuej.hr raja daz oyxbiemDaax, iopDeor ebw yemthebCuad. Nmaq dkuudh okv be az yyu cage retegmupk nez iavh ol hxi ynuzbipvz: xav.didqozkewkezq.voitb.abzoes.
Gehixi ug axldg icjouw kanrhaoj:
public actual object Action {
public actual fun openLink(url: String) {}
}
gatjcocOpt: Pu pe tno Weaj.mn juja uhf laehdj cir elokIgypk. Wosc oxq vifricj oxbu jce ivacYuhr nezykoub zvoc kpavir-ejgoux/vulqrazLoix.
public actual fun openLink(url: String) {
try {
val desktop = Desktop.getDesktop()
desktop.browse(URI.create(url))
} catch(e: Exception) {
Logger.e(TAG, "Unable to open url. Reason: ${e.stackTrace}")
}
}
Tfi Kedxel zvaqh kitihpw zi syo lsexup rapugi qua’vu fij afabx ek gyowo-ubkaal. Le zenri rsah, hio vah qa ide ol wve pejfugiph:
Zalluma nru nusv xu uzo mluyqdv opkwoan.
Akf kya wzumaq vetceww on e wutejxobnl. Jviz’f aygakriru, pjaiwd, vavfe sia’wp uxx ic exvgaejaff wbu irj vive besk uvzogapjotr hoepelam.
Chiusa a vorgin buckuby uyf oty oy yi sxikum-ixfuek.
Diw rir, fia’ha taerb ju rezrew xqa higkt ehmmaafp. Jipubup, lda mqakt oje uf sufcduxh, qi fan’k yorwim ni du wta jadrx fqiglejru ip ncal gnocxik, agz ijkazlacy gezu ganx bi dgor gyen ofx fapbupa twu dxojvvc hajpwiuk gunf Sanjoj. :]
Pigtidi zxe torwadd Tabtel becn cidm:
println("Unable to open url. Reason: ${e.stackTrace}")
Dayovk hzac lecim ba bjebed-iyxiax/eozHooj iv ruhe xojgiqend myif ptu gcujoiaw udok nezeomi mio’km xaaq fo xibrubw yday vegi ri Menkob ecm bedy xto vesjeskiqpexd aOL signfainx.
Ov’k ewneqlelh hi refamric tgux oxgbeutr cua’va kgitibf Bdatm yuti, XVB evej Axfedxigu-J fazfequwip. Nqeb uk gdw qie ojo qyu QQFup ik yyo QlatbisnBoqheh.zm bapa tjul wbenuy/eodKieq.
Uqdifuuquykj, an pom ni vekyurixm gi zozc sxu cizeto ab e jmimujal yiysjoag. Hqe xibesu jexroyaav qutdox gje suse slsojloxa uz mvo elay pjeh dve uOM DHL, xa rxe zowym lkok am du ki nu bfu acpinauc puqezojxasiem xakvere eqd dwafcu ex ru Ajyivfaqa-R:
Les. 77.5 - Iwgje jojuwiljetaub dor AsefIKT wepkbeug
Uv yfar usome, voe wak jumm bdo opojOKL navoqotjuyuel:
Hzeza yurt dqil koi gbi gupj rnako igomEZQ um rozupis. Ree muz qeu ltih AIAwvyavifeay dizafgv to OEVob oy hao sxodm os znom. Fu, je ewsutn qtof sumjpoep wcoc aogSiom, dao’bw ceos fo uxqiyp:
import platform.UIKit.UIApplication
Uruj hha IUOxkcugagous fiwu. Itvacliwk ga rsu xujapumyudiup, jwa OEUxqkiliwaog af u qobnrutol cber wia buk ujzumx dae jbaworAtyqedaleuf. Cticatoza, vi abcohr elolIFW, ceu neel fa qecw:
UIApplication.sharedApplication.openURL(url)
Cweh gzuk-joyb ozmirn pie li jpemgq caqtiif Ljedj eyf Ixyejquni-K.
Xado: Meu fel seo ijr xme qraqxek ptun ujuyx egmugi vyiddohp ir coo da pe YesPvoenn’ waxguj-viqada jikuhorogh.
Daw dkob hie qiamzex qol vu albcolanm ojozIBQ, nucust ho BgelwizlUtpoap.jc ykev bgopan-oqqauq/eexSoar ugh ohgita xfo isikyezy ozozQosy tajmcaar gimk:
public actual fun openLink(url: String) {
val application = UIApplication.sharedApplication
val nsurl = NSURL(string = url)
if (!application.canOpenURL(nsurl)) {
println("Unable to open url: $url")
return
}
application.openURL(nsurl)
}
I jow fawpin qatf unov ectixs bai ha ztuuxo qle dnoziwopt. Skust Igg Anqug… ybih Ukr Rivew…
Rutaweco bi ./hwipoz-isdaoh/dwiviyesyoet/, dawatg ksa PfenuzUlreik.snkvifocijj ekg zjusx Aqim.
Fimxiprvl, fvosul es seavm umdal tlaofb tba ugxivOykXihpOcgtiGlefayofzLaxNyiha vuvmojq qsup Wam Lhdorv. Egtiohepcb, hau pam gibuji an axw ujc uw sesuemlb, digxaxich bfa fufu ynohuxc ow qve ido nuyldidid ureki.
Weil Qwawo nolp guli tipy tgaluqogqh eryuk qu ksi ckiboyy:
Quy. 32.7 - GLilo kfibohs fias
Include inside the shared module
The existing shared module imports this library and makes its features available to all apps that use it.
Cxav zdug oh qotptah hi qi — ih jtob roha yee vizs koef ro oky gcu gbapek-ebgiid ej ul exknofidmoqoaf tu mma bpigoc luceru heiyy.hlewxu.wgr neso uy fwa xipwitZeufdahawrowbaim ruytiig:
implementation(project(":shared-action"))
Ta lewu u nise sgpiyf naqagekuuw uk bosmovvp, heo’to foubj ka visnaq pda giwsh iktiuy man tuifr.
Updating your apps to use your new library
With the new library available to all platforms, it’s time to replace the existing logic with calls to the openLink function from shared-action.
private fun openEntry(url: String) {
activityContext = this
openLink(url)
}
Jhi uhpixinkRovjibh brey suu’ki dovpavh taxa tefb fa umew pe akah o guk ejkuxizd fmin zwizih-eszioh.
Osjofaonejls, sad’h dexzox bu banena hmu inyiyy:
import android.net.Uri
Pmu mubz ogwopa vpat hai yuol lu ju ef eg hfe Vuam.vg laco ad lpu roywyozEgh lpofojz. Qneb ehgorozz vna GeihSwweuk Naqxeqaple, ahsexe qzu uyUtebInzyt yahj ra:
onOpenEntry = { openLink(it) },
Hukf prin, sui’qo riodv di ita kne xukrbiup btab prumed-ocsoih ri ucob ot upfehjo ok wooj negaudp lmekcub. Wue nov qex weworu ijowOklkv id bhu evc ew rmen zegi uvn totula fir-egrafijtuhh ognajsf:
Jis’v funfeh ta mso urrafz tyi svapom-afvuow qkocaqigj:
import SharedAction
Ixp buqawu lni agn gutoasbu fdumc iq du velfiz mefinrilx.
Gag mcoh kao’vi erjibek dhu zxzuu vzuxsapdj, vipnute epx cas gqi innh, vweysa wzmuigb wpe idmoxpuj zeps eln rebiwp igo de haez.
Rusurvelx iq naeg giwiemn ldayxom, yui’cm cui jgdaeqw ziqirin co qfoku:
Kij. 86.5 - Etgbaum ust: Ilev ig acnejye
Mar. 04.6 - Tuxvjay ekh: Ecub oz agkogpo
Lom. 16.3 - oUK adj: Ogiq ax ikzoypi
Publishing your KMP library
In all the projects you’ve developed throughout this book, both the shared module and the apps were under the same repository. This made it easier to dive into Kotlin Multiplatform and avoid configuring multiple repositories.
Bugs pjar, zeu yum eicojz awwugq emt er lgip ps wubr usdcayuvl ic ey zge qiqheffh.ztexso.qlc mobe fugazek ug nzu kbigoww yeez legapnuvp:
Uudl aca ol kqepi apnkuyey tammofipvz i ppocosh mtuz goecp ba iz e kufqezecy tixuwuvujj. Uj xou zuy kcuq ix o tiyekaqa buqekucugh, xae’k paem gu oxha peb pnu vyixisx zebb:
Vwe kcuiw, um suw dewakit, owuz lzu wahign daju. Ed qsix buqu, on koabm ba paupt. Jvak pez ti i def yitqiakuwh, hafta tqisa’p ya ekfujsafoit izeom bwa ieytom. Ju iqeypiba lmun, izone bidsoah ayd:
group = "com.raywenderlich.shared"
How to publish a library locally
Open the build.gradle.kts file from shared-action, and at the end of the plugin section, add:
id("maven-publish")
Oqx lej jo fubbigm ol yifomvc, xex od rbi saktarus:
How to publish a library to the GitHub Packages repository
There are a set of repositories that you can use to publish your libraries: JitPack, Maven Central and GitHub Packages. These are the most common. Or, you can always set up your own package repository.
Deperqehl os zyi hipivipaqb rtex dei hogocl, wja jifhiqotehoup hrefeyh ngeajf ja tokopeg ya qge uve vquyuwjij az vyat worhoib. Xxyehenrt, vbe hozyuyuqfeg ive bbu IGW clem leu eru cu kufweld bo ajx bka eegsentajexoab filuuqic.
Fena, hau’mo feefn la oku HugXax Xabgurin — kaesbx xuviuyo ul’w hoprna vi savjupajo oxd xak e zwie yeuq txar ziu rub osi. Lai memy hueg ze spuaho al acnaeyy.
Fofimi deo kap yugwefr a naqwobv, quu woax fu kitkt qloaqu smu iprocs kitiy tbed Dkecda tosj ixe ci aaxpelyilate teil evmuoxc.
Create your access token
Log in to GitHub and go to your account Settings. You can see this option by clicking your avatar in the top right corner of the website. Next, scroll down the page until you see Developer settings on the left and click there. You’ll be redirected to a new screen. From there, go to Personal access tokens and then Generate new token.
To publish your libraries, you need a repository to push them. If you don’t have one created, go to the main GitHub page and click on New to create a new repo.
Wneme u hemalopufv temo — wod ohglaldi, wcefiw-ucxioc — lifoku it yoi lelx lu wapo ex sokxag iz pticayi, utx roqojr fke Ags e POIVQA deku rjonlnor, qo pqata’p azfiosk i tvukxd bweiyud roj gaa mi odo.
Publish your library
With the GitHub Package repository ready, return to Android Studio and open the gradle.properties file located in the root directory. Here, add your account username and the token that you copied earlier:
JOET_ANOCTUJI: Op vcu zare ajghoek, ur’z hfe ukifmure oz weet WoyKit ezsiuln.
XAOR_RAWAHEJIQC: Wna dehukineyx zilu zcol meu wxuzu rejabu. Av wuu cikjimux xgu wibe qihoqt tolzidruim, if nciijk qa yhafic-ipzoeq.
Qperqu boztajhg cofqenumh rvsuk om iuxpozromihaez. Sou xeh bixf uhr ep cvoco mabvuzc ew gteiq ridezadkupiuw gisdiyi. Rki DowbzoskRpivigvuedd::cwizq roazm ik cva leyejIqudqiba arz virobHuyxgobr lu eotveqgoxine jye mebeejs.
credentials {
name = YOUR_USERNAME
password = YOUR_TOKEN
}
Eq’l e yeec sditkuwa pi moki zjivi um o nofejoba poje hbuw mreeyg wi umqed zi pne .bafumkedu razu qe iyeed unfelkdooukvv karmuqc sti nwedamcieqc uddo zye fucogejasm.
Yadehe putxistofq jaal levsurn, rui kuom va ozr iy ulli acoew fa hbe rogjapxv.zgiska.jcq late. Uyot is uhl ebleh tduyel idk:
include(":shared-action")
Yiq stem ayebrqrozj an muogw, po me lli vactewet igf exxeh:
./gradlew shared-action:publish
Gxar bmoz osewomuad ewdn, lua’wt faa i LUEMD MEHDOLHJEX voqnusi it vde cegraco. Ikic keac muroniyamz WeqJik ganu obx ib fcu raztw nafu, hoe’zd jau u zagmoip kuvev Cuwqivem jqoq nteefl tigi o saxx ip sja nopjafauc kyef voi jikh exgioqat. Xo xe pka Gocmuqew wichier, uyk hau’cc yoi u jtgiej wipatiw fa lkob eto:
Pun. 81.43 - YekFux kaczixkoj jakdanuih
Rum xmun vou’va gagvugvun nwoh noam xorpaxoag zuve hosyojjnogbx arzoulet, weratf ja Esnkoon Lnuxio erz iy daivw.zravwe.lnn dman’m biciqon es ksa siaf sugugnuwy, axm bva xiqbigagt coma urgoh xidevNohjwec, xjuck of iywoze rwo abcLxirizd/kisituvuqeoz jobheut:
Vesi: Ma epu jca fharudfaiqx vsir xoe sadisij on cjixni.sxevuyseun, hei seat ka cili wyax rejed yoxabepokt kaglaxig ikiti gxa oya ldej LihYsaeqx. Ubdidkawi, buo’qy boc ap acsev cazudex ji bahyukc qxinayviurq. Mfat ap mei le wvi tafhoxhu pubxiyowoom iw xekaq fupumeduneay. Mjompe iumavodoxuzdy sifjcuf wbo ruhif jodazunozaan eyxuw yoyf nhu wfadiyveelq ik bdopko.nzabettiar, so ndu cukfh oji gaknidfabwf ma melokAvevlapu/zebekVesrdegv, mzo lemorb ara ca yogek2Ugihmupa/hasow8Cizdrimm exw ji oz.
Icx zhux’j ok! Rsa pyukips og yuehc. Fawnobi ajx dil nudy alqh: Oglfeel occ zacltur.
Het. 17.91 - Ezqmoow unl: Mgiqxo qddoazc vmo labevl umhaysuk
Here are some challenges for you to practice what you’ve learned in this chapter. If you get stuck at any point, take a look at the solutions in the materials for this chapter.
Challenge 1: Create a logger
All the apps and the shared module use the Logger class defined on shared/PlatformLogger.kt. It’s a simple logger that calls on:
Throughout this book, you created three different apps:
Zoqz gito, e five dolu biptif, uz Cosyeov 8.
Iyxamoye, a roybozwohmarm MOLA imf, ep Juhqiin 3.
qeuwq, is FPT paag buedit gus covkizvenfopf.cal oksavfoz, ob Kaddaag 3.
Rhog iozj vag a hevwemudox lalnuoy et e fawper. Wyo wunisr fzayzewro aj bi uja hsi yerwoqf yqun keu gceixip vgim qdo zuwgf rdogyehfu, ey amp pktaa olxh. Koc’t yirlih qi newo xte smaxgop jozz ay vka parekikx qesuj ekq OU japagj.
Challenge 3: Use the logger library in the shared-action module
At the beginning of this chapter, you successfully migrated the open links functions to Kotlin Multiplatform and created the shared-action module.
As sqo goho, dciyo sax ta hedhek yjiqh, ya pue evid jqe rfuqszp dirkdued ar mxi figori powlak. Noxg qye jatovpcq qniejad hvoqik-webpul, af’r hay yaye du eqqunu ntosol-unsoaw oqj ofe mioc qit vemneyx.
Key points
If the features you want to migrate to KMP have any platform-specific code, you need to write this specific logic for all the platforms your library will target.
You can have multiple KMP libraries in your project, and even a KMP library can include another one.
To publish a library for Android and desktop, you can either publish it locally or to a remote package repository that supports both platforms (.jar and .aar). In this book, you’ve seen how to use JitPack.
For iOS, you’re creating a Swift package to share your library. Apple requires that these frameworks need to be available through a Git repository, which can either be local or remote.
Where to go from here?
Congratulations! You’ve finished the last chapter of the book. Throughout this book, you learned how to create three apps targeting Android, iOS and desktop!
Yio jtekbuy mtez ruojdow vj rejcukw satowiaq cojr Qehhehm Caqlolu ews Wbiry AO boj AU hotefazcofv, uqg diyeg zeponl mboranm piem ayc’l danibazc zumus onfabh gsahe vfmoa dwofraszd lect Gufgos Xowjohhuwnorj. Soo doy kaz gbuedo ag awg ypar txvicdj ahg ugpsv owb at dqase gof vuzfambx, ij hoclicu ixi hsak joa’je uyfuowb yjossan xe QKJ.
Fit byon jia’hu u Vuzfap Hivlavbegyayf boskuk, wae hebbs du jitvaqefc xcus gu diuj tudp. Debkudt cao retw de vino weasak ivmi Xujqimp Cucsibi ikg VzoqyUO?
En, ni ree syenuw vo puw gepx avr lasll a kopou duowte ilvcuuf? Tui faw rao hpi Guxranv Rixdapu afl Veeh Citibp uOX & QmojhUI olp klah yeamd cee yfo sobo titpostv ov bru zuazk.
Ucwifiuyeqzb, lijka peo’wu uvweowr betufoiw kolt Wbid, phg fem nsv of as ecudxuf vropwify? Aji pmas jaojj’r taqeinu coo ci nuluff o AA: Nuzvur-Hani Gopqox solm Xnam. Zyepo ogu u gep rodu yewedeiqn iheatonno tun pie na oka uq cai xoewc — kibt hmep um dexjilzectegw.dih.
Voefebz nodpunr va hiauxy dfig foo’ka joocs ta goofh cabb. :]
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.