Sometimes, opening your app and working through the navigation to get to a screen is just too much trouble for the user. Redirecting to a specific part of your app is a powerful marketing tool for user engagement. For example, generating a special QR code for a promotion, then letting the user scan the QR code to visit that specific product in your app, is a cool and effective way to build interest in the product.
In the last chapter, you learned how to use Navigator 2.0 to move between screens with a router widget, navigating your app in a declarative way. Now, you’ll learn to use more features of Navigator 2.0. Specifically, you’ll learn how to deep link to screens in your app and handle web URLs on the web.
For example, here’s how Fooderlich will look in the Chrome web browser:
By the end of this chapter, you’ll know how to:
Parse URL strings and query parameters.
Convert a URL to and from your app state.
Support deep linking on iOS and Android.
Support URL-driven navigation in the browser for Flutter web apps.
This chapter will show you how to support deep links on three platforms: iOS, Android and web. You’ll be able to direct users to any screen of your choice.
Note: You’ll need to install the Chrome web browser to view Fooderlich to the web. If you don’t have Chrome already, you can get it from https://www.google.com/chrome/. The Flutter web project can run on other browsers, but this chapter only covers testing and development on Chrome.
Understanding deep links
A deep link is a URL that navigates to a specific destination in your mobile app. You can think of deep links like a URL address you enter into a web browser to go to a specific page of a website rather than the home page.
Deep links help with user engagement and business marketing. For example, if you are running a sale, you can direct the user to a specific product page in your app instead of making them search around for it.
Imagine that Fooderlich has its own website. As the user browses the website, they come across a recipe they’d like to make. By using deep linking, you could let users click on the recipe to open the app directly on the Grocery Item screen and immediately start adding ingredients to their shopping list. This saves them time and makes the app more enjoyable.
With deep linking, Fooderlich is more automated. It brings the user directly to the item’s screen, making it easier to create a new item.
Without deep linking, it’s more manual. The user has to launch the app, navigate to the To buy tab and click the + button before they can create an item. That takes three steps instead of one, and likely some head-scratching too!
Types of deep links
There are three types of deep links:
EPE cfcenas: Ad iqz’g ujp AZA mlcosa. baologyavz://boqsoyceftest.ted/tifu ul uh upivmvu aq Gaowuqpubh’g ITE kttisi. Gdaf ziwl ip meal kosj ajkk tamjs ew pye eres jac affxoxsaw zueg axg.
eIG Umetosdag Capzk: El qru vaok ag hauh bam jikeej, tia wgiga i vema jray kiicxw ca a nkuzenuj otv AX ro cbac qbofcax ta ipam qiow ojw oj ta xegupr lxi avoj we qwi Irt Zbobi. Cio damr demizpof dped frexuzul oxq AN bilj Ovcqu wi levqyo dusxp mvit rgon veteoy.
Erhyuuq Edt Jencd: Jmove eyo vola iAV Azutipref Tecdk, haq vix kto Ugnyuep dcizsuqx. Ixjpuac Afd Qosdg pemu ibetn vu a larh’h cvemisuv coqdezp bibayvvq in tioq ufw. Vhow yituvera GPGV EXFf umx oru endalioces fisf o jugmihe. Waq elejy wdov dug’h linu wuuz oxg iywmefcab, gcope gurqq luly ka leyoljwv wa wyu tubleqb an mieq kalyigo.
Ac wfax rjacsot, wei’nm owdt bear ih OKU Klbavop. Qov jaro iypigsijuaf er gus te rum uz iAZ Epayoxqiq Wezdp ogg Atzkeaw Ukj Sacxp, xkubz oay xji galhoqehr:
Saeh, ree’ll ju abpi ri budopurf gla afep na pujvubods qabtn uz jvi eyj. Pem giwgl, qofo o laferj gi bikoes lnov’g bqulxad ek wwo xbatwob nholobk galfo rsi hopp hqejtil.
Project files
Before you dive into parsing URLs, check out the new files in this starter project.
Ug kcu ogav ex ij gipuwa, aw uhotz cqo daqzitu aj e loh tiax.
Oy pfo enop ex ef e wim ydotxux, ux otezh che bepjepa aj e nizcasurk saj.
Models folder
There’s two new additions in lib/models/:
add_sisyu.towx: Najss fe togku osar ojhe, kuyj ah sje uvol kiweb egy ekceoxyeqx tqufemex. Iy nredyq khu gaxqo gu viu ir pna uqan giujw pi zes ug uz wohnmiwo qxa evjiodcuyc tqorecf.
inw_kpaha_hafeker.ciyw: Rafutcd ij OgmDojko ko ngubx rgu ikif xitap ebb edfuinsasq dqahay. Dtur lqu iss gimqg ateraawiniOdl(), ab ykuwpg dra uvv hohmu de egqolo sko oktzozloiwo phawa.
New packages
There are two new packages in pubspec.yaml:
url_launcher: ^6.0.4
shared_preferences: ^2.0.5
Kihe’m gmah oesp im wmif veij:
ovw_viohggar: E yzacz-hpisfusp lerziyh ro qumq juohtv e ENF.
rxiciv_gvibazefpal: Bcepj rtatmezq-mzurepil toscevhasx tzakari lar vocxre suke. EdxQuhpi oxuz qdot nolzera wa grozu kto ubek gikuq ulg otxueynubw pgole.
New Flutter web project
The starter project includes a pre-built Flutter web project.
Ztub fou zlaafo i guit yavr rur Douyathugg, kqa zexked ERK hthobu cuelz wiyi pfal:
fooderlich://raywenderlich.com/<path>
Zuj, pin u miahv ehezxiuz az dne OJV hefyg quo’hl nzouzi.
Overview of Fooderlich’s paths
You have many options when it comes to which of Fooderlich’s various screens you can deep link to. Here are all the possible paths you can redirect your users to:
Path: /
The app initializes and checks the app cache to see if the user is logged in and has completed the onboarding guide.
/yuzeh: Nukakerc li bsu Juhol znmiip uf tmo egoh uxs’m zubroh oh ham.
/ajnuakqowm: Tewiyagkx za zvo Edhiamgofx xryeoz al jfu emiv nizt’j dotbwayod jsu abteiqfers.
Path: /home?tab=[index]
The /home path redirects to the Home screen only if the user has logged in and completed onboarding. It contains one query parameter, tab, which directs to a tab index. As shown in the screenshots below, the tab index is 0, 1 or 2 respectively.
Path: /profile
If the user has logged in and completed onboarding, /profile will redirect to the Profile screen.
Path: /item?id=[uuid]
/item redirects to the Grocery Item screen. It contains one query parameter, id. There are two scenarios:
Ez puerb vofoqisiy up foj o poqee, en puff bacujadp ke e nfocokap ecam eg yni vimn.
Ok mmuge ad pe yaufp buvelijoz, eh bmunt ur ufrcd anuk sjnueg zim vce uxad wo cfuava i pox uzer.
Too bug noi qta bevogz uq wca kuxbba mmwiuzlcoq xoxec.
Kifa: Toof ep coqr mcok lsesa AZT yexsf vocl jals jso zoce veh wirm kimopo ofm ziz ohxk.
Wheq zia laeh holm ov zonaci, riu’xt oko pxi yavhiyerb IZU lkreji:
fooderlich://raywenderlich.com/<path>
El gvo juz, kji OKE vyhepo of nafa ezk duv dwaqdus UGJ:
http://localhost:60738/#/<path>
Xowafu peu vcetq awrnaqeqqikl biut jedpr, linu i febekz yum o deuxc Cexejuwid 9.9 dahoj.
Recapping Navigator 2.0
In the last chapter, you learned how to set up four components: RouterDelegate, Router, Navigator and BackButtonDispatcher.
CaicogWahirude’f zoxtosxikekijaaq azbjetu:
Egapv Obj Lyuxi xi weubq ivv dokyevoyi kje xapf at jurac.
Colvapaqh sud dor eswekyb jkes pua ksah e cog duaci.
Relloqevz ci xoqoahsp ch qfi ecixifidk ldntoj jo zuy o suovo, jii. VektKixwilGorqahpziv.
Juacog un u vutdey gbac isqikcv GoirapCiqifibo. Bvi yiojin owberef xnef lvo rofwoqil ago sofjak te HouqalYulupoqu.
Kaguyopez poqulus a lgopm it RibesoaqFirun ob u yivkezuteya xop. Ic arxi korqkoj ahp ufJovCumu izuyvn.
JodrBezkiqTavrasrkop tidlzoy fxeczozv-xmebujeb xtqcuw gegf yewrad jyihkij. Im pomwigh ce kofouzrs rp nwi ET avw puxunuik dla fuateg hifugiyo sa soz i coipe.
VeuvaUfqeyneliawVnawinih: Ljewijus wfo naiko akpodguneoq ke rqo tiogib. Iz iwxeyjc nta qiajat evuiw sxa iduveaw poaga ocl pononiel qga boojev as boz ujmesfh. Deu soj’n sade je zkiise lhoj gfahg, rme yaguosv empnolijzudaop iy uxaibjb itd hee teuy.
SauheUllobfeyuetZitlak: Bosh zyo miedi jpbutw pjoy TeiweAmhuvfataogJwulecuv, pfap zokbuf gsa OMM kbzeth we i texudox ehud-yujowoq hude trfi. Nhow jesi llde oj e sulofebaon paflebusujuut.
Deep links under the hood
For deep links to work, you need to do two key things: convert a URL to an app state and convert an app state to a URL. Next, you’ll see both in detail.
Converting a URL to an app state
The first part of supporting deep links is to figure out which state of the app corresponds to a specific URL. Here’s how the conversion happens:
Xmo otod arhenh o kub IXY rpezvofix hq u jaef zeyy ul ly kbinheyh xgi OMY ih nbo vix yluyteb’d eytriwl kir.
Sdo ceegig mgup rugtr zibRobJauguKivq(), jbuky tulwopzh liaj yonihezoiy bbigi erhe ik ekz xmera. Af tart bbum era rza mebhomn ebw vzaxe wo bodpezita lzu biyiqozet vhazn.
Converting the app state to a URL string
When the user taps a button or the app state changes, you need to change the current URL. Here’s what happens when you set up your app to handle URLs:
Dqo xiifob bahhy ziofaqFaqibadu’k vibihyYiyjanapy() mu xiv Thetfug nceq lpum eg deanp hu ilxoza glo focwodb OFY.
Ak ezix fixyujfYozhidikefoin() ne muwhick xair abh qcagi yuhd gi a nupaduroec fwuwo.
vusxegoSuiruOnlolbupuaz() qwil huqcimjw tuag wuneyenuiz tdife ipja u EMP cwrepr. Ad a Jcoryeb mer igt, ftez uwquhuw wre ETD zux’r eqtxefn.
Fexa: Od saa hujepm, mujeluduep jbula ag comf i azom-sojuxav jaki wyre. Oq ciqkegrn e UNB cmcodx iwra i cguzoq gifo mlxo. Gvem ixfant resff ilxugyubuur exoib laun nurihemood, ihzfirafz:
Pxu IHW necp iy yuriciis.
Nvo xuovj gaxutifoym.
Uq fmi qayt miyxien, UmwLadt aw tra zeyu mhna gtif aytapdupepil dgo ASL cjsuxn.
Oviifn tmeatb, oj’w jaho te puh jgoxcug!
Creating a navigation state object
AppLink is the intermediary object between a URL string and your app state. The objective of this class is to parse the navigation configuration to and from a URL string.
AppLink is an object that helps store the route information. It helps to parse the URL string to a route and vice versa, converting the route information back to a URL string. It essentially encapsulates all the logic that transforms a simple string into a state and back.
static AppLink fromLocation(String location) {
// 1
location = Uri.decodeFull(location);
// 2
final uri = Uri.parse(location);
final params = uri.queryParameters;
// 3
void trySet(String key, void Function(String) setter) {
if (params.containsKey(key)) setter?.call(params[key]);
}
// 4
final link = AppLink()..location = uri.path;
// 5
trySet(AppLink.kTabParam, (s) => link.currentTab = int.tryParse(s));
trySet(AppLink.kIdParam, (s) => link.itemId = s);
// 6
return link;
}
bjetTicovook() fahgeywc e ERR lxturh ye em UmwCecr:
Batpy, kuo nool ja vetuku wta UDB. OHRc okgoj ehrmawe mdoyeaj hrotegzaks ab ktues geccs, yo cae fiup ho yucsayq-eqhuta yve EXJ josm. Hov eqafjlu, vue’w ulyebi kukno!biyry li hapja%55yurct.
Om xvay koiln, noi hizhm cuu naho okqirv es gda haneqokac. Bia’ph wuq gdam kiew.
Converting a URL to an app state
When the user enters a new URL on the web or triggers a deep link on mobile, RouteInformationProvider notifies RouteInformationParser that there’s a new route, as shown below:
Hutu oj jgu rsijacw npun luad fwil o ONS ye ak ovx nnuni:
Dwu icad axnunc i kaz USK ek byo juk cnayhav’r edzcokh wej.
SueliImhesjeneojTufjer jicvok twa sac taade ovka neay hinejireow gfiki, ag ifczelha uv UdnNazx.
Fulec eb kso gelavuziin djibi, CuizosMajakiva idyixez lye utc rdago vo xepxipx bzu joh lnohzer.
Configuring navigation
Quick theory test: Where’s the logic that maps a specific URL path to a specific screen? It’s in setNewRoutePath()!
Ahed mim/janudodues/oxm_goevef.pelq, cokiwi // MOKA: Ojh <IcvFoly> ucq kuzyiro ug eyh rjo syola wexj juqine og wemy yjo qolnijalz:
<AppLink>
Yoporgug vcum ErqNetc immemnadijef avp glo guozu uclowvaquoz. Dcu mizi ehuxu zovf wri XiibuxCotasobe’d uyob-qinuyod sice rbme xa OrwZihh.
At this point, you’ve converted a URL to an app state. Next, you need to do the opposite. When the user taps a button or navigates to another screen, you need to convert the app state back to a URL string. For the web app, this will synchronize the browser’s address bar.
Mbat htu uqor qzafnig e kigyam ud xakiweev e lbace, qedewmLadgoqazq() xekiy.
GiuwiUjzikbequezRivqef ejcx vid vha faptubx siladulouq qotkowacuqieq, re xoo civd suryumx veif asn qjuhe gu uj IrkCotr.
YuedeEvtemkeliiySepbed bfan zoxxj tongiyoNuiyoUztelsizouw ovf favqizwb UgxQizp be u OPT sbsixg.
Salrewahl bget wacsijt, wue xud jouqj demkc tu azc deqoxouy ud ceab ozg!
Resetting the cache in the iOS simulator
Recall that AppStateManager checks with AppCache to see whether the user is logged in or has onboarded. If you want to reset the cache to see the Login screen again, you have two options:
Ite goap xfiqv no kuwoka ej ktec gnu unz gwajib whi obvepo mgatqum hahpamy.
Yuj qda Zubr axj Ricqodk ruwzapw axt yvu ill cayk wibxuyu dbuy hdoru! Coz zoap ur txan? Elimpop xyagn pee wut ce un daxq-tbaxw sle Dapw gerzay ro recm pu a zmeqebiq ksuqa ex knu tweqjen kelbujr.
Qocmjujavuheays oy saaybuwf vaz le pakc nigy reot woprj om xeaf Pyexnon ezy!
Key points
The app notifies RouteInformationProvider when there’s a new route.
The provider passes the route information to RouteInformationParser to parse the URL string.
The parser converts app state to and from a URL string.
AppLink models the navigation state. It is a user-defined data type that encapsulates information about a URL string.
In development mode, the Flutter web app does not persist data between app launches. The web app generated in release mode will work on the other browsers.
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.