package Ġme . h uf man . android aut oid rive . car app . maps Ċ Ċ import Ġandroid . Manifest Ċ import Ġandroid . content . Context Ċ import Ġandroid . content . pm . PackageManager Ċ import Ġandroid . hardware . display . Virtual Display Ċ import Ġandroid . location . Location Ċ import Ġandroid . os . Handler Ċ import Ġandroid . os . Looper Ċ import Ġandroidx . core . content . Context Compat Ċ import Ġandroid . util . Log Ċ import Ġcom . google . android . gms . location . Location Callback Ċ import Ġcom . google . android . gms . location . Location Request Ċ import Ġcom . google . android . gms . location . Location Result Ċ import Ġcom . google . android . gms . location . Location Services Ċ import Ġcom . google . android . gms . maps . Camera Update Factory Ċ import Ġcom . google . android . gms . maps . Google Map Ċ import Ġcom . google . android . gms . maps . model .* Ċ import Ġcom . google . android . libraries . places . api . Places Ċ import Ġcom . google . android . libraries . places . api . model .* Ċ import Ġcom . google . android . libraries . places . api . net . Fetch Place Request Ċ import Ġcom . google . android . libraries . places . api . net . Find Autocomplete Pred i ctions Request Ċ import Ġcom . google . android . libraries . places . api . net . Places Client Ċ import Ġcom . google . maps . Directions Api Ċ import Ġcom . google . maps . Geo Api Context Ċ import Ġcom . google . maps . Pending Result Ċ import Ġcom . google . maps . model . Directions Result Ċ import Ġcom . google . maps . model . Travel Mode Ċ import Ġme . h uf man . android aut oid rive . AppSettings Ċ import Ġme . h uf man . android aut oid rive . AppSettings Observer Ċ import Ġme . h uf man . android aut oid rive . R Ċ import Ġjava . util . concurrent . TimeUnit Ċ import Ġkotlin . math . max Ċ import Ġkotlin . math . min Ċ Ċ class ĠG Maps Controller ( private Ġval Ġcontext : ĠContext , Ġprivate Ġval Ġcar Location Provider : ĠCar Location Provider , Ġprivate Ġval Ġresults Controller : ĠMap Results Controller , Ġprivate Ġval Ġvirtual Display : ĠVirtual Display , Ġval Ġapp Settings : ĠApp Settings Observer ): ĠMap Interaction Controller Ġ{ Ċ ĉ val ĠTAG Ġ= Ġ" G Maps Controller " Ċ ĉ var Ġhandler Ġ= ĠHandler ( context . main Looper ) Ċ ĉ var Ġprojection : ĠG Maps Projection ? Ġ= Ġnull ĊĊ ĉ private Ġval ĠSH UT DOWN _ WAIT _ INTERVAL Ġ= Ġ 1 2 0 0 0 0 L ĠĠ Ġ// Ġmilliseconds Ġof Ġin activity Ġbefore Ġshut ting Ġdown Ġmap Ċ ĉ private Ġval ĠSEARCH _ SESSION _ TTL Ġ= Ġ 1 8 0 0 0 0 L ĠĠĠ Ġ// Ġnumber Ġof Ġmilliseconds Ġthat Ġa Ġsearch Ġsession Ġcan Ġlive ĠĠ Ġhttps :// stackoverflow . com / a / 5 2 3 3 9 8 5 8 ĊĊ ĉ private Ġval Ġplaces Client : ĠPl aces Client Ċ ĉ private Ġval Ġgeo Client Ġ= ĠGeo Api Context (). set Query RateLimit ( 3 ) Ċĉĉ ĉ . set ApiKey ( context . package Manager . getApplication Info ( context . packageName , ĠPackage Manager . GET _ META _ DATA ) Ċĉĉĉĉ ĉ . metaData . getString (" com . google . android . geo . API _ KEY ")) Ċĉĉ ĉ . set Connect Timeout ( 2 , ĠTimeUnit . SECONDS ) Ċĉĉ ĉ . set Read Timeout ( 2 , ĠTimeUnit . SECONDS ) Ċĉĉ ĉ . set Write Timeout ( 2 , ĠTimeUnit . SECONDS ) ĊĊ ĉ private Ġvar Ġlast Settings Time Ġ= Ġ 0 L ĠĠ Ġ// Ġthe Ġlast Ġtime Ġwe Ġchecked Ġsettings , Ġfor Ġday / night Ġcheck Ċ ĉ private Ġval ĠSET T INGS _ TIME _ INTERVAL Ġ= Ġ 5 Ġ* Ġ 6 0 0 0 0 Ġ Ġ// Ġmilliseconds Ġbetween Ġchecking Ġday / night ĊĊ ĉ val Ġlocation Provider Ġ= ĠLocation Services . getF used Location Provider Client ( context ) Ċ ĉ val Ġlocation Callback Ġ= ĠLocation Callback Impl () Ċ ĉ val Ġg Map Location Source Ġ= ĠG Map Location Source () Ċ ĉ var Ġcurrent Location : ĠLocation ? Ġ= Ġnull ĊĊ ĉ var Ġanim ating Camera Ġ= Ġfalse Ċ ĉ var Ġzoom ing Camera Ġ= Ġfalse ĠĠ Ġ// Ġwhether Ġthe Ġanimation Ġstarted Ġwith Ġa Ġzoom Ġcommand , Ġand Ġthus Ġshould Ġbe Ġcancel able Ċ ĉ val Ġanimation Finished Callback Ġ= Ġobject : ĠGoogle Map . Cancel able Callback Ġ{ Ċĉ ĉ override Ġfun Ġon Finish () Ġ{ Ċĉĉ ĉ anim ating Camera Ġ= Ġfalse Ċĉĉ ĉ zoom ing Camera Ġ= Ġfalse Ċĉĉ ĉ start Zoom Ġ= Ġcurrent Zoom Ġ// Ġrestore Ġa Ġback gro unded Ġmap Ġto Ġthis Ġzoom Ġlevel Ċĉ ĉ } Ċĉ ĉ override Ġfun Ġon Cancel () Ġ{ Ċĉĉ ĉ anim ating Camera Ġ= Ġfalse Ċĉ ĉ } Ċ ĉ } Ċ ĉ private Ġvar Ġstart Zoom Ġ= Ġ 6 f Ġ Ġ// Ġwhat Ġzoom Ġlevel Ġwe Ġstart Ġthe Ġprojection Ġwith Ċ ĉ private Ġvar Ġcurrent Zoom Ġ= Ġ 1 5 f Ċ ĉ private Ġvar Ġsearch Session Start : ĠLong Ġ= Ġ 0 ĠĠĠ Ġ// Ġwhen Ġthe Ġsearch Ġsession Ġstarted Ċ ĉ private Ġvar Ġsearch Session Cons umed Ġ= Ġtrue ĠĠĠ Ġ// Ġif Ġwe Ġused Ġthe Ġsearch Ġsession Ġfor Ġa ĠPlace ĠInfo Ġlookup Ċ ĉ private Ġvar Ġsearch Session : ĠAuto complete Session Token ? Ġ= Ġnull Ġ// Ġthe Ġsearch Ġsession Ġtoken Ċ ĉ private Ġvar Ġcurrent Nav Destination : ĠLat Long ? Ġ= Ġnull Ċ ĉ var Ġcurrent Nav Route : ĠList < LatLng >? Ġ= Ġnull ĊĊ ĉ init Ġ{ Ċĉ ĉ val Ġapi _ key Ġ= Ġcontext . package Manager . getApplication Info ( context . packageName , ĠPackage Manager . GET _ META _ DATA ) Ċĉĉĉ ĉ . metaData . getString (" com . google . android . geo . API _ KEY ") Ġ?: Ġ"" Ċĉ ĉ Places . initialize ( context , Ġapi _ key ) Ċĉ ĉ places Client Ġ= ĠPl aces . create Client ( context ) ĊĊĉ ĉ car Location Provider . callback Ġ= Ġ{ Ġlocation Ġ-> Ċĉĉ ĉ if Ġ(! app Settings [ AppSettings . KEYS . MAP _ USE _ PHONE _ GPS ]. to Boolean ()) Ġ{ Ċĉĉĉ ĉ handler . post Ġ{ Ċĉĉĉĉ ĉ on Location Update ( location ) Ċĉĉĉ ĉ } Ċĉĉ ĉ } Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ override Ġfun Ġshow Map () Ġ{ Ċĉ ĉ Log . i ( TAG , Ġ" Beginning Ġmap Ġprojection ") ĊĊĉ ĉ // Ġcancel Ġa Ġshutdown Ġtimer Ċĉ ĉ handler . remove Callbacks ( shutdown Map Runnable ) ĊĊĉ ĉ if Ġ( projection Ġ== Ġnull ) Ġ{ Ċĉĉ ĉ Log . i ( TAG , Ġ" First Ġshowing Ġof Ġthe Ġmap ") Ċĉĉ ĉ val Ġprojection Ġ= ĠG Maps Projection ( context , Ġvirtual Display . display , Ġapp Settings , Ġg Map Location Source ) Ċĉĉ ĉ this . projection Ġ= Ġprojection Ċĉĉ ĉ projection . map Listener Ġ= ĠRunnable Ġ{ Ċĉĉĉ ĉ // Ġwhen Ġget Map Async Ġfinishes Ċĉĉĉ ĉ init Camera () Ċĉĉĉ ĉ draw Navigation () ĠĠĠ Ġ// Ġrestore Ġnavigation , Ġif Ġit 's Ġstill Ġgoing Ċĉĉ ĉ } ĊĊĉ ĉ } Ċĉ ĉ if Ġ( projection ?. is Showing Ġ== Ġfalse ) Ġ{ Ċĉĉ ĉ projection ?. show () Ċĉ ĉ } Ċĉ ĉ // Ġn udge Ġthe Ġcamera Ġto Ġtrigger Ġa Ġredraw , Ġin Ġcase Ġwe Ġchanged Ġwindows Ċĉ ĉ if Ġ(! anim ating Camera ) Ġ{ Ċĉĉ ĉ projection ?. map ?. move Camera ( Camera Update Factory . scroll By ( 1 f , Ġ 1 f )) Ċĉ ĉ } ĊĊĉ ĉ // Ġregister Ġfor Ġlocation Ġupdates Ċĉ ĉ if Ġ( app Settings [ AppSettings . KEYS . MAP _ USE _ PHONE _ GPS ]. to Boolean () Ġ&& Ċĉĉĉ ĉ Context Compat . check Self Permission ( context , ĠManifest . permission . ACCESS _ F INE _ LOCATION ) Ġ== ĠPackage Manager . PERMISSION _ GRAN TED ) Ġ{ Ċĉĉ ĉ val Ġlocation Request Ġ= ĠLocation Request . create () Ċĉĉ ĉ location Request . priority Ġ= ĠLocation Request . PRIORITY _ HIGH _ AC CUR ACY Ċĉĉ ĉ location Request . interval Ġ= Ġ 3 0 0 0 Ċĉĉ ĉ location Request . fast est Interval Ġ= Ġ 5 0 0 ĊĊĉĉ ĉ location Provider . request Location Updates ( location Request , Ġlocation Callback , Ġcontext . main Looper ) Ċĉ ĉ } Ċĉ ĉ car Location Provider . start () Ċ ĉ } ĊĊ ĉ override Ġfun Ġpause Map () Ġ{ Ċĉ ĉ location Provider . remove Location Updates ( location Callback ) Ċĉ ĉ car Location Provider . stop () ĊĊĉ ĉ handler . post Delayed ( shutdown Map Runnable , ĠSH UT DOWN _ WAIT _ INTERVAL ) Ċ ĉ } ĊĊ ĉ private Ġval Ġshutdown Map Runnable Ġ= ĠRunnable Ġ{ Ċĉ ĉ Log . i ( TAG , Ġ" Shut ting Ġdown ĠG Map Projection Ġdue Ġto Ġin activity Ġof Ġ${ SHUT DOWN _ WAIT _ INTERVAL } ms ") Ċĉ ĉ projection ?. hide () Ċĉ ĉ projection Ġ= Ġnull Ċ ĉ } ĊĊ ĉ inner Ġclass ĠLocation Callback Impl : ĠLocation Callback () Ġ{ Ċĉ ĉ override Ġfun Ġon Location Result ( result : ĠLocation Result ?) Ġ{ Ċĉĉ ĉ if Ġ( result ?. last Location Ġ!= Ġnull Ġ&& Ġapp Settings [ AppSettings . KEYS . MAP _ USE _ PHONE _ GPS ]. to Boolean ()) Ġ{ Ċĉĉĉ ĉ on Location Update ( result . last Location ) Ċĉĉ ĉ } Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ private Ġfun Ġon Location Update ( location : ĠLocation ) Ġ{ Ċĉ ĉ if Ġ( current Location Ġ== Ġnull ) Ġ{ Ġ Ġ// Ġfirst Ġview Ċĉĉ ĉ init Camera () Ċĉ ĉ } ĊĊĉ ĉ // Ġsave Ġthe Ġnew Ġlocation Ġand Ġmove Ġthe Ġcamera Ċĉ ĉ current Location Ġ= Ġlocation Ċĉ ĉ update Camera () ĊĊĉ ĉ // Ġmove Ġthe Ġmap Ġdot Ġto Ġthe Ġnew Ġlocation Ċĉ ĉ g Map Location Source . on Location Update ( location ) ĊĊĉ ĉ // Ġcheck Ġto Ġre - apply Ġday / night Ġsettings Ġafter Ġan Ġinterval Ċĉ ĉ if Ġ( last Settings Time Ġ+ ĠSET T INGS _ TIME _ INTERVAL Ġ< ĠSystem . currentTimeMillis ()) Ġ{ Ċĉĉ ĉ projection ?. apply Settings () Ċĉĉ ĉ last Settings Time Ġ= ĠSystem . currentTimeMillis () Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ override Ġfun Ġzoom In ( steps : ĠInt ) Ġ{ Ċĉ ĉ Log . i ( TAG , Ġ" Zoom ing Ġmap Ġin Ġ$ steps Ġsteps ") Ċĉ ĉ zoom ing Camera Ġ= Ġtrue Ċĉ ĉ current Zoom Ġ= Ġmin ( 2 0 f , Ġcurrent Zoom Ġ+ Ġsteps ) Ċĉ ĉ update Camera () Ċ ĉ } Ċ ĉ override Ġfun Ġzoom Out ( steps : ĠInt ) Ġ{ Ċĉ ĉ Log . i ( TAG , Ġ" Zoom ing Ġmap Ġout Ġ$ steps Ġsteps ") Ċĉ ĉ zoom ing Camera Ġ= Ġtrue Ċĉ ĉ current Zoom Ġ= Ġmax ( 0 f , Ġcurrent Zoom Ġ- Ġsteps ) Ċĉ ĉ update Camera () Ċ ĉ } ĊĊ ĉ private Ġfun Ġinit Camera () Ġ{ Ċĉ ĉ // Ġset Ġthe Ġcamera Ġto Ġthe Ġstarting Ġposition Ċĉ ĉ val Ġlocation Ġ= Ġcurrent Location Ċĉ ĉ if Ġ( location Ġ!= Ġnull ) Ġ{ Ċĉĉ ĉ val Ġcamera Location Ġ= ĠLat Lng ( location . latitude , Ġlocation . longitude ) Ċĉĉ ĉ projection ?. map ?. move Camera ( Camera Update Factory . new LatLng Zoom ( camera Location , Ġstart Zoom )) Ċĉ ĉ } Ġelse Ġ{ Ċĉĉ ĉ projection ?. map ?. move Camera ( Camera Update Factory . zoom To ( start Zoom )) Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ private Ġfun Ġupdate Camera () Ġ{ Ċĉ ĉ val Ġlocation Ġ= Ġcurrent Location Ġ?: Ġreturn Ċĉ ĉ if Ġ(! anim ating Camera Ġ|| Ġzoom ing Camera ) Ġ{ Ċĉĉ ĉ // Ġif Ġthe Ġcamera Ġis Ġidle Ġor Ġwe Ġare Ġzoom ing Ġthe Ġcamera Ġalready Ċĉĉ ĉ val Ġcamera Location Ġ= ĠLat Lng ( location . latitude , Ġlocation . longitude ) Ċĉĉ ĉ projection ?. map ?. stop Animation () Ċĉĉ ĉ projection ?. map ?. animate Camera ( Camera Update Factory . new LatLng Zoom ( camera Location , Ġcurrent Zoom ), Ġanimation Finished Callback ) Ċĉĉ ĉ anim ating Camera Ġ= Ġtrue Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ override Ġfun Ġsearch Locations ( query : ĠString ) Ġ{ Ċĉ ĉ val Ġlat lng Bounds Ġ= Ġprojection ?. map ?. projection ?. visible Region ?. lat Lng Bounds Ġ?: Ġreturn Ċĉ ĉ search Locations ( query , Ġlat lng Bounds ) Ċ ĉ } ĊĊ ĉ private Ġfun Ġgenerate Search Session () Ġ{ Ċĉ ĉ // Ġthe Ġsearch Ġsession Ġonly Ġshould Ġlive Ġfor Ġ 3 Ġminutes Ċĉ ĉ if Ġ( search Session Start Ġ+ ĠSEARCH _ SESSION _ TTL Ġ< ĠSystem . currentTimeMillis ()) Ġ{ Ċĉĉ ĉ search Session Ġ= Ġnull Ċĉ ĉ } Ċĉ ĉ if Ġ( search Session Ġ== Ġnull ) Ġ{ Ċĉĉ ĉ search Session Ġ= ĠAuto complete Session Token . newInstance () Ċĉĉ ĉ search Session Start Ġ= ĠSystem . currentTimeMillis () Ċĉĉ ĉ search Session Cons umed Ġ= Ġfalse Ċĉ ĉ } Ċ ĉ } Ċ ĉ fun Ġsearch Locations ( query : ĠString , Ġlocation : ĠLat Lng Bounds ) Ġ{ Ċĉ ĉ generate Search Session () ĊĊĉ ĉ val Ġbounds Ġ= ĠRect angular Bounds . newInstance ( location ) Ċĉ ĉ Log . i ( TAG , Ġ" Starting ĠPlace Ġsearch Ġfor Ġ$ query Ġnear Ġ$ bounds ") Ċĉ ĉ val Ġautocomplete Request Ġ= ĠFind Autocomplete Pred i ctions Request . builder () Ċĉĉĉ ĉ . setLocation Bias ( bounds ) Ċĉĉĉ ĉ . set Session Token ( search Session ) Ċĉĉĉ ĉ . set Query ( query ) Ċĉĉĉ ĉ . build () Ċĉ ĉ places Client . find Autocomplete Pred i ctions ( autocomplete Request ). add On Success Listener Ġ{ Ġresult Ġ-> Ċĉĉ ĉ val Ġresults Ġ= Ġresult ?. autocomplete Pred i ctions Ġ?: Ġreturn @ add On Success Listener Ċĉĉ ĉ Log . i ( TAG , Ġ" Received Ġ${ results . size } Ġresults Ġfor Ġquery Ġ$ query ") ĊĊĉĉ ĉ val Ġmap Results Ġ= Ġresults . map Ġ{ Ċĉĉĉ ĉ Map Result ( it . place Id , Ġit . get Primary Text ( null ). toString (), Ġit . get Secondary Text ( null ). toString ()) Ċĉĉ ĉ } Ċĉĉ ĉ results Controller . on SearchResults ( map Results . to Typed Array ()) Ċĉ ĉ }. add On Failure Listener Ġ{ Ċĉĉ ĉ Log . w ( TAG , Ġ" Un successful Ġresult Ġwhen Ġloading Ġresults Ġfor Ġ$ query : Ġ$ it ") Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ override Ġfun Ġresult Information ( result Id : ĠString ) Ġ{ Ċĉ ĉ val Ġrequested Fields Ġ= ĠlistOf ( Place . Field . ID , ĠPlace . Field . NAME , ĠPlace . Field . LAT _ L NG , ĠPlace . Field . ADDRESS ) Ċĉ ĉ val Ġrequest Builder Ġ= ĠFetch Place Request . builder ( result Id , Ġrequested Fields ) Ċĉ ĉ if Ġ(! search Session Cons umed ) Ġ{ Ċĉĉ ĉ request Builder . set Session Token ( search Session ) Ċĉĉ ĉ search Session Cons umed Ġ= Ġtrue Ċĉ ĉ } Ċĉ ĉ val Ġrequest Ġ= Ġrequest Builder . build () ĊĊĉ ĉ places Client . fetch Place ( request ). add On Success Listener Ġ{ Ġresult Ġ-> Ċĉĉ ĉ Log . i ( TAG , Ġ" Received ĠPlace Ġresult Ġfor Ġresult Id Ġ$ result Id : Ġ${ result ?. place }") Ċĉĉ ĉ val Ġplace Ġ= Ġresult ?. place Ġ?: Ġreturn @ add On Success Listener Ċĉĉ ĉ val Ġlat Lng Ġ= Ġplace . lat Lng Ċĉĉ ĉ if Ġ( lat Lng Ġ== Ġnull ) Ġ{ Ċĉĉĉ ĉ Log . w ( TAG , Ġ" Place Ġdoes Ġnot Ġhave Ġa Ġlat lng Ġlocation !") Ċĉĉĉ ĉ return @ add On Success Listener Ċĉĉ ĉ } Ċĉĉ ĉ val Ġmap Result Ġ= ĠMap Result ( result Id , Ġplace . name . toString (), Ġplace . address . toString (), Ċĉĉĉĉ ĉ Lat Long ( lat Lng . latitude , Ġlat Lng . longitude )) Ċĉĉ ĉ results Controller . on Place Result ( map Result ) Ċĉ ĉ }. add On Failure Listener Ġ{ Ċĉĉ ĉ Log . w ( TAG , Ġ" Did Ġnot Ġfind ĠPlace Ġinfo Ġfor ĠPlace ĠID Ġ$ result Id : Ġ$ it ") Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ override Ġfun Ġnavigate To ( dest : ĠLat Long ) Ġ{ Ċĉ ĉ Log . i ( TAG , Ġ" Beginning Ġnavigation Ġto Ġ$ dest ") Ċĉ ĉ // Ġclear Ġout Ġprevious Ġnav Ċĉ ĉ projection ?. map ?. clear () Ċĉ ĉ // Ġshow Ġnew Ġnav Ġdestination Ġicon Ċĉ ĉ current Nav Destination Ġ= Ġdest Ċĉ ĉ draw Navigation () ĊĊĉ ĉ // Ġsearch Ġfor Ġa Ġroute Ċĉ ĉ route Navigation () ĊĊĉ ĉ // Ġstart Ġzoom Ġanimation Ċĉ ĉ animate Navigation () Ċ ĉ } ĊĊ ĉ private Ġfun Ġanimate Navigation () Ġ{ Ċĉ ĉ // Ġshow Ġa Ġcamera Ġanimation Ġto Ġzoom Ġout Ġto Ġthe Ġwhole Ġnavigation Ġroute Ċĉ ĉ val Ġdest Ġ= Ġcurrent Nav Destination Ġ?: Ġreturn Ċĉ ĉ val Ġlast Location Ġ= Ġcurrent Location Ġ?: Ġreturn Ċĉ ĉ anim ating Camera Ġ= Ġtrue Ċĉ ĉ // Ġzoom Ġout Ġto Ġthe Ġfull Ġview Ċĉ ĉ val Ġstart LatLng Ġ= ĠLat Lng ( last Location . latitude , Ġlast Location . longitude ) Ċĉ ĉ val Ġdest LatLng Ġ= ĠLat Lng ( dest . latitude , Ġdest . longitude ) ĊĊĉ ĉ val Ġnavigation Bounds Ġ= ĠLat Lng Bounds . builder () Ċĉĉĉ ĉ . include ( start LatLng ) Ċĉĉĉ ĉ . include ( dest LatLng ) Ċĉĉĉ ĉ . build () Ċĉ ĉ val Ġcurrent Visible Region Ġ= Ġprojection ?. map ?. projection ?. visible Region ?. lat Lng Bounds Ċĉ ĉ if Ġ( current Visible Region Ġ== Ġnull Ġ|| Ġ! current Visible Region . contains ( navigation Bounds . northeast ) Ġ|| Ġ! current Visible Region . contains ( navigation Bounds . sout hw est )) Ġ{ Ċĉĉ ĉ handler . post Delayed ({ Ċĉĉĉ ĉ projection ?. map ?. animate Camera ( Camera Update Factory . new LatLng Bounds ( navigation Bounds , ĠNAV IG ATION _ MAP _ START ZO OM _ P ADDING )) Ċĉĉ ĉ }, Ġ 1 0 0 ) Ċĉ ĉ } ĊĊĉ ĉ // Ġthen Ġzoom Ġback Ġin Ġto Ġthe Ġuser 's Ġchosen Ġzoom Ċĉ ĉ handler . post Delayed ({ Ċĉĉ ĉ projection ?. map ?. animate Camera ( Camera Update Factory . new LatLng Zoom ( start LatLng , Ġcurrent Zoom )) Ċĉĉ ĉ anim ating Camera Ġ= Ġfalse Ċĉ ĉ }, ĠNAV IG ATION _ MAP _ START ZO OM _ TIME . to Long ()) Ċ ĉ } ĊĊ ĉ private Ġfun Ġroute Navigation () Ġ{ Ċĉ ĉ // Ġstart Ġa Ġroute Ġsearch Ċĉ ĉ val Ġlast Location Ġ= Ġcurrent Location Ġ?: Ġreturn Ċĉ ĉ val Ġdest Ġ= Ġcurrent Nav Destination Ġ?: Ġreturn Ċĉ ĉ val Ġorigin Ġ= Ġcom . google . maps . model . LatLng ( last Location . latitude , Ġlast Location . longitude ) Ċĉ ĉ val Ġroute Dest Ġ= Ġcom . google . maps . model . LatLng ( dest . latitude , Ġdest . longitude ) ĊĊĉ ĉ val Ġdirections Request Ġ= ĠDirection s Api . new Request ( geo Client ) Ċĉĉĉ ĉ . mode ( Travel Mode . DR IV ING ) Ċĉĉĉ ĉ . origin ( origin ) Ċĉĉĉ ĉ . destination ( route Dest ) Ċĉ ĉ directions Request . set Callback ( object : ĠPending Result . Callback < Directions Result > Ġ{ Ċĉĉ ĉ override Ġfun Ġon Failure ( e : ĠThrowable ?) Ġ{ Ċĉĉĉ ĉ Log . w ( TAG , Ġ" Failed Ġto Ġfind Ġroute ! Ġ$ e ") Ċ // ĉĉĉ ĉ throw Ġe Ġ?: Ġreturn Ċĉĉ ĉ } ĊĊĉĉ ĉ override Ġfun Ġon Result ( result : ĠDirection s Result ?) Ġ{ Ċĉĉĉ ĉ if Ġ( result Ġ== Ġnull Ġ|| Ġresult . routes . isEmpty ()) Ġ{ Ġreturn Ġ} Ċĉĉĉ ĉ Log . i ( TAG , Ġ" Adding Ġroute Ġto Ġmap ") Ċĉĉĉ ĉ // Ġthis Ġneeds Ġto Ġbe Ġon Ġthe Ġmain Ġthread Ċĉĉĉ ĉ val Ġdecoded Path Ġ= Ġresult . routes [ 0 ]. overview Polyline . decode Path () Ċĉĉĉ ĉ val Ġcurrent Nav Route Ġ= Ġdecoded Path . map Ġ{ Ċĉĉĉĉ ĉ // Ġconvert Ġfrom Ġroute ĠLat Lng Ġto Ġmap ĠLat Lng Ċĉĉĉĉ ĉ LatLng ( it . lat , Ġit . lng ) Ċĉĉĉ ĉ } Ċĉĉĉ ĉ this @ G Maps Controller . current Nav Route Ġ= Ġcurrent Nav Route Ċĉĉĉ ĉ draw Navigation () Ċĉĉ ĉ } Ċĉ ĉ }) Ċ ĉ } ĊĊ ĉ private Ġfun Ġdraw Navigation () Ġ{ Ċĉ ĉ // Ġmake Ġsure Ġwe Ġare Ġin Ġthe ĠUI Ġthread , Ġand Ġthen Ġdraw Ġnavigation Ġlines Ġonto Ġit Ċĉ ĉ // Ġbecause Ġroute Ġsearch Ġcomes Ġback Ġon Ġa Ġnetwork Ġthread Ċĉ ĉ val Ġaction Ġ= Ġ{ Ċĉĉ ĉ val Ġmap Ġ= Ġprojection ?. map Ċĉĉ ĉ if Ġ( map Ġ!= Ġnull ) Ġ{ Ċĉĉĉ ĉ map . clear () ĊĊĉĉĉ ĉ // Ġdestination Ġflag Ċĉĉĉ ĉ val Ġdest Ġ= Ġcurrent Nav Destination Ċĉĉĉ ĉ if Ġ( dest Ġ!= Ġnull ) Ġ{ Ċĉĉĉĉ ĉ val Ġdest LatLng Ġ= ĠLat Lng ( dest . latitude , Ġdest . longitude ) Ċĉĉĉĉ ĉ val Ġmarker Ġ= ĠMarker Options () Ċĉĉĉĉĉĉ ĉ . position ( dest LatLng ) Ċĉĉĉĉĉĉ ĉ . icon ( Bitmap Descriptor Factory . default Marker ( Bitmap Descriptor Factory . H UE _ RED )) Ċĉĉĉĉĉĉ ĉ . visible ( true ) Ċĉĉĉĉ ĉ map . add Marker ( marker ) Ċĉĉĉ ĉ } ĊĊĉĉĉ ĉ // Ġrouting Ċĉĉĉ ĉ val Ġcurrent Nav Route Ġ= Ġthis . current Nav Route Ċĉĉĉ ĉ if Ġ( current Nav Route Ġ!= Ġnull ) Ġ{ Ċĉĉĉĉ ĉ map . add Polyline ( Polyline Options (). color ( context . getColor ( R . color . map Route Line )). addAll ( current Nav Route )) Ċĉĉĉ ĉ } Ċĉĉ ĉ } Ċĉ ĉ } Ċĉ ĉ if Ġ( Looper . my Looper () Ġ!= Ġhandler . lo oper ) Ġ{ Ċĉĉ ĉ handler . post ( action ) Ċĉ ĉ } Ġelse Ġ{ Ċĉĉ ĉ action () Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ override Ġfun Ġstop Navigation () Ġ{ Ċĉ ĉ // Ġclear Ġout Ġprevious Ġnav Ċĉ ĉ current Nav Destination Ġ= Ġnull Ċĉ ĉ current Nav Route Ġ= Ġnull Ċĉ ĉ draw Navigation () Ċ ĉ } Ċ }