/* Ċ Ġ* ĠCopyright Ġ 2 0 1 9 - 2 0 2 1 ĠGoogle ĠLLC , ĠSe an ĠBar be au Ċ Ġ* Ċ Ġ* ĠLicensed Ġunder Ġthe ĠApache ĠLicense , ĠVersion Ġ 2 . 0 Ġ( the Ġ" License "); Ċ Ġ* Ġyou Ġmay Ġnot Ġuse Ġthis Ġfile Ġexcept Ġin Ġcompliance Ġwith Ġthe ĠLicense . Ċ Ġ* ĠYou Ġmay Ġobtain Ġa Ġcopy Ġof Ġthe ĠLicense Ġat Ċ Ġ* Ċ Ġ* ĠĠĠĠ Ġhttps :// www . apache . org / licenses / LICENSE - 2 . 0 Ċ Ġ* Ċ Ġ* ĠUnless Ġrequired Ġby Ġapplicable Ġlaw Ġor Ġagreed Ġto Ġin Ġwriting , Ġsoftware Ċ Ġ* Ġdistributed Ġunder Ġthe ĠLicense Ġis Ġdistributed Ġon Ġan Ġ" AS ĠIS " ĠBASIS , Ċ Ġ* ĠWITHOUT ĠWARRANTIES ĠOR ĠCONDITIONS ĠOF ĠANY ĠKIND , Ġeither Ġexpress Ġor Ġimplied . Ċ Ġ* ĠSee Ġthe ĠLicense Ġfor Ġthe Ġspecific Ġlanguage Ġgoverning Ġpermissions Ġand Ċ Ġ* Ġlimitations Ġunder Ġthe ĠLicense . Ċ Ġ*/ Ċ package Ġcom . android . gp st est . data Ċ Ċ import Ġandroid . Manifest Ċ import Ġandroid . annotation . Suppress Lint Ċ import Ġandroid . content . Context Ċ import Ġandroid . location . Gn ss Status Ċ import Ġandroid . location . Location Ċ import Ġandroid . location . Location Manager Ċ import Ġandroid . os . Build Ċ import Ġandroid . os . Handler Ċ import Ġandroid . os . Looper Ċ import Ġandroid . os . System Clock Ċ import Ġandroid . util . Log Ċ import Ġandroidx . core . content . Context Compat Ċ import Ġcom . android . gp st est . util . Preference Util . min Time Millis Ċ import Ġcom . android . gp st est . util . has Permission Ċ import Ġkotlinx . coroutines . Coroutine Scope Ċ import Ġkotlinx . coroutines . Experimental Cor outines Api Ċ import Ġkotlinx . coroutines . channels . await Close Ċ import Ġkotlinx . coroutines . flow .* Ċ import Ġjava . util . concurrent . TimeUnit Ċ Ċ private Ġconst Ġval ĠTAG Ġ= Ġ" Shared Gn ss Status Manager " Ċ Ċ /** Ċ Ġ* ĠWrap s Ġthe ĠG nss Status Ġupdates Ġin Ġcallback Flow Ċ Ġ* Ċ Ġ* ĠDerived Ġin Ġpart Ġfrom Ġhttps :// github . com / android / location - samples / blob / main / Location Updates Background Kotlin / app / src / main / java / com / google / android / gms / location / sample / location updates background kotlin / data / My Location Manager . kt Ċ Ġ* Ġand Ġhttps :// github . com / google code labs / kotlin - coroutines / blob / master / k tx - library - code lab / step - 0 6 / my k tx library / src / main / java / com / example / android / my k tx library / Location Utils . kt Ċ Ġ*/ Ċ class ĠShared Gn ss Status Manager Ġconstructor ( ĊĠĠĠ Ġprivate Ġval Ġcontext : ĠContext , ĊĠĠĠ Ġexternal Scope : ĠCor outine Scope Ċ ) Ġ{ ĊĠĠĠ Ġ// ĠState Ġof ĠG nss Status ĊĠĠĠ Ġprivate Ġval Ġ_ status State Ġ= ĠMutable State Flow < Gn ss Status State >( Gn ss Status State . Stopped ) ĊĠĠĠ Ġval Ġstatus State : ĠState Flow < Gn ss Status State > Ġ= Ġ_ status State ĊĊĠĠĠ Ġ// ĠState Ġof Ġongoing ĠGN SS Ġfix ĊĠĠĠ Ġprivate Ġval Ġ_ fix State Ġ= ĠMutable State Flow < Fix State >( Fix State . Not Acquire d ) ĊĠĠĠ Ġval Ġfix State : ĠState Flow < Fix State > Ġ= Ġ_ fix State ĊĊĠĠĠ Ġ// ĠState Ġof Ġfirst ĠGN SS Ġfix ĊĠĠĠ Ġprivate Ġval Ġ_ first Fix State Ġ= ĠMutable State Flow < First Fix State >( First Fix State . Not Acquire d ) ĊĠĠĠ Ġval Ġfirst Fix State : ĠState Flow < First Fix State > Ġ= Ġ_ first Fix State ĊĊĠĠĠ Ġ@ Experimental Cor outines Api ĊĠĠĠ Ġ@ Suppress Lint (" Missing Permission ") ĊĠĠĠ Ġprivate Ġval Ġ_ gn ss Status Updates Ġ= Ġcallback Flow Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġlocation Manager Ġ= Ġcontext . getSystem Service ( Context . LOCATION _ SERVICE ) Ġas ĠLocation Manager ĊĠĠĠĠĠĠĠ Ġval Ġcallback : ĠG nss Status . Callback Ġ= Ġobject Ġ: ĠG nss Status . Callback () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġon Started () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ_ status State . value Ġ= ĠG nss Status State . Started ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġon Stopped () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ_ status State . value Ġ= ĠG nss Status State . Stopped ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġon First Fix ( tt ff Millis : ĠInt ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ_ first Fix State . value Ġ= ĠFirst Fix State . Acquire d ( tt ff Millis ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ_ fix State . value Ġ= ĠFix State . Acquire d ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġon S atellite Status Changed ( status : ĠG nss Status ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġlocation Ġ= Ġlocation Manager . getLast Known Location ( Location Manager . GPS _ PROVIDER ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( location Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ_ fix State . value Ġ= Ġcheck Have Fix ( location ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ_ fix State . value Ġ= ĠFix State . Not Acquire d ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Log . d ( TAG , Ġ" New Ġgn ss Status : Ġ${ status }") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠSend Ġthe Ġnew Ġlocation Ġto Ġthe ĠFlow Ġob servers ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtry Send ( status ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġif Ġ(! context . has Permission ( Manifest . permission . ACCESS _ F INE _ LOCATION ) Ġ|| ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ! context . has Permission ( Manifest . permission . ACCESS _ CO AR SE _ LOCATION ) ĊĠĠĠĠĠĠĠ Ġ) Ġclose () ĊĊĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" Starting ĠG nss Status Ġupdates ") ĊĊĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( Build . VERSION . SDK _ INT Ġ>= ĠBuild . VERSION _ CODES . R ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlocation Manager . register Gn ss Status Callback ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠContext Compat . get Main Executor ( context ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcallback ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlocation Manager . register Gn ss Status Callback ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcallback , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠHandler ( Looper . get Main Looper ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġclose ( e ) Ġ// Ġin Ġcase Ġof Ġexception , Ġclose Ġthe ĠFlow ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġawait Close Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" Stopping ĠG nss Status Ġupdates ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlocation Manager . unregister Gn ss Status Callback ( callback ) Ġ// Ġclean Ġup Ġwhen ĠFlow Ġcollection Ġends ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ_ fix State . value Ġ= ĠFix State . Not Acquire d ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ_ first Fix State . value Ġ= ĠFirst Fix State . Not Acquire d ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ}. share In ( ĊĠĠĠĠĠĠĠ Ġexternal Scope , ĊĠĠĠĠĠĠĠ Ġreplay Ġ= Ġ 0 , ĊĠĠĠĠĠĠĠ Ġstarted Ġ= ĠSh aring Started . While Sub scribed () ĊĠĠĠ Ġ) ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠReturns Ġa Ġflow Ġof ĠG nss Status Ġbacked Ġby Ġthe ĠAndroid Ġsystem ĠG nss Status ĠAPI . ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* ĠNote Ġthat Ġfor Ġother Ġflows Ġin Ġthis Ġclass Ġto Ġreturn Ġup - to - date Ġdata Ġthis Ġflow Ġmust Ġbe Ġactive . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġ@ Experimental Cor outines Api ĊĠĠĠ Ġfun Ġstatus Flow (): ĠFlow < Gn ss Status > Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġ_ gn ss Status Updates ĊĠĠĠ Ġ} Ċ } Ċ Ċ private Ġfun Ġcheck Have Fix ( location : ĠLocation ): ĠFix State Ġ{ ĊĠĠĠ Ġval Ġthreshold Ġ= Ġif Ġ( min Time Millis () Ġ>= Ġ 1 0 0 0 L ) Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠUse Ġtwo Ġrequested Ġupdate Ġintervals Ġ( it Ġmissed Ġtwo Ġupdates ) ĊĠĠĠĠĠĠĠ ĠTimeUnit . MILLISECONDS . to Nan os ( min Time Millis () Ġ* Ġ 2 ) ĊĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠMost ĠAndroid Ġdevices Ġcan 't Ġrefresh Ġfaster Ġthan Ġ 1 Hz , Ġso Ġuse Ġ 1 . 5 Ġseconds Ġ- Ġsee Ġ# 5 4 4 ĊĠĠĠĠĠĠĠ ĠTimeUnit . MILLISECONDS . to Nan os ( 1 5 0 0 ) ĊĠĠĠ Ġ} ĊĠĠĠ Ġval Ġnan os Since Fix Ġ= ĠSystem Clock . elapsed Realtime Nan os () Ġ- Ġlocation . elapsed Realtime Nan os ĊĠĠĠ Ġreturn Ġif Ġ( nan os Since Fix Ġ> Ġthreshold ) Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠWe Ġlost Ġthe ĠGN SS Ġfix ĊĠĠĠĠĠĠĠ ĠFix State . Not Acquire d ĊĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠWe Ġhave Ġa ĠGN SS Ġfix ĊĠĠĠĠĠĠĠ ĠFix State . Acquire d ĊĠĠĠ Ġ} Ċ } Ċ Ċ // ĠStarted / stopped Ġstates Ċ sealed Ġclass ĠG nss Status State Ġ{ ĊĠĠĠ Ġobject ĠStarted Ġ: ĠG nss Status State () ĊĠĠĠ Ġobject ĠSto pped Ġ: ĠG nss Status State () Ċ } Ċ Ċ // ĠGN SS Ġongoing Ġfix Ġacquired Ġstates Ċ sealed Ġclass ĠFix State Ġ{ ĊĠĠĠ Ġobject ĠAc quire d Ġ: ĠFix State () ĊĠĠĠ Ġobject ĠNot Acquire d Ġ: ĠFix State () Ċ } Ċ Ċ // ĠGN SS Ġfirst Ġfix Ġstate Ċ sealed Ġclass ĠFirst Fix State Ġ{ ĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* Ġ[ tt ff Millis ] Ġthe Ġtime Ġfrom Ġstart Ġof ĠGN SS Ġto Ġfirst Ġfix Ġin Ġmilliseconds . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġdata Ġclass ĠAc quire d ( val Ġtt ff Millis : ĠInt ) Ġ: ĠFirst Fix State () ĊĠĠĠ Ġobject ĠNot Acquire d Ġ: ĠFirst Fix State () Ċ }