package Ġnet . os mand . telegram Ċ Ċ import Ġandroid . annotation . Suppress Lint Ċ import Ġandroid . content . Context Ċ import Ġandroid . hardware .* Ċ import Ġandroid . location . Location Ċ import Ġandroid . os . Looper Ċ import Ġandroid . util . Log Ċ import Ġcom . google . android . gms . location .* Ċ import Ġnet . os mand . Platform Util Ċ import Ġnet . os mand . data . Lat Lon Ċ import Ġnet . os mand . telegram . utils . Android Utils Ċ import Ġnet . os mand . util . Map Utils Ċ import Ġjava . util .* Ċ import Ġkotlin . math . atan 2 Ċ Ċ class ĠTelegram Location Provider ( private Ġval Ġapp : ĠTelegram Application ) Ġ: ĠSensor EventListener Ġ{ ĊĊ ĉ private Ġvar Ġlast Time GPS Location Fixed : ĠLong Ġ= Ġ 0 ĊĊ ĉ private Ġvar Ġsensor Registered Ġ= Ġfalse Ċ ĉ private Ġval Ġm Gr av s Ġ= ĠFloat Array ( 3 ) Ċ ĉ private Ġval Ġm Geo M ags Ġ= ĠFloat Array ( 3 ) Ċ ĉ private Ġvar Ġprevious Correction Value Ġ= Ġ 3 6 0 f ĊĊ ĉ internal Ġvar Ġavg Val Sin Ġ= Ġ 0 f Ċ ĉ internal Ġvar Ġavg Val Cos Ġ= Ġ 0 f Ċ ĉ internal Ġvar Ġlast Val Sin Ġ= Ġ 0 f Ċ ĉ internal Ġvar Ġlast Val Cos Ġ= Ġ 0 f Ċ ĉ private Ġval Ġprevious Comp ass Values A Ġ= ĠFloat Array ( 5 0 ) Ċ ĉ private Ġval Ġprevious Comp ass Values B Ġ= ĠFloat Array ( 5 0 ) Ċ ĉ private Ġvar Ġprevious Comp ass Ind A Ġ= Ġ 0 Ċ ĉ private Ġvar Ġprevious Comp ass Ind B Ġ= Ġ 0 Ċ ĉ private Ġvar Ġin Update Value Ġ= Ġfalse ĊĊ ĉ @ get : Synchron ized Ċ ĉ var Ġheading : ĠFloat ? Ġ= Ġnull Ċĉ ĉ private Ġset ĊĊ ĉ // ĠCurrent Ġscreen Ġorientation Ċ ĉ private Ġvar Ġcurrent Screen Orientation : ĠInt Ġ= Ġ 0 ĊĊ ĉ var Ġlast Known Location : Ġnet . os mand . Location ? Ġ= Ġnull Ċĉ ĉ private Ġset ĊĊ ĉ private Ġvar Ġf used Location Provider Client : ĠF used Location Provider Client ? Ġ= Ġnull Ċ ĉ private Ġval Ġlocation Request Ġ= ĠLocation Request (). apply Ġ{ Ċĉ ĉ interval Ġ= Ġ 1 0 0 0 Ċĉ ĉ // fast est Interval Ġ= Ġ 5 0 0 Ċĉ ĉ max Wait Time Ġ= Ġ 0 Ċĉ ĉ priority Ġ= ĠLocation Request . PRIORITY _ HIGH _ AC CUR ACY Ċ ĉ } Ċ ĉ private Ġval Ġlocation Callback Ġ= Ġobject Ġ: ĠLocation Callback () Ġ{ Ċĉ ĉ override Ġfun Ġon Location Result ( location Result : ĠLocation Result ?) Ġ{ Ċĉĉ ĉ super . on Location Result ( location Result ) Ċĉĉ ĉ val Ġlast Location Ġ= Ġlocation Result ?. last Location Ċĉĉ ĉ if Ġ( last Location Ġ!= Ġnull ) Ġ{ Ċĉĉĉ ĉ last Time GPS Location Fixed Ġ= Ġlast Location . time Ċĉĉ ĉ } Ċĉĉ ĉ setLocation ( convert Location ( last Location )) Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ private Ġval Ġlocation Listeners Ġ= ĠArrayList < Telegram Location Listener >() Ċ ĉ private Ġval Ġcomp ass Listeners Ġ= ĠArrayList < Telegram Comp ass Listener >() Ċ ĉ private Ġval Ġm Rotation M Ġ= ĠFloat Array ( 9 ) Ċ ĉ private Ġval Ġuse Mag netic Field Sensor Comp ass Ġ= Ġfalse ĊĊ ĉ val Ġlast Known Location Lat Lon : ĠLat Lon ? Ċĉ ĉ get () Ġ= Ġif Ġ( last Known Location Ġ!= Ġnull ) Ġ{ Ċĉĉ ĉ Lat Lon ( last Known Location !!. latitude , Ġlast Known Location !!. longitude ) Ċĉ ĉ } Ġelse Ġ{ Ċĉĉ ĉ null Ċĉ ĉ } ĊĊ ĉ interface ĠTelegram Location Listener Ġ{ Ċĉ ĉ fun Ġupdate Location ( location : Ġnet . os mand . Location ?) Ċ ĉ } ĊĊ ĉ interface ĠTelegram Comp ass Listener Ġ{ Ċĉ ĉ fun Ġupdate Comp ass Value ( value : ĠFloat ) Ċ ĉ } ĊĊ ĉ @ Suppress Lint (" Missing Permission ") Ċ ĉ fun Ġresume All Updates () Ġ{ Ċĉ ĉ if Ġ( Android Utils . is Location Permission Available ( app ) Ġ&& Ġf used Location Provider Client Ġ== Ġnull ) Ġ{ Ċĉĉ ĉ f used Location Provider Client Ġ= ĠLocation Services . getF used Location Provider Client ( app ) Ċĉ ĉ } ĊĊĉ ĉ try Ġ{ Ċĉĉ ĉ f used Location Provider Client ?. request Location Updates ( Ċĉĉĉĉ ĉ location Request , Ġlocation Callback , ĠL ooper . my Looper ()) Ċĉ ĉ } Ġcatch Ġ( unlikely : ĠSecurity Exception ) Ġ{ Ċĉĉ ĉ Log . d ( Platform Util . TAG , Ġ" Lost Ġlocation Ġpermissions . ĠCould n 't Ġrequest Ġupdates . Ġ$ unlikely ") Ċĉ ĉ } ĊĊĉ ĉ register Or Unregister Comp ass Listener ( true ) Ċ ĉ } ĊĊ ĉ fun Ġupdate Screen Orientation ( orientation : ĠInt ) Ġ{ Ċĉ ĉ current Screen Orientation Ġ= Ġorientation Ċ ĉ } ĊĊ ĉ fun Ġadd Location Listener ( listener : ĠTelegram Location Listener ) Ġ{ Ċĉ ĉ if Ġ(! location Listeners . contains ( listener )) Ġ{ Ċĉĉ ĉ location Listeners . add ( listener ) Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ fun Ġremove Location Listener ( listener : ĠTelegram Location Listener ) Ġ{ Ċĉ ĉ location Listeners . remove ( listener ) Ċ ĉ } ĊĊ ĉ fun Ġadd Comp ass Listener ( listener : ĠTelegram Comp ass Listener ) Ġ{ Ċĉ ĉ if Ġ(! compass Listeners . contains ( listener )) Ġ{ Ċĉĉ ĉ compass Listeners . add ( listener ) Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ fun Ġremove Comp ass Listener ( listener : ĠTelegram Comp ass Listener ) Ġ{ Ċĉ ĉ compass Listeners . remove ( listener ) Ċ ĉ } ĊĊ ĉ @ Synchron ized Ċ ĉ fun Ġregister Or Unregister Comp ass Listener ( register : ĠBoolean ) Ġ{ Ċĉ ĉ if Ġ( sensor Registered Ġ&& Ġ! register ) Ġ{ Ċĉĉ ĉ Log . d ( Platform Util . TAG , Ġ" Disable Ġsensor ") Ċĉĉ ĉ ( app . getSystem Service ( Context . SENSOR _ SERVICE ) Ġas ĠSensor Manager ). unregister Listener ( this ) Ċĉĉ ĉ sensor Registered Ġ= Ġfalse Ċĉĉ ĉ heading Ġ= Ġnull Ċĉ ĉ } Ġelse Ġif Ġ(! sensor Registered Ġ&& Ġregister ) Ġ{ Ċĉĉ ĉ Log . d ( Platform Util . TAG , Ġ" Enable Ġsensor ") Ċĉĉ ĉ val Ġsensor Mgr Ġ= Ġapp . getSystem Service ( Context . SENSOR _ SERVICE ) Ġas ĠSensor Manager Ċĉĉ ĉ if Ġ( use Mag netic Field Sensor Comp ass ) Ġ{ Ċĉĉĉ ĉ var Ġs : ĠSensor ? Ġ= Ġsensor Mgr . getDefault Sensor ( Sensor . TYPE _ AC CEL ERO METER ) Ċĉĉĉ ĉ if Ġ( s Ġ== Ġnull Ġ|| Ġ! sensor Mgr . register Listener ( Ċĉĉĉĉĉ ĉ this , Ċĉĉĉĉĉ ĉ s , Ċĉĉĉĉĉ ĉ Sensor Manager . SENSOR _ DELAY _ UI Ċĉĉĉĉ ĉ ) Ċĉĉĉ ĉ ) Ġ{ Ċĉĉĉĉ ĉ Log . e ( Platform Util . TAG , Ġ" Sensor Ġaccel erometer Ġcould Ġnot Ġbe Ġenabled ") Ċĉĉĉ ĉ } Ċĉĉĉ ĉ s Ġ= Ġsensor Mgr . getDefault Sensor ( Sensor . TYPE _ MAG NET IC _ FIELD ) Ċĉĉĉ ĉ if Ġ( s Ġ== Ġnull Ġ|| Ġ! sensor Mgr . register Listener ( Ċĉĉĉĉĉ ĉ this , Ċĉĉĉĉĉ ĉ s , Ċĉĉĉĉĉ ĉ Sensor Manager . SENSOR _ DELAY _ UI Ċĉĉĉĉ ĉ ) Ċĉĉĉ ĉ ) Ġ{ Ċĉĉĉĉ ĉ Log . e ( Platform Util . TAG , Ġ" Sensor Ġmagnetic Ġfield Ġcould Ġnot Ġbe Ġenabled ") Ċĉĉĉ ĉ } Ċĉĉ ĉ } Ġelse Ġ{ Ċĉĉĉ ĉ val Ġs Ġ= Ġsensor Mgr . getDefault Sensor ( Sensor . TYPE _ OR IENTATION ) Ċĉĉĉ ĉ if Ġ( s Ġ== Ġnull Ġ|| Ġ! sensor Mgr . register Listener ( Ċĉĉĉĉĉ ĉ this , Ċĉĉĉĉĉ ĉ s , Ċĉĉĉĉĉ ĉ Sensor Manager . SENSOR _ DELAY _ UI Ċĉĉĉĉ ĉ ) Ċĉĉĉ ĉ ) Ġ{ Ċĉĉĉĉ ĉ Log . e ( Platform Util . TAG , Ġ" Sensor Ġorientation Ġcould Ġnot Ġbe Ġenabled ") Ċĉĉĉ ĉ } Ċĉĉ ĉ } Ċĉĉ ĉ sensor Registered Ġ= Ġtrue Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ override Ġfun Ġon Accuracy Changed ( sensor : ĠSensor , Ġaccuracy : ĠInt ) Ġ{} ĊĊ ĉ override Ġfun Ġon Sensor Changed ( event : ĠSensor Event ) Ġ{ Ċĉ ĉ // ĠAtt ention Ġ: Ġsensor Ġproduces Ġa Ġlot Ġof Ġevents Ġ& Ġcan Ġhang Ġthe Ġsystem Ċĉ ĉ if Ġ( in Update Value ) Ġ{ Ċĉĉ ĉ return Ċĉ ĉ } Ċĉ ĉ synchronized ( this ) Ġ{ Ċĉĉ ĉ if Ġ(! sensor Registered ) Ġ{ Ċĉĉĉ ĉ return Ċĉĉ ĉ } Ċĉĉ ĉ in Update Value Ġ= Ġtrue Ċĉĉ ĉ try Ġ{ Ċĉĉĉ ĉ var Ġ` val ` Ġ= Ġ 0 f Ċĉĉĉ ĉ when Ġ( event . sensor . type ) Ġ{ Ċĉĉĉĉ ĉ Sensor . TYPE _ AC CEL ERO METER Ġ-> ĠSystem . arraycopy ( event . values , Ġ 0 , Ġm Gr av s , Ġ 0 , Ġ 3 ) Ċĉĉĉĉ ĉ Sensor . TYPE _ MAG NET IC _ FIELD Ġ-> ĠSystem . arraycopy ( event . values , Ġ 0 , Ġm Geo M ags , Ġ 0 , Ġ 3 ) Ċĉĉĉĉ ĉ Sensor . TYPE _ OR IENTATION Ġ-> Ġ` val ` Ġ= Ġevent . values [ 0 ] Ċĉĉĉĉ ĉ else Ġ-> Ġreturn Ċĉĉĉ ĉ } Ċĉĉĉ ĉ if Ġ( use Mag netic Field Sensor Comp ass ) Ġ{ Ċĉĉĉĉ ĉ if Ġ( m Gr av s Ġ!= Ġnull Ġ&& Ġm Geo M ags Ġ!= Ġnull ) Ġ{ Ċĉĉĉĉĉ ĉ val Ġsuccess Ġ= Ċĉĉĉĉĉĉ ĉ Sensor Manager . get Rotation Matrix ( m Rotation M , Ġnull , Ġm Gr av s , Ġm Geo M ags ) Ċĉĉĉĉĉ ĉ if Ġ(! success ) Ġ{ Ċĉĉĉĉĉĉ ĉ return Ċĉĉĉĉĉ ĉ } Ċĉĉĉĉĉ ĉ val Ġorientation Ġ= ĠSensor Manager . get Orientation ( m Rotation M , ĠFloat Array ( 3 )) Ċĉĉĉĉĉ ĉ ` val ` Ġ= ĠMath . to Degrees ( orientation [ 0 ]. toDouble ()). toFloat () Ċĉĉĉĉ ĉ } Ġelse Ġ{ Ċĉĉĉĉĉ ĉ return Ċĉĉĉĉ ĉ } Ċĉĉĉ ĉ } Ċĉĉĉ ĉ ` val ` Ġ= Ġcalc Screen Orientation Correction (` val `) Ċĉĉĉ ĉ ` val ` Ġ= Ġcalc Geo Mag netic Correction (` val `) ĊĊĉĉĉ ĉ val Ġval Rad Ġ= Ġ(` val ` Ġ/ Ġ 1 8 0 f Ġ* ĠMath . PI ). toFloat () Ċĉĉĉ ĉ last Val Sin Ġ= ĠMath . sin ( val Rad . toDouble ()). toFloat () Ċĉĉĉ ĉ last Val Cos Ġ= ĠMath . cos ( val Rad . toDouble ()). toFloat () ĊĊĉĉĉ ĉ avg Val Sin Ġ= Ġlast Val Sin Ċĉĉĉ ĉ avg Val Cos Ġ= Ġlast Val Cos ĊĊĉĉĉ ĉ update Comp ass Val () Ċĉĉ ĉ } Ġfinally Ġ{ Ċĉĉĉ ĉ in Update Value Ġ= Ġfalse Ċĉĉ ĉ } Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ private Ġfun Ġcalc Geo Mag netic Correction ( value : ĠFloat ): ĠFloat Ġ{ Ċĉ ĉ var Ġres Ġ= Ġvalue Ċĉ ĉ if Ġ( previous Correction Value Ġ== Ġ 3 6 0 f Ġ&& Ġlast Known Location Ġ!= Ġnull ) Ġ{ Ċĉĉ ĉ val Ġl Ġ= Ġlast Known Location Ċĉĉ ĉ val Ġgf Ġ= ĠGe om ag netic Field ( Ċĉĉĉ ĉ l !!. latitude . toFloat (), Ġl . longitude . toFloat (), Ġl . altitude . toFloat (), Ċĉĉĉ ĉ System . currentTimeMillis () Ċĉĉ ĉ ) Ċĉĉ ĉ previous Correction Value Ġ= Ġgf . decl ination Ċĉ ĉ } Ċĉ ĉ if Ġ( previous Correction Value Ġ!= Ġ 3 6 0 f ) Ġ{ Ċĉĉ ĉ res Ġ+= Ġprevious Correction Value Ċĉ ĉ } Ċĉ ĉ return Ġres Ċ ĉ } ĊĊ ĉ private Ġfun Ġcalc Screen Orientation Correction ( value : ĠFloat ): ĠFloat Ġ{ Ċĉ ĉ var Ġres Ġ= Ġvalue Ċĉ ĉ when Ġ( current Screen Orientation ) Ġ{ Ċĉĉĉ 1 Ġ-> Ġres Ġ+= Ġ 9 0 f Ċĉĉĉ 2 Ġ-> Ġres Ġ+= Ġ 1 8 0 f Ċĉĉĉ 3 Ġ-> Ġres Ġ-= Ġ 9 0 f Ċĉ ĉ } Ċĉ ĉ return Ġres Ċ ĉ } ĊĊ ĉ private Ġfun Ġfilter Comp ass Value () Ġ{ Ċĉ ĉ if Ġ( heading Ġ== Ġnull Ġ&& Ġprevious Comp ass Ind A Ġ== Ġ 0 ) Ġ{ Ċĉĉ ĉ Arrays . fill ( previous Comp ass Values A , Ġlast Val Sin ) Ċĉĉ ĉ Arrays . fill ( previous Comp ass Values B , Ġlast Val Cos ) Ċĉĉ ĉ avg Val Sin Ġ= Ġlast Val Sin Ċĉĉ ĉ avg Val Cos Ġ= Ġlast Val Cos Ċĉ ĉ } Ġelse Ġ{ Ċĉĉ ĉ val Ġl Ġ= Ġprevious Comp ass Values A . size Ċĉĉ ĉ previous Comp ass Ind A Ġ= Ġ( previous Comp ass Ind A Ġ+ Ġ 1 ) Ġ% Ġl Ċĉĉ ĉ previous Comp ass Ind B Ġ= Ġ( previous Comp ass Ind B Ġ+ Ġ 1 ) Ġ% Ġl Ċĉĉ ĉ // Ġupdate Ġaverage Ċĉĉ ĉ avg Val Sin Ġ+= Ġ(- previous Comp ass Values A [ previous Comp ass Ind A ] Ġ+ Ġlast Val Sin ) Ġ/ Ġl Ċĉĉ ĉ previous Comp ass Values A [ previous Comp ass Ind A ] Ġ= Ġlast Val Sin Ċĉĉ ĉ avg Val Cos Ġ+= Ġ(- previous Comp ass Values B [ previous Comp ass Ind B ] Ġ+ Ġlast Val Cos ) Ġ/ Ġl Ċĉĉ ĉ previous Comp ass Values B [ previous Comp ass Ind B ] Ġ= Ġlast Val Cos Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ private Ġfun Ġupdate Comp ass Val () Ġ{ Ċĉ ĉ heading Ġ= Ġget Angle ( avg Val Sin , Ġavg Val Cos ) Ċĉ ĉ for Ġ( c Ġin Ġcomp ass Listeners ) Ġ{ Ċĉĉ ĉ c . update Comp ass Value ( heading !! ) Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ private Ġfun Ġget Angle ( sin A : ĠFloat , Ġcos A : ĠFloat ) Ġ= ĠMap Utils . un ify Rotation To 3 6 0 ( Ċĉ ĉ ( atan 2 ( sin A . toDouble (), Ġcos A . toDouble ()) Ġ* Ġ 1 8 0 Ġ/ ĠMath . PI ). toFloat () Ċ ĉ ) ĊĊ ĉ private Ġfun Ġupdate Location ( loc : Ġnet . os mand . Location ?) Ġ{ Ċĉ ĉ for Ġ( l Ġin Ġlocation Listeners ) Ġ{ Ċĉĉ ĉ l . update Location ( loc ) Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ private Ġfun Ġstop Location Requests () Ġ{ Ċĉ ĉ try Ġ{ Ċĉĉ ĉ f used Location Provider Client ?. remove Location Updates ( location Callback ) Ċĉ ĉ } Ġcatch Ġ( unlikely : ĠSecurity Exception ) Ġ{ Ċĉĉ ĉ Log . d ( Platform Util . TAG , Ġ" Lost Ġlocation Ġpermissions . ĠCould n 't Ġremove Ġupdates . Ġ$ unlikely ") Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ fun Ġpause All Updates () Ġ{ Ċĉ ĉ stop Location Requests () Ċĉ ĉ register Or Unregister Comp ass Listener ( false ) Ċ ĉ } ĊĊ ĉ private Ġfun Ġset Location ( location : Ġnet . os mand . Location ?) Ġ{ Ċĉ ĉ this . last Known Location Ġ= Ġlocation Ċĉ ĉ update Location ( this . last Known Location ) Ċ ĉ } ĊĊ ĉ fun Ġcheck If Last Known Location IsValid () Ġ{ Ċĉ ĉ val Ġloc Ġ= Ġlast Known Location Ċĉ ĉ if Ġ( loc Ġ!= Ġnull Ġ&& ĠSystem . currentTimeMillis () Ġ- Ġloc . time Ġ> ĠINTER VAL _ TO _ CLEAR _ SET _ LOCATION ) Ġ{ Ċĉĉ ĉ setLocation ( null ) Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ comp anion Ġobject Ġ{ ĊĊĉ ĉ private Ġconst Ġval ĠINTER VAL _ TO _ CLEAR _ SET _ LOCATION Ġ= Ġ 3 0 Ġ* Ġ 1 0 0 0 ĊĊĉ ĉ fun Ġconvert Location ( l : ĠLocation ?): Ġnet . os mand . Location ? Ġ{ Ċĉĉ ĉ if Ġ( l Ġ== Ġnull ) Ġ{ Ċĉĉĉ ĉ return Ġnull Ċĉĉ ĉ } Ċĉĉ ĉ val Ġr Ġ= Ġnet . os mand . Location ( l . provider ) Ċĉĉ ĉ r . latitude Ġ= Ġl . latitude Ċĉĉ ĉ r . longitude Ġ= Ġl . longitude Ċĉĉ ĉ r . time Ġ= Ġl . time Ċĉĉ ĉ if Ġ( l . has Accuracy ()) Ġ{ Ċĉĉĉ ĉ r . accuracy Ġ= Ġl . accuracy Ċĉĉ ĉ } Ċĉĉ ĉ if Ġ( l . has Speed ()) Ġ{ Ċĉĉĉ ĉ r . speed Ġ= Ġl . speed Ċĉĉ ĉ } Ċĉĉ ĉ if Ġ( l . has Alt itude ()) Ġ{ Ċĉĉĉ ĉ r . altitude Ġ= Ġl . altitude Ċĉĉ ĉ } Ċĉĉ ĉ if Ġ( l . has Be aring ()) Ġ{ Ċĉĉĉ ĉ r . be aring Ġ= Ġl . be aring Ċĉĉ ĉ } Ċĉĉ ĉ return Ġr Ċĉ ĉ } Ċ ĉ } Ċ } Ċ