package Ġio . homeassistant . comp anion . android . location Ċ Ċ import Ġandroid . annotation . Suppress Lint Ċ import Ġandroid . app . Notification Ċ import Ġandroid . app . Notification Channel Ċ import Ġandroid . app . Notification Manager Ċ import Ġandroid . app . Pending Intent Ċ import Ġandroid . app . Service Ċ import Ġandroid . content . Context Ċ import Ġandroid . content . Intent Ċ import Ġandroid . graphics . Color Ċ import Ġandroid . location . Location Ċ import Ġandroid . os . Build Ċ import Ġandroid . os . IB inder Ċ import Ġandroid . util . Log Ċ import Ġandroidx . core . app . Notification Compat Ċ import Ġandroidx . core . app . Notification Manager Compat Ċ import Ġcom . google . android . gms . location . F used Location Provider Client Ċ import Ġcom . google . android . gms . location . Location Request Ċ import Ġcom . google . android . gms . location . Location Services Ċ import Ġio . homeassistant . comp anion . android . R Ċ import Ġio . homeassistant . comp anion . android . sensors . Location Sensor Manager Ċ import Ġio . homeassistant . comp anion . android . util . Foreground Service Launcher Ċ import Ġkotlin . math . abs Ċ import Ġkotlin . math . round ToInt Ċ Ċ class ĠHigh Accuracy Location Service Ġ: ĠService () Ġ{ ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġinternal Ġconst Ġval ĠTAG Ġ= Ġ" High Acc Loc Service " ĊĊĠĠĠĠĠĠĠ Ġprivate Ġlateinit Ġvar Ġnotification Builder : ĠNotification Compat . Builder ĊĠĠĠĠĠĠĠ Ġprivate Ġlateinit Ġvar Ġnotification : ĠNotification ĊĠĠĠĠĠĠĠ Ġprivate Ġlateinit Ġvar Ġnotification Manager Compat : ĠNotification Manager Compat ĊĠĠĠĠĠĠĠ Ġprivate Ġvar Ġnotification Id : ĠInt Ġ= Ġ 0 ĊĊĠĠĠĠĠĠĠ Ġprivate Ġval ĠLA UNCH ER Ġ= ĠFore ground Service Launcher ( High Accuracy Location Service :: class . java ) ĊĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠDEFAULT _ UPDATE _ INTERVAL _ SECONDS Ġ= Ġ 5 ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠHIGH _ AC CUR ACY _ LOCATION _ NOTIFICATION _ ID Ġ= Ġ" High Accuracy Location Notification " ĊĊĠĠĠĠĠĠĠ Ġ@ Synchron ized ĊĠĠĠĠĠĠĠ Ġfun Ġstart Service ( context : ĠContext , Ġinterval InSeconds : ĠInt ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" Try Ġstarting Ġhigh Ġaccuracy Ġlocation Ġservice Ġ( Interval : Ġ${ interval InSeconds } s ) ...") ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLA UNCH ER . start Service ( context ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġput Extra (" interval InSeconds ", Ġinterval InSeconds ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ@ Synchron ized ĊĠĠĠĠĠĠĠ Ġfun Ġstop Service ( context : ĠContext ) Ġ{ ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" Try Ġstopping Ġhigh Ġaccuracy Ġlocation Ġservice ...") ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLA UNCH ER . stop Service ( context ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfun Ġrestart Service ( context : ĠContext , Ġinterval InSeconds : ĠInt ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" Try Ġrestart ing Ġhigh Ġaccuracy Ġlocation Ġservice Ġ( Interval : Ġ${ interval InSeconds } s ) ...") ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLA UNCH ER . restart Service ( context ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġput Extra (" interval InSeconds ", Ġinterval InSeconds ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfun Ġupdate Notification Address ( context : ĠContext , Ġlocation : ĠLocation , Ġgeo coded Address : ĠString Ġ= Ġ"") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġlocation Readable Ġ= Ġgeo coded Address ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( location Readable . isNull OrEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlocation Readable Ġ= Ġget Formatted Location In Degree ( location . latitude , Ġlocation . longitude ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlocation Readable Ġ= Ġ"$ location Readable Ġ(~ ${ location . accuracy } m )" ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġupdate Notification Content Text ( context , Ġlocation Readable ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġget Formatted Location In Degree ( latitude : ĠDouble , Ġlongitude : ĠDouble ): ĠString Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġlat Seconds Ġ= Ġ( latitude Ġ* Ġ 3 6 0 0 ). round ToInt () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġlat Degrees Ġ= Ġlat Seconds Ġ/ Ġ 3 6 0 0 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlat Seconds Ġ= Ġabs ( lat Seconds Ġ% Ġ 3 6 0 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġlat Minutes Ġ= Ġlat Seconds Ġ/ Ġ 6 0 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlat Seconds Ġ% = Ġ 6 0 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġlong Seconds Ġ= Ġ( longitude Ġ* Ġ 3 6 0 0 ). round ToInt () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġlong Degrees Ġ= Ġlong Seconds Ġ/ Ġ 3 6 0 0 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlong Seconds Ġ= Ġabs ( long Seconds Ġ% Ġ 3 6 0 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġlong Minutes Ġ= Ġlong Seconds Ġ/ Ġ 6 0 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlong Seconds Ġ% = Ġ 6 0 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġlat Degree Ġ= Ġif Ġ( lat Degrees Ġ>= Ġ 0 ) Ġ" N " Ġelse Ġ" S " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġlon Degrees Ġ= Ġif Ġ( long Degrees Ġ>= Ġ 0 ) Ġ" E " Ġelse Ġ" W " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġabs ( lat Degrees ). toString () Ġ+ Ġ" Â° " Ġ+ Ġlat Minutes Ġ+ Ġ"'" Ġ+ Ġlat Seconds Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"\"" Ġ+ Ġlat Degree Ġ+ Ġ" Ġ" Ġ+ Ġabs ( long Degrees ) Ġ+ Ġ" Â° " Ġ+ Ġlong Minutes Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"'" Ġ+ Ġlong Seconds Ġ+ Ġ"\"" Ġ+ Ġlon Degrees ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : Ġjava . lang . Exception ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"" Ġ+ ĠString . format ("% 8 . 5 f ", Ġlatitude ) Ġ+ Ġ" Ġ Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠString . format ("% 8 . 5 f ", Ġlongitude ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġupdate Notification Content Text ( context : ĠContext , Ġtext : ĠString ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( LA UNCH ER . isRunning ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnotification Manager Ġ= ĠNotification Manager Compat . from ( context ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnotification Id Ġ= ĠHIGH _ AC CUR ACY _ LOCATION _ NOTIFICATION _ ID . hashCode () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnotification Builder ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. setContent Text ( text ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. setStyle ( Notification Compat . Big TextStyle (). big Text ( text )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnotification Manager . notify ( notification Id , Ġnotification Builder . build ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġcreate Notification Builder ( context : ĠContext ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġchannel ID Ġ= Ġ" High Ġaccuracy Ġlocation " ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( Build . VERSION . SDK _ INT Ġ>= ĠBuild . VERSION _ CODES . O ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġchannel Ġ= ĠNotification Channel ( channel ID , Ġcontext . getString ( R . string . high _ accuracy _ mode _ channel _ name ), ĠNotification Manager . IMPORT ANCE _ DEFAULT ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnotification Manager Compat . create Notification Channel ( channel ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdisable Intent Ġ= ĠIntent ( context , ĠHigh Accuracy Location Receiver :: class . java ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdisable Intent . apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġaction Ġ= ĠHigh Accuracy Location Receiver . HIGH _ AC CUR ACY _ LOCATION _ DISABLE ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdisable Pending Intent Ġ= ĠPending Intent . get Broadcast ( context , Ġ 0 , Ġdisable Intent , ĠPending Intent . FLAG _ MUT ABLE ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġnotification Builder Ġ= ĠNotification Compat . Builder ( context , Ġchannel ID ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. set Small Icon ( R . drawable . ic _ stat _ ic _ notification ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. setColor ( Color . GRAY ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. set O ngo ing ( true ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. set Only Alert Once ( true ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. setContent Title ( context . getString ( R . string . high _ accuracy _ mode _ notification _ title )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. setVisibility ( Notification Compat . VIS IBILITY _ SECRET ) Ġ// ĠThis Ġhide s Ġthe Ġnotification Ġfrom Ġlock Ġscreen ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. set Category ( Notification . CATEGORY _ SERVICE ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. addAction ( 0 , Ġcontext . getString ( R . string . disable ), Ġdisable Pending Intent ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġvar Ġf used Location Provider Client : ĠF used Location Provider Client ? Ġ= Ġnull ĊĊĠĠĠ Ġoverride Ġfun ĠonCreate () Ġ{ ĊĠĠĠĠĠĠĠ Ġsuper . onCreate () ĊĊĠĠĠĠĠĠĠ Ġnotification Id Ġ= ĠHIGH _ AC CUR ACY _ LOCATION _ NOTIFICATION _ ID . hashCode () ĊĊĠĠĠĠĠĠĠ Ġnotification Manager Compat Ġ= ĠNotification Manager Compat . from ( this ) ĊĊĠĠĠĠĠĠĠ Ġ// ĠCreate Ġnotification ĊĠĠĠĠĠĠĠ Ġcreate Notification Builder ( this ) ĊĠĠĠĠĠĠĠ Ġnotification Ġ= Ġnotification Builder . build () ĊĊĠĠĠĠĠĠĠ ĠLA UNCH ER . on Service Created ( this , Ġnotification Id , Ġnotification ) ĊĊĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" High Ġaccuracy Ġlocation Ġservice Ġcreated Ġ-> ĠonCreate ") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun ĠonStart Command ( intent : ĠIntent ?, Ġflags : ĠInt , Ġstart Id : ĠInt ): ĠInt Ġ{ ĊĠĠĠĠĠĠĠ Ġsuper . onStart Command ( intent , Ġflags , Ġstart Id ) ĊĊĠĠĠĠĠĠĠ Ġval Ġinterval InSeconds Ġ= Ġintent ?. getInt Extra (" interval InSeconds ", ĠDEFAULT _ UPDATE _ INTERVAL _ SECONDS ) Ġ?: ĠDEFAULT _ UPDATE _ INTERVAL _ SECONDS ĊĠĠĠĠĠĠĠ Ġrequest Location Updates ( interval InSeconds ) ĊĊĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" High Ġaccuracy Ġlocation Ġservice Ġ( Interval : Ġ${ interval InSeconds } s ) Ġstarted Ġ-> ĠonStart Command ") ĊĠĠĠĠĠĠĠ Ġreturn ĠSTART _ NOT _ STICK Y ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġon Destroy () Ġ{ ĊĠĠĠĠĠĠĠ Ġsuper . on Destroy () ĊĊĠĠĠĠĠĠĠ Ġf used Location Provider Client ?. remove Location Updates ( getLocation Update Intent ()) ĊĊĠĠĠĠĠĠĠ ĠLA UNCH ER . on Service Destroy ( this ) ĊĊĠĠĠĠĠĠĠ Ġ// ĠRemove Ġnotification Ġagain . ĠSometimes Ġstop Foreground ( true ) Ġis Ġnot Ġenough . ĠJust Ġto Ġbe Ġsure ĊĠĠĠĠĠĠĠ Ġnotification Manager Compat . cancel ( notification Id ) ĊĊĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" High Ġaccuracy Ġlocation Ġservice Ġstopped Ġ-> Ġon Destroy ") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġon Bind ( intent : ĠIntent ?): ĠI Binder ? Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġnull ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġget Location Update Intent (): ĠPending Intent Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġintent Ġ= ĠIntent ( this , ĠLocation Sensor Manager :: class . java ) ĊĠĠĠĠĠĠĠ Ġintent . action Ġ= ĠLocation Sensor Manager . ACTION _ PROCESS _ LOCATION ĊĠĠĠĠĠĠĠ Ġreturn ĠPending Intent . get Broadcast ( this , Ġ 0 , Ġintent , ĠPending Intent . FLAG _ UPDATE _ CURRENT Ġor ĠPending Intent . FLAG _ MUT ABLE ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Suppress Lint (" Missing Permission ") ĊĠĠĠ Ġprivate Ġfun Ġrequest Location Updates ( interval InSeconds : ĠInt ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġrequest Ġ= ĠLocation Request () ĊĊĠĠĠĠĠĠĠ Ġval Ġinterval In MS Ġ= Ġ( interval InSeconds Ġ* Ġ 1 0 0 0 ). to Long () ĊĠĠĠĠĠĠĠ Ġrequest . interval Ġ= Ġinterval In MS ĊĠĠĠĠĠĠĠ Ġrequest . fast est Interval Ġ= Ġinterval In MS Ġ/ Ġ 2 ĊĠĠĠĠĠĠĠ Ġrequest . priority Ġ= ĠLocation Request . PRIORITY _ HIGH _ AC CUR ACY ĊĊĠĠĠĠĠĠĠ Ġf used Location Provider Client Ġ= ĠLocation Services . getF used Location Provider Client ( this ) ĊĠĠĠĠĠĠĠ Ġf used Location Provider Client ?. request Location Updates ( request , Ġget Location Update Intent ()) ĊĠĠĠ Ġ} Ċ } Ċ