package Ġcom . github . ku ya 3 2 . ge oc aching android coding exercise . ge oc aching map čĊč Ċ import Ġandroid . Manifest č Ċ import Ġandroid . content . Context č Ċ import Ġandroid . content . pm . PackageManager č Ċ import Ġandroid . os . Looper č Ċ import Ġandroid . util . Log č Ċ import Ġandroidx . compose . runtime . Mutable State č Ċ import Ġandroidx . compose . runtime . mutable State Of č Ċ import Ġandroidx . compose . ui . graphics . Color č Ċ import Ġandroidx . core . app . Activity Compat č Ċ import Ġandroidx . core . content . Context Compat č Ċ import Ġandroidx . lifecycle . ViewModel č Ċ import Ġcom . android . vol ley . Request č Ċ import Ġcom . android . vol ley . Response č Ċ import Ġcom . android . vol ley . toolbox . String Request č Ċ import Ġcom . android . vol ley . toolbox . Vol ley č Ċ import Ġcom . google . android . gms . location .* č Ċ import Ġcom . google . android . libraries . maps . Google Map č Ċ import Ġcom . google . android . libraries . maps . model . Polyline Options č Ċ import Ġcom . google . maps . android . Poly Util č Ċ import Ġcom . google . maps . model . LatLng č Ċ import Ġorg . json . JSONObject č Ċ import Ġkotlin . coroutines . resume č Ċ import Ġkotlin . coroutines . suspend Coroutine čĊč Ċ /* ĠThere Ġwere Ġmultiple Ġinstances Ġwhere Ġpermissions Ġchecks Ġwere Ġrequired Ġto Ġuse Ġthe Ġlocation Ġfunctionality . ĠOrigin ally ĠI Ġjust Ġused čĊĠĠ Ġa Ġsuppress Ġannotation Ġto Ġavoid Ġhaving Ġto Ġhandle Ġthe Ġerror Ġcase Ġwhere Ġthe Ġuser Ġremoves Ġlocation Ġpermission . ĠThis Ġis Ġa Ġfuture čĊĠĠ Ġimprovement ĠI Ġcould Ġimplement Ġwere ĠI Ġcan Ġhandle Ġthe Ġerror Ġand Ġnotify Ġthe Ġuser Ġwith Ġan Ġerror Ġdialog Ġor Ġsn ack Ġbar Ġand Ġgiven Ġthem Ġthe čĊĠĠ Ġability Ġto Ġgrant Ġpermissions Ġin Ġapplication Ġsettings . Ġ*/ č Ċ class ĠMap View ViewModel Ġ: ĠViewModel () Ġ{ čĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġlocation Callback : ĠLocation Callback čĊčĊĠĠĠ Ġvar Ġcalculated Distance Ġ= Ġmutable State Of ("") čĊčĊĠĠĠ Ġvar Ġlocation Permission Granted Ġ= Ġmutable State Of ( false ) čĊčĊĠĠĠ Ġvar Ġis New Location P ined Ġ= Ġmutable State Of ( false ) čĊčĊĠĠĠ Ġvar Ġis Navigation Requested Ġ= Ġmutable State Of ( false ) čĊčĊĠĠĠ Ġvar Ġis Calculation Requested Ġ= Ġmutable State Of ( false ) čĊčĊĠĠĠ Ġprivate Ġvar Ġ_ user Current Lat Ġ= Ġmutable State Of ( 0 . 0 ) čĊĠĠĠ Ġvar Ġuser Current Lat : ĠMutable State < Double > Ġ= Ġ_ user Current Lat čĊčĊĠĠĠ Ġprivate Ġvar Ġ_ user Current Lng Ġ= Ġmutable State Of ( 0 . 0 ) čĊĠĠĠ Ġvar Ġuser Current Lng : ĠMutable State < Double > Ġ= Ġ_ user Current Lng čĊčĊĠĠĠ Ġprivate Ġvar Ġ_ p ined Lat Ġ= Ġmutable State Of ( 0 . 0 ) čĊĠĠĠ Ġvar Ġp ined Lat : ĠMutable State < Double > Ġ= Ġ_ p ined Lat čĊčĊĠĠĠ Ġprivate Ġvar Ġ_ p ined Lng Ġ= Ġmutable State Of ( 0 . 0 ) čĊĠĠĠ Ġvar Ġp ined Lng : ĠMutable State < Double > Ġ= Ġ_ p ined Lng čĊčĊĠĠĠ Ġprivate Ġfun ĠgetUser Current Coordinates ( lat Lng : ĠLat Lng ) Ġ{ čĊĠĠĠĠĠĠĠ Ġ_ user Current Lat . value Ġ= Ġlat Lng . lat čĊĠĠĠĠĠĠĠ Ġ_ user Current Lng . value Ġ= Ġlat Lng . lng čĊĠĠĠ Ġ} čĊčĊĠĠĠ Ġfun Ġset P ined Location ( lat Lng : ĠLat Lng ) Ġ{ čĊĠĠĠĠĠĠĠ Ġ_ p ined Lat . value Ġ= Ġlat Lng . lat čĊĠĠĠĠĠĠĠ Ġ_ p ined Lng . value Ġ= Ġlat Lng . lng čĊĠĠĠ Ġ} čĊčĊĠĠĠ Ġfun Ġupdated Calculation Request ( request : ĠBoolean ) Ġ{ čĊĠĠĠĠĠĠĠ Ġis Calculation Requested . value Ġ= Ġrequest čĊĠĠĠ Ġ} čĊčĊĠĠĠ Ġfun Ġupdated Navigation Request ( request : ĠBoolean ) Ġ{ čĊĠĠĠĠĠĠĠ Ġis Navigation Requested . value Ġ= Ġrequest čĊĠĠĠ Ġ} čĊčĊĠĠĠ Ġfun Ġupdated P ined Location ( status : ĠBoolean ) Ġ{ čĊĠĠĠĠĠĠĠ Ġis New Location P ined . value Ġ= Ġstatus čĊĠĠĠ Ġ} čĊčĊĠĠĠ Ġprivate Ġfun Ġset Permission Is Granted ( set Granted : ĠBoolean ) Ġ{ čĊĠĠĠĠĠĠĠ Ġlocation Permission Granted . value Ġ= Ġset Granted čĊĠĠĠ Ġ} čĊčĊĠĠĠ Ġfun Ġupdate Calculated Distance ( string : ĠString ) Ġ{ čĊĠĠĠĠĠĠĠ Ġcalculated Distance . value Ġ= Ġstring čĊĠĠĠ Ġ} čĊčĊĠĠĠ Ġ// ĠChecks Ġif Ġthe Ġlocation Ġpermissions Ġwere Ġgranted čĊĠĠĠ Ġfun Ġget Location Permission ( context : ĠContext ) Ġ{ čĊĠĠĠĠĠĠĠ Ġif Ġ( čĊĠĠĠĠĠĠĠĠĠĠĠ ĠContext Compat . check Self Permission ( čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontext . application Context , čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠManifest . permission . ACCESS _ F INE _ LOCATION čĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) Ġ== ĠPackage Manager . PERMISSION _ GRAN TED Ġ&& čĊĠĠĠĠĠĠĠĠĠĠĠ ĠContext Compat . check Self Permission ( čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontext . application Context , čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠManifest . permission . ACCESS _ CO AR SE _ LOCATION čĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) Ġ== ĠPackage Manager . PERMISSION _ GRAN TED čĊĠĠĠĠĠĠĠ Ġ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠ Ġset Permission Is Granted ( true ) čĊĠĠĠĠĠĠĠĠĠĠĠ Ġget Device Location ( context ) čĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠ ĠLog . d (" Location ĠPermission ", Ġ" Location Ġpermission Ġnot Ġgranted ") čĊĠĠĠĠĠĠĠ Ġ} čĊĠĠĠ Ġ} čĊčĊĠĠĠ Ġ// ĠLoc ates Ġthe Ġuser 's Ġcurrent Ġlocation čĊĠĠĠ Ġprivate Ġfun Ġget Device Location ( context : ĠContext ) Ġ{ čĊĠĠĠĠĠĠĠ Ġval Ġf used Location Provider Client Ġ= ĠLocation Services . getF used Location Provider Client ( context ) čĊčĊĠĠĠĠĠĠĠ Ġtry Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠ Ġstart Location Updates ( f used Location Provider Client , Ġcontext ) čĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( location Permission Granted . value ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġlocation Result Ġ= Ġf used Location Provider Client . last Location čĊčĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlocation Result . add On Complete Listener Ġ{ Ġtask Ġ-> čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( task . is Successful ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġlast Known Location Ġ= Ġtask . result čĊčĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( last Known Location Ġ!= Ġnull ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠgetUser Current Coordinates ( čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLat Lng ( last Known Location . latitude , Ġlast Known Location . longitude ) čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLog . d (" User ĠLocation ", Ġ" Current Ġuser Ġlocation Ġis Ġnull ") čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} čĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} čĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠSecurity Exception ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠ ĠLog . d (" Exception ", Ġ" Exception : Ġ${ e . message . toString () }") čĊĠĠĠĠĠĠĠ Ġ} čĊĠĠĠ Ġ} čĊčĊĠĠĠ Ġ// ĠGets Ġupdates Ġof Ġuser Ġlocation Ġand Ġdisplays Ġon Ġmap čĊĠĠĠ Ġprivate Ġfun Ġstart Location Updates ( čĊĠĠĠĠĠĠĠ Ġf used Location Provider Client : ĠF used Location Provider Client , čĊĠĠĠĠĠĠĠ Ġcontext : ĠContext čĊĠĠĠ Ġ) Ġ{ čĊĠĠĠĠĠĠĠ Ġif Ġ( Activity Compat . check Self Permission ( čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontext , čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠManifest . permission . ACCESS _ F INE _ LOCATION čĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) Ġ!= ĠPackage Manager . PERMISSION _ GRAN TED Ġ&& ĠActivity Compat . check Self Permission ( čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontext , čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠManifest . permission . ACCESS _ CO AR SE _ LOCATION čĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) Ġ!= ĠPackage Manager . PERMISSION _ GRAN TED čĊĠĠĠĠĠĠĠ Ġ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn čĊĠĠĠĠĠĠĠ Ġ} čĊčĊĠĠĠĠĠĠĠ Ġval Ġlocation Request Ġ= ĠLocation Request . create (). apply Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠ Ġinterval Ġ= Ġ 1 0 0 0 čĊĠĠĠĠĠĠĠĠĠĠĠ Ġfast est Interval Ġ= Ġ 5 0 0 čĊĠĠĠĠĠĠĠĠĠĠĠ Ġpriority Ġ= ĠLocation Request . PRIORITY _ HIGH _ AC CUR ACY čĊĠĠĠĠĠĠĠ Ġ} čĊčĊĠĠĠĠĠĠĠ Ġlocation Callback Ġ= Ġobject Ġ: ĠLocation Callback () Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġon Location Result ( result : ĠLocation Result ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsuper . on Location Result ( result ) čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresult . locations . let Ġ{ Ġlocations Ġ-> čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( location Ġin Ġlocations ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠgetUser Current Coordinates ( LatLng ( location . latitude , Ġlocation . longitude )) čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} čĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} čĊĠĠĠĠĠĠĠ Ġ} čĊčĊĠĠĠĠĠĠĠ Ġf used Location Provider Client . request Location Updates ( čĊĠĠĠĠĠĠĠĠĠĠĠ Ġlocation Request , čĊĠĠĠĠĠĠĠĠĠĠĠ Ġlocation Callback , čĊĠĠĠĠĠĠĠĠĠĠĠ ĠL ooper . get Main Looper () čĊĠĠĠĠĠĠĠ Ġ) čĊĠĠĠ Ġ} čĊčĊĠĠĠ Ġ/* ĠFunction Ġuses ĠGoogle ĠMaps ĠDirection ĠAPI Ġto Ġmake Ġa Ġrequest Ġand Ġgather Ġdata Ġfrom Ġuser 's Ġcurrent Ġlocation Ġto Ġpinned Ġlocation . čĊĠĠĠĠĠĠ ĠThen Ġgr abs Ġthe Ġfirst Ġroute Ġand Ġsteps Ġin Ġgetting Ġto Ġthe Ġdestination . ĠA Ġpoly line Ġis Ġthen Ġdrawn Ġon Ġthe Ġmap . čĊĠĠĠĠĠĠ ĠLink : Ġhttps :// github . com / law g im ene z / google map sd irection ss ample / blob / main / app / src / main / java / com / li vin ide as / google map sd irection sample / MainActivity . kt */ čĊĠĠĠ Ġfun Ġdirections Request To Polyline ( čĊĠĠĠĠĠĠĠ Ġorigin : ĠLat Lng , čĊĠĠĠĠĠĠĠ Ġdestination : ĠLat Lng , čĊĠĠĠĠĠĠĠ ĠapiKey : ĠString , čĊĠĠĠĠĠĠĠ Ġmap : ĠGoogle Map čĊĠĠĠ Ġ): ĠString Request Ġ{ čĊĠĠĠĠĠĠĠ Ġval Ġpath : ĠMutable List < List < com . google . android . libraries . maps . model . LatLng >> Ġ= ĠArrayList () čĊĠĠĠĠĠĠĠ Ġval Ġurl Direction Ġ= čĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" https :// maps . googleapis . com / maps / api / directions / json ? origin =${ origin }& destination =${ destination }& key =${ apiKey }" čĊĠĠĠĠĠĠĠ Ġval Ġdirection Request Ġ= Ġobject Ġ: čĊĠĠĠĠĠĠĠĠĠĠĠ ĠString Request ( Request . Method . GET , Ġurl Direction , ĠResponse . Listener < String > Ġ{ Ġresponse Ġ-> čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġjson Response Ġ= ĠJSONObject ( response ) čĊčĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ/* ĠT aking Ġthe Ġfirst Ġroute Ġthat Ġthe ĠDirection ĠAPI Ġgives Ġme Ġis Ġsingle Ġroute Ġthat Ġdisplays Ġon Ġthe Ġmap . čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠOne Ġthing ĠI Ġcan Ġdo Ġto Ġimprove Ġthis Ġfunctionality Ġis Ġgather Ġmultiple Ġroutes Ġso Ġthat Ġthis Ġgives čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthe Ġuser Ġothers Ġoptions Ġto Ġtake Ġand Ġget Ġto Ġtheir Ġdestination . Ġ*/ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġroutes Ġ= Ġjson Response . get JSONArray (" routes ") čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġle gs Ġ= Ġroutes . getJSONObject ( 0 ). get JSONArray (" leg s ") čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġsteps Ġ= Ġle gs . getJSONObject ( 0 ). get JSONArray (" steps ") čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( i Ġin Ġ 0 Ġuntil Ġsteps . length ()) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpoints Ġ= čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsteps . getJSONObject ( i ). getJSONObject (" poly line "). getString (" points ") čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpath . add ( Poly Util . decode ( points )) čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( i Ġin Ġ 0 Ġuntil Ġpath . size ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmap . add Polyline ( Polyline Options (). addAll ( path [ i ]). color ( Color . Blue . hashCode ())) čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} čĊčĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ/* ĠCa ught Ġthis Ġone Ġa Ġlittle Ġlate . ĠAnother Ġinstance Ġof Ġimpro per Ġway Ġof Ġhandling Ġerrors . ĠIn Ġthis Ġparticular Ġsituation , čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġthere Ġis Ġan Ġerror Ġwith Ġthe ĠDirection ĠAPI ĠI Ġcould 've Ġused Ġan Ġalert Ġdialog Ġto Ġprompt Ġthe Ġuser Ġabout Ġthe Ġerror . Ġ*/ čĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}, ĠResponse . Error Listener Ġ{ Ġe Ġ-> čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLog . d (" Direction ĠAPI ", Ġe . message . toString ()) čĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}) Ġ{} čĊčĊĠĠĠĠĠĠĠ Ġreturn Ġdirection Request čĊĠĠĠ Ġ} čĊčĊĠĠĠ Ġ/* ĠMakes Ġa Ġrequest Ġto ĠDirection s ĠAPI Ġto Ġgather Ġdata Ġfrom Ġthis Ġparticular Ġroute Ġto Ġbe Ġthen Ġused Ġto Ġcalculate Ġthe čĊĠĠĠĠĠĠ Ġdistance Ġfrom Ġpinned Ġlocation Ġin Ġthe Ġmap Ġcomp osable . čĊĠĠĠĠĠĠ ĠLink : Ġhttps :// stackoverflow . com / questions / 6 0 2 4 6 8 5 2 / can - you - get - the - response - data - from - vol ley - outside - of - the - string request - variable Ġ*/ čĊĠĠĠ Ġsuspend Ġfun ĠgetData ( origin : ĠLat Lng , Ġdestination : ĠLat Lng , ĠapiKey : ĠString , Ġcontext : ĠContext ) Ġ= čĊĠĠĠĠĠĠĠ Ġsuspend Coroutine < String ?> Ġ{ Ġcont Ġ-> čĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġqueue Ġ= ĠVol ley . new Request Queue ( context ) čĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġurl Ġ= čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" https :// maps . googleapis . com / maps / api / directions / json ? origin =${ origin }& destination =${ destination }& key =${ apiKey }" čĊčĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġstring Request Ġ= ĠString Request ( Request . Method . GET , Ġurl , čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ{ Ġresponse Ġ-> čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcont . resume ( response ) čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ}, čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ{ Ġcont . resume ( null ) Ġ}) čĊčĊĠĠĠĠĠĠĠĠĠĠĠ Ġqueue . add ( string Request ) čĊĠĠĠĠĠĠĠ Ġ} č Ċ }