package Ġme . h uf man . android aut oid rive . car app . navigation Ċ Ċ import Ġandroid . content . Context Ċ import Ġandroid . location . Address Ċ import Ġandroid . location . Geo coder Ċ import Ġandroid . util . Log Ċ import Ġcom . google . open location code . Open Location Code Ċ import Ġme . h uf man . android aut oid rive . car app . maps . Lat Long Ċ import Ġjava . io . IOException Ċ import Ġjava . net .* Ċ import Ġjava . util .* ĊĊ Ċ interface ĠAddress Searcher Ġ{ Ċ ĉ fun Ġsearch ( query : ĠString ): ĠAddress ? Ċ } Ċ Ċ class ĠAndroid Geo coder Searcher ( context : ĠContext ): ĠAddress Searcher Ġ{ Ċ ĉ val Ġgeo coder Ġ= ĠGeo coder ( context ) Ċ ĉ override Ġfun Ġsearch ( query : ĠString ): ĠAddress ? Ġ{ Ċĉ ĉ return Ġtry Ġ{ Ċĉĉ ĉ geo coder . get From Location Name ( query , Ġ 1 )?. get OrNull ( 0 ) Ċĉ ĉ } Ġcatch Ġ( e : ĠIOException ) Ġ{ Ċĉĉ ĉ null Ċĉ ĉ } Ċ ĉ } Ċ } Ċ Ċ class ĠNavigation Parser ( val Ġaddress Searcher : ĠAddress Searcher , Ġval Ġredirect or : ĠURL Redirect or ) Ġ{ Ċ ĉ comp anion Ġobject Ġ{ Ċĉ ĉ val ĠTAG Ġ= Ġ" Navigation Parser " Ċĉ ĉ val ĠNUM _ MATCH ER Ġ= ĠRegex ("^ ([ 0 - 9 ]+ )\\ s +( .* )") Ċĉ ĉ val ĠLAT L NG _ MATCH ER Ġ= ĠRegex ("^ ([- 0 - 9 . ]+ \\ s *, \\ s * [- 0 - 9 . ]+ ). * ") Ċĉ ĉ val ĠLAT L NG _ LABEL _ MATCH ER Ġ= ĠRegex ("^ q = ([- 0 - 9 . ]+ \\ s *, \\ s * [- 0 - 9 . ]+ \\ s *)( , [- 0 - 9 . ]+ )? \\ s *( \\ (( .* )\\ )) ?$ ") Ċĉ ĉ val ĠPL US CODE _ SPLIT TER Ġ= ĠRegex ("^ ([ 2 - 9 CF GH J MP QR V WX + ]+) ([ , Ġ]( .* )) ?") Ċĉ ĉ val ĠPL US CODE _ URL _ MATCH ER Ġ= ĠRegex ("^ /+ ([ 2 - 9 CF GH J MP QR V WX + ]+ ([ , Ġ]( .* )) ? )$ ") Ċĉ ĉ val ĠGOOGLE _ OL C _ MATCH ER Ġ= ĠRegex ("^ / maps / dir /+ ([ 2 - 9 CF GH J MP QR V WX + ]+ ([ , Ġ]( .* )) ?) ") Ċĉ ĉ val ĠGOOGLE _ Q _ MATCH ER Ġ= ĠRegex ("^ (.* [ & ? ]) ? q = ([^ & ]* ). * ") Ċĉ ĉ val ĠGOOGLE _ QL L _ MATCH ER Ġ= ĠRegex ("^ (.* [ & ? ]) ? q = ([- 0 - 9 . ]+ , \\ s * [- 0 - 9 . ]+ ). * ") Ċĉ ĉ val ĠGOOGLE _ LL _ MATCH ER Ġ= ĠRegex ("^ (.* [ & ? ]) ? ll = ([- 0 - 9 . ]+ , \\ s * [- 0 - 9 . ]+ ). * ") Ċĉ ĉ val ĠGOOGLE _ SEARCH PATH LL _ MATCH ER Ġ= ĠRegex ("/ maps / search /+ () ([- 0 - 9 . ]+ \\ s *, \\ s * [- 0 - 9 . ]+ \\ s * ). * ") Ċĉ ĉ val ĠGOOGLE _ PLACE PATH LL _ MATCH ER Ġ= ĠRegex ("/ maps / place / ([^ / ]*) /+ @ ([- 0 - 9 . ]+ \\ s *, \\ s * [- 0 - 9 . ]+ \\ s * ). * ") Ċĉ ĉ val ĠGOOGLE _ DIR PATH LL _ MATCH ER Ġ= ĠRegex ("/ maps / dir / [^ / ] */ + () ([- 0 - 9 . ]+ \\ s *, \\ s * [- 0 - 9 . ]+ \\ s * ). * ") Ċĉ ĉ val ĠGOOGLE _ DIR PATH _ MATCH ER Ġ= ĠRegex ("/ maps / dir / [^ / ] */ + ([^ / ]+ ). * ") Ċĉ ĉ val ĠGOOGLE _ PLACE PATH _ MATCH ER Ġ= ĠRegex ("/ maps / place /+ ([^ / ]+ ). * ") Ċĉ ĉ val ĠGOOGLE _ SEARCH PATH _ MATCH ER Ġ= ĠRegex ("/ maps / search /+ ([^ / ]+ ). * ") Ċĉ ĉ val ĠGOOGLE _ QUERY LL _ MATCH ER Ġ= ĠRegex ("^ (.* [ & ? ]) ?( q | query | d addr | destination ) =( loc :\\ s + )? ([- 0 - 9 . ]+ \\ s *, \\ s * [- 0 - 9 . ]+ \\ s * ). * ") Ċĉ ĉ val ĠGOOGLE _ QUERY _ MATCH ER Ġ= ĠRegex ("^ (.* [ & ? ]) ?( q | query | d addr | destination )= ([^ & ]* ). * ") ĊĊĉ ĉ fun Ġlat long To Address ( lat long : ĠString , Ġlabel : ĠString Ġ= Ġ"") : ĠAddress Ġ{ Ċĉĉ ĉ val Ġsplits Ġ= Ġlat long . split (',') Ċĉĉ ĉ return Ġlat long To Address ( Lat Long ( splits [ 0 ]. toDouble (), Ġsplits [ 1 ]. toDouble ()), Ġlabel ) Ċĉ ĉ } ĊĊĉ ĉ fun Ġlat long To Address ( lat long : ĠLat Long , Ġlabel : ĠString Ġ= Ġ"") : ĠAddress Ġ{ Ċĉĉ ĉ return ĠAddress ( Locale . ROOT ). apply Ġ{ Ċĉĉĉ ĉ latitude Ġ= Ġlat long . latitude Ċĉĉĉ ĉ longitude Ġ= Ġlat long . longitude Ċĉĉĉ ĉ feature Name Ġ= Ġlabel Ċĉĉ ĉ } Ċĉ ĉ } ĊĊĉ ĉ fun Ġparse Uri ( url : ĠString ): ĠURI Ġ{ Ċĉĉ ĉ try Ġ{ Ċĉĉĉ ĉ return ĠURI ( url ) Ċĉĉ ĉ } Ġcatch Ġ( e : ĠUR ISyntaxException ) Ġ{ Ċĉĉĉ ĉ return ĠURI ( URL Encoder . encode ( url , Ġ" UTF - 8 ")) Ċĉĉ ĉ } Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ fun Ġparse Url ( url : ĠString ?): ĠAddress ? Ġ{ Ċĉ ĉ url Ġ?: Ġreturn Ġnull Ċĉ ĉ if Ġ( url . startsWith (" geo :" )) Ġreturn Ġparse Geo Url ( url ) Ċĉ ĉ if Ġ( url . startsWith (" google . navigation :" )) Ġreturn Ġparse Google Uri ( url ) Ċĉ ĉ if Ġ( url . startsWith (" http ")) Ġ{ Ċĉĉ ĉ return Ġparse Plus Url ( url ) Ġ?: Ċĉĉĉ ĉ parse Google Url ( url ) Ċĉ ĉ } Ċĉ ĉ return Ġnull Ċ ĉ } ĊĊ ĉ private Ġfun Ġparse Geo Url ( url : ĠString ): ĠAddress ? Ġ{ Ċĉ ĉ val Ġuri Ġ= Ġparse Uri ( url ) Ċĉ ĉ val Ġdata Ġ= Ġuri . scheme Specific Part . replace ('+ ', Ġ' Ġ') Ċĉ ĉ val Ġquery Ġ= Ġif Ġ( data . contains (' ? ')) Ġ{ Ġdata . split (' ?', Ġlimit = 2 )[ 1 ] Ġ} Ġelse Ġnull ĊĊĉ ĉ val Ġauthority Result Ġ= ĠLAT L NG _ MATCH ER . match Ent ire ( data ) Ċĉ ĉ val Ġquery Result Ġ= ĠLAT L NG _ LABEL _ MATCH ER . match Ent ire ( query Ġ?: Ġ"") ĊĊĉ ĉ // Ġfind Ġa Ġtext Ġquery Ċĉ ĉ // Ġgeo : 0 , 0 ? q = 1 6 0 0 ĠAmp hit heat re ĠPark way , ĠMountain + View , ĠCalifornia Ċĉ ĉ if Ġ( query ?. startsWith (" q =") Ġ== Ġtrue Ġ&& Ġquery Result Ġ== Ġnull ) Ġ{ Ċĉĉ ĉ val Ġsearch Ġ= Ġquery . substring ( 2 ) Ċĉĉ ĉ val Ġresult Ġ= Ġaddress Searcher . search ( search ) Ċĉĉ ĉ if Ġ( result Ġ!= Ġnull ) Ġ{ Ċĉĉĉ ĉ Log . i ( TAG , Ġ" Parsed Ġ$ search Ġto Ġ$ result ") Ċĉĉĉ ĉ return Ġresult Ċĉĉ ĉ } Ċĉ ĉ } ĊĊĉ ĉ // Ġlat lng Ġin Ġthe Ġgeo Ġurl Ċĉ ĉ val Ġlat lng Ġ= Ġquery Result ?. group Values ?. get OrNull ( 1 ) Ġ?: Ġauthority Result ?. group Values ?. get OrNull ( 1 ) Ċĉ ĉ val Ġlat long Ġ= Ġif Ġ( lat lng ?. contains (',') Ġ== Ġtrue ) Ġ{ Ċĉĉ ĉ val Ġsplits Ġ= Ġlat lng . split (',') Ċĉĉ ĉ Lat Long ( splits [ 0 ]. trim (). toDouble (), Ġsplits [ 1 ]. trim (). toDouble ()) Ċĉ ĉ } Ġelse Ġnull Ċĉ ĉ if Ġ( lat long ?. latitude Ġ== Ġ 0 . 0 Ġ&& Ġlat long . latitude Ġ== Ġ 0 . 0 ) Ġreturn Ġnull Ċĉ ĉ val Ġlabel Ġ= Ġquery Result ?. group Values ?. get OrNull ( 4 ) Ġ?: Ġ"" Ċĉ ĉ if Ġ( lat long Ġ!= Ġnull ) Ġreturn Ġlat long To Address ( lat long , Ġlabel ) ĠĠ Ġ// Ġfound Ġa Ġlat long ĊĊĉ ĉ return Ġnull Ċ ĉ } ĊĊ ĉ private Ġfun Ġparse Plus Url ( url : ĠString ): ĠAddress ? Ġ{ Ċĉ ĉ if Ġ(! url . contains (" plus . codes ")) Ġreturn Ġnull Ċĉ ĉ val Ġuri Ġ= Ġparse Uri ( url ) Ċĉ ĉ val Ġmatcher Ġ= ĠPL US CODE _ URL _ MATCH ER . match Ent ire ( uri . path ) Ġ?: Ġreturn Ġnull Ċĉ ĉ return Ġparse Plus Code ( matcher . group Values [ 1 ]) Ċ ĉ } ĊĊ ĉ private Ġfun Ġparse Plus Code ( plus Code : ĠString ): ĠAddress ? Ġ{ Ċĉ ĉ val Ġparsed Ġ= ĠPL US CODE _ SPLIT TER . match Ent ire ( plus Code ) Ġ?: Ġreturn Ġnull Ċĉ ĉ val Ġcode Ġ= Ġparsed . group Values [ 1 ] Ċĉ ĉ val Ġreference Ġ= Ġparsed . group Values [ 3 ] Ċĉ ĉ var Ġo lc Ġ= Ġtry Ġ{ Ċĉĉ ĉ Open Location Code ( code ) Ċĉ ĉ } Ġcatch Ġ( e : ĠIllegalArgumentException ) Ġ{ Ċĉĉ ĉ return Ġnull Ċĉ ĉ } Ċĉ ĉ if Ġ( ol c . is Short Ġ&& Ġreference . isNotBlank ()) Ġ{ Ċĉĉ ĉ val Ġreference Name Ġ= Ġreference . replace ('+ ', Ġ' Ġ'). trim () Ċĉĉ ĉ val Ġresult Ġ= Ġaddress Searcher . search ( reference Name ) Ġ?: Ġreturn Ġnull Ċĉĉ ĉ ol c Ġ= Ġo lc . recover ( result . latitude , Ġresult . longitude ) Ċĉ ĉ } Ġelse Ġif Ġ( ol c . is Short ) Ġ{ Ċĉĉ ĉ // Ġcan 't Ġresolve Ġshort Ġcode Ċĉĉ ĉ return Ġnull Ċĉ ĉ } ĊĊĉ ĉ val Ġarea Ġ= Ġo lc . decode () Ċĉ ĉ return Ġlat long To Address ( Lat Long ( area . center Latitude , Ġarea . center Longitude )) Ċ ĉ } ĊĊ ĉ private Ġfun Ġparse Google Uri ( url : ĠString ): ĠAddress ? Ġ{ Ċĉ ĉ // Ġhttps :// developers . google . com / maps / documentation / urls / android - int ents Ċĉ ĉ // Ġgoogle . navigation : q = Tar ong a + Z oo , + Sy dn ey + A ustralia Ċĉ ĉ val Ġuri Ġ= Ġparse Uri ( url ) Ċĉ ĉ val Ġdata Ġ= Ġuri . scheme Specific Part . replace ('+ ', Ġ' Ġ') Ċĉ ĉ val Ġgoogle QL L Ġ= ĠGOOGLE _ QL L _ MATCH ER . match Ent ire ( data ) Ċĉ ĉ if Ġ( google QL L Ġ!= Ġnull ) Ġ{ Ċĉĉ ĉ return Ġlat long To Address ( google QL L . group Values [ 2 ]) Ċĉ ĉ } ĊĊĉ ĉ val Ġgoogle Q Ġ= ĠGOOGLE _ Q _ MATCH ER . match Ent ire ( data ) Ċĉ ĉ if Ġ( google Q Ġ!= Ġnull ) Ġ{ Ċĉĉ ĉ val Ġq Ġ= Ġgoogle Q . group Values [ 2 ] Ċĉĉ ĉ val Ġresult Ġ= Ġaddress Searcher . search ( q ) Ċĉĉ ĉ if Ġ( result Ġ!= Ġnull ) Ġ{ Ċĉĉĉ ĉ Log . i ( TAG , Ġ" Parsed Ġ$ q Ġto Ġ$ result ") Ċĉĉĉ ĉ return Ġresult Ċĉĉ ĉ } Ċĉ ĉ } ĊĊĉ ĉ return Ġnull Ċ ĉ } ĊĊ ĉ private Ġfun Ġparse Google Url ( url : ĠString ): ĠAddress ? Ġ{ Ċĉ ĉ val Ġorig Uri Ġ= Ġparse Uri ( url ) Ċĉ ĉ // Ġtry Ġone Ġlevel Ġof Ġredirect Ċĉ ĉ val Ġuri Ġ= Ġif Ġ( orig Uri . authority Ġ== Ġ" goo . gl " Ġ|| Ġorig Uri . authority Ġ== Ġ" maps . app . goo . gl ") Ġ{ Ċĉĉ ĉ redirect or . try Redirect ( url )?. let Ġ{ Ġparse Uri ( it ) Ġ} Ġ?: Ġorig Uri Ċĉ ĉ } Ġelse Ġ{ Ġorig Uri Ġ} Ċĉ ĉ if Ġ(! uri . authority . contains (" google ")) Ġreturn Ġnull ĊĊĉ ĉ val Ġpath Ġ= Ġuri . path ?. replace ('+ ', Ġ' Ġ') Ġ?: Ġ"" Ċĉ ĉ // Ġhttps :// www . google . com / maps / dir / Current + Location / 4 7 . 5 9 5 1 5 1 8 ,- 1 2 2 . 3 3 1 6 3 9 3 Ċĉ ĉ // Ġhttp :// maps . google . com / maps / place /< name >/ @ 4 7 . 5 9 5 1 5 1 8 ,- 1 2 2 . 3 3 1 6 3 9 3 , 1 5 z Ċĉ ĉ // Ġhttps :// www . google . com / maps / search / 4 7 . 5 9 5 1 5 1 8 ,- 1 2 2 . 3 3 1 6 3 9 3 Ċĉ ĉ val Ġgoogle Path LL Ġ= ĠGOOGLE _ DIR PATH LL _ MATCH ER . match Ent ire ( path ) Ġ?: ĠGOOGLE _ PLACE PATH LL _ MATCH ER . match Ent ire ( path ) Ġ?: ĠGOOGLE _ SEARCH PATH LL _ MATCH ER . match Ent ire ( path ) Ċĉ ĉ if Ġ( google Path LL Ġ!= Ġnull ) Ġ{ Ċĉĉ ĉ return Ġlat long To Address ( google Path LL . group Values [ 2 ], Ġgoogle Path LL . group Values [ 1 ]) Ċĉ ĉ } Ċĉ ĉ // Ġhttps :// www . google . com / maps / dir // Q JQ 5 + XX , San % 2 0 Fr anc isco Ċĉ ĉ val Ġgoogle O lc Ġ= ĠGOOGLE _ OL C _ MATCH ER . match Ent ire ( uri . path Ġ?: Ġ"") Ċĉ ĉ if Ġ( google O lc Ġ!= Ġnull ) Ġ{ Ċĉĉ ĉ return Ġparse Plus Code ( google O lc . group Values [ 1 ]) Ċĉ ĉ } ĊĊĉ ĉ // Ġhttps :// www . google . com / maps / search / 1 9 7 0 + N ag lee + A ve + San + J ose , + CA Ċĉ ĉ // Ġhttps :// www . google . com / maps / dir / Current + Location / 1 9 7 0 + N ag lee + A ve + San + J ose , + CA Ċĉ ĉ val Ġgoogle Path Ġ= ĠGOOGLE _ DIR PATH _ MATCH ER . match Ent ire ( path ) Ġ?: GOOGLE _ PLACE PATH _ MATCH ER . match Ent ire ( path ) Ġ?: ĠGOOGLE _ SEARCH PATH _ MATCH ER . match Ent ire ( path ) Ċĉ ĉ if Ġ( google Path Ġ!= Ġnull ) Ġ{ Ċĉĉ ĉ val Ġresult Ġ= Ġaddress Searcher . search ( google Path . group Values [ 1 ]) Ċĉĉ ĉ if Ġ( result Ġ!= Ġnull ) Ġ{ Ċĉĉĉ ĉ Log . i ( TAG , Ġ" Parsed Ġ${ google Path . group Values [ 1 ]} Ġto Ġ$ result ") Ċĉĉĉ ĉ return Ġresult Ċĉĉ ĉ } Ċĉ ĉ } ĊĊĉ ĉ val Ġquery Ġ= Ġuri . query ?. replace ('+ ', Ġ' Ġ') Ġ?: Ġ"" ĊĊĉ ĉ // Ġhttps :// developers . google . com / maps / documentation / urls / get - started Ċĉ ĉ // Ġhttps :// www . google . com / maps / search /? api = 1 & query = 4 7 . 5 9 5 1 5 1 8 ,- 1 2 2 . 3 3 1 6 3 9 3 Ċĉ ĉ // Ġhttps :// www . google . com / maps / dir /? api = 1 & destination = 4 7 . 5 9 5 1 5 1 8 ,- 1 2 2 . 3 3 1 6 3 9 3 Ċĉ ĉ val Ġgoogle Query LL Ġ= ĠGOOGLE _ QUERY LL _ MATCH ER . match Ent ire ( query ) Ċĉ ĉ val Ġgoogle Query Ġ= ĠGOOGLE _ QUERY _ MATCH ER . match Ent ire ( query ) Ċĉ ĉ if Ġ( google Query LL Ġ!= Ġnull ) Ġ{ Ċĉĉ ĉ return Ġlat long To Address ( google Query LL . group Values [ 4 ], Ġ"") Ċĉ ĉ } ĊĊĉ ĉ // Ġsome Ġurls Ġcan Ġinclude Ġan Ġ& ll Ġparameter , Ġuse Ġthat Ġinstead Ġof Ġconduct ing Ġa Ġsearch Ċĉ ĉ // Ġhttp :// maps . google . com / maps ? q = 1 9 7 0 + N ag lee + A ve + San + J ose , + CA + 9 5 1 2 6 & ie = UTF 8 & hl = en & hq =& h near = 1 9 7 0 + N ag lee + A ve , + San + J ose , + Santa + Cl ara , + California + 9 5 1 2 6 & ll = 3 7 . 3 3 5 3 7 8 ,- 1 2 1 . 9 3 1 0 9 8 & spn = 0 , 3 5 9 . 9 6 7 0 6 2 & z = 1 6 & layer = c & cb ll = 3 7 . 3 2 8 3 0 4 ,- 1 2 1 . 9 3 1 3 4 2 & pan oid = k fy FC 9 p O gb Tv Y FI k HY ns MQ & cb p = 1 2 , 1 9 3 . 0 3 ,, 0 , 2 . 3 6 Ċĉ ĉ // Ġhttp :// maps . google . com / maps ? q = loc : 4 7 . 5 9 5 1 5 1 8 ,- 1 2 2 . 3 3 1 6 3 9 3 & z = 1 5 Ċĉ ĉ val Ġgoogle LL Ġ= ĠGOOGLE _ LL _ MATCH ER . match Ent ire ( query ) Ċĉ ĉ if Ġ( google LL Ġ!= Ġnull ) Ġ{ Ċĉĉ ĉ return Ġlat long To Address ( google LL . group Values [ 2 ], Ġgoogle Query ?. group Values ?. get OrNull ( 3 ) Ġ?: Ġ"") Ċĉ ĉ } ĊĊĉ ĉ // Ġhttps :// developers . google . com / maps / documentation / urls / get - started Ċĉ ĉ // Ġhttps :// www . google . com / maps / search /? api = 1 & query = p izza + se attle + wa Ċĉ ĉ // Ġhttps :// www . google . com / maps / dir /? api = 1 & destination = p izza + se attle + wa Ċĉ ĉ if Ġ( google Query Ġ!= Ġnull ) Ġ{ Ċĉĉ ĉ val Ġresult Ġ= Ġaddress Searcher . search ( google Query . group Values [ 3 ]) Ċĉĉ ĉ if Ġ( result Ġ!= Ġnull ) Ġ{ Ċĉĉĉ ĉ Log . i ( TAG , Ġ" Parsed Ġ${ google Query . group Values [ 3 ]} Ġto Ġ$ result ") Ċĉĉĉ ĉ return Ġresult Ċĉĉ ĉ } Ċĉ ĉ } ĊĊĉ ĉ return Ġnull Ċ ĉ } Ċ } Ċ Ċ class ĠURL Redirect or Ġ{ Ċ ĉ fun Ġtry Redirect ( url : ĠString ): ĠString ? Ġ{ Ċĉ ĉ val Ġparsed Ġ= ĠURL ( url ) Ċĉ ĉ val Ġconnection Ġ= Ġparsed . open Connection () Ġas ? ĠHttp URLConnection Ċĉ ĉ connection ?. instance Follow Redirect s Ġ= Ġfalse Ċĉ ĉ return Ġconnection ?. getHeader Field (" Location ") Ċ ĉ } Ċ }