/* Ċ Ġ* ĠCopyright Ġ 2 0 2 1 ĠThe ĠAndroid ĠOpen ĠSource ĠProject Ċ Ġ* Ċ Ġ* Ġ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 . example . exercise Ċ Ċ import Ġandroid . app . Notification Ċ import Ġandroid . app . Notification Channel Ċ import Ġandroid . app . Notification Manager Ċ import Ġandroid . app . Service Ċ import Ġandroid . content . Intent Ċ import Ġandroid . os . Binder Ċ import Ġandroid . os . IB inder Ċ import Ġandroid . os . System Clock Ċ import Ġandroid . util . Log Ċ import Ġandroidx . core . app . Notification Compat Ċ import Ġandroidx . health . services . client . data . DataPoint Ċ import Ġandroidx . health . services . client . data . DataType Ċ import Ġandroidx . health . services . client . data . Exercise State Ċ import Ġandroidx . health . services . client . data . Exercise Update Ċ import Ġandroidx . lifecycle . Lifecycle Service Ċ import Ġandroidx . lifecycle . lifecycle Scope Ċ import Ġandroidx . navigation . Nav Deep Link Builder Ċ import Ġandroidx . we ar . ongo ing . O ngo ing Activity Ċ import Ġandroidx . we ar . ongo ing . Status Ċ import Ġdagger . h ilt . android . Android EntryPoint Ċ import Ġkotlinx . coroutines . delay Ċ import Ġkotlinx . coroutines . flow . Mutable State Flow Ċ import Ġkotlinx . coroutines . flow . State Flow Ċ import Ġkotlinx . coroutines . flow . collect Ċ import Ġkotlinx . coroutines . launch Ċ import Ġjava . time . Duration Ċ import Ġjava . time . Instant Ċ import Ġjavax . inject . Inject Ċ Ċ /** Ċ Ġ* ĠService Ġthat Ġlist ens Ġto Ġthe Ġexercise Ġstate Ġof Ġthe Ġapp . ĠLocal Ġclients Ġcan Ġbind Ġto Ġthis Ġservice Ġto Ċ Ġ* Ġaccess Ġthe Ġexercise Ġstate Ġand Ġassociated Ġmetrics . Ċ Ġ* Ċ Ġ* ĠThis Ġservice Ġmanages Ġits Ġown Ġlifecycle . ĠOnce Ġa Ġclient Ġbind s Ġto Ġit , Ġit Ġcalls Ġ[ start Service ] Ġon Ċ Ġ* Ġitself Ġand Ġregisters Ġfor Ġexercise Ġstate . ĠWhen Ġthere Ġare Ġno Ġbound Ġclients , Ġif Ġthere Ġisn 't Ġan Ċ Ġ* Ġactive Ġexercise , Ġthis Ġservice Ġstops Ġitself . ĠIf Ġthere Ġis Ġan Ġactive Ġexercise , Ġit Ġmoves Ġitself Ġto Ċ Ġ* Ġthe Ġforeground Ġwith Ġan Ġongoing Ġnotification Ġso Ġthat Ġthe Ġuser Ġhas Ġan Ġeasy Ġway Ġback Ġinto Ġthe Ġapp . Ċ Ġ* Ċ Ġ* Ġ( see Ġ[ Bound ĠServices ]( https :// developer . android . com / guide / components / bound - services )) Ċ Ġ*/ Ċ @ Android EntryPoint Ċ class ĠExercise Service Ġ: ĠLifecycle Service () Ġ{ ĊĊĠĠĠ Ġ@ Inject ĊĠĠĠ Ġlateinit Ġvar Ġhealth Services Manager : ĠHealth Services Manager ĊĊĠĠĠ Ġprivate Ġval Ġlocal Binder Ġ= ĠLocal Binder () ĊĠĠĠ Ġprivate Ġvar Ġis Bound Ġ= Ġfalse ĊĠĠĠ Ġprivate Ġvar Ġis Started Ġ= Ġfalse ĊĠĠĠ Ġprivate Ġvar Ġis Foreground Ġ= Ġfalse ĊĊĠĠĠ Ġprivate Ġval Ġ_ exercise State Ġ= ĠMutable State Flow ( Exercise State . USER _ ENDED ) ĊĠĠĠ Ġval Ġexercise State : ĠState Flow < Exercise State > Ġ= Ġ_ exercise State ĊĊĠĠĠ Ġprivate Ġval Ġ_ exercise Metrics Ġ= ĠMutable State Flow ( empty Map < DataType , ĠList < DataPoint >> ()) ĊĠĠĠ Ġval Ġexercise Metrics : ĠState Flow < Map < DataType , ĠList < DataPoint >>> Ġ= Ġ_ exercise Metrics ĊĊĠĠĠ Ġprivate Ġval Ġ_ exercise L aps Ġ= ĠMutable State Flow ( 0 ) ĊĠĠĠ Ġval Ġexercise L aps : ĠState Flow < Int > Ġ= Ġ_ exercise L aps ĊĊĠĠĠ Ġprivate Ġval Ġ_ exercise Duration Update Ġ= ĠMutable State Flow ( Active Duration Update ()) ĊĠĠĠ Ġval Ġexercise Duration Update : ĠState Flow < Active Duration Update > Ġ= Ġ_ exercise Duration Update ĊĊĠĠĠ Ġoverride Ġfun ĠonStart Command ( intent : ĠIntent ?, Ġflags : ĠInt , Ġstart Id : ĠInt ): ĠInt Ġ{ ĊĠĠĠĠĠĠĠ Ġsuper . onStart Command ( intent , Ġflags , Ġstart Id ) ĊĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" onStart Command ") ĊĊĠĠĠĠĠĠĠ Ġif Ġ(! is Started ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġis Started Ġ= Ġtrue ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! is Bound ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠWe Ġmay Ġhave Ġbeen Ġrestarted Ġby Ġthe Ġsystem . ĠManage Ġour Ġlifetime Ġaccordingly . ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġgo Foreground Or Stop Self () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠStart Ġcollecting Ġexercise Ġinformation . ĠWe Ġmight Ġstop Ġshortly Ġ( see Ġabove ), Ġin Ġwhich ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġcase Ġlaunch When Started Ġtakes Ġcare Ġof Ġcancel ing Ġthis Ġcoroutine . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlifecycle Scope . launch When Started Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġhealth Services Manager . exercise Update Flow . collect Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ( it ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠExercise Message . Exercise Update Message Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprocess Exercise Update ( it . exercise Update ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠExercise Message . Lap Summary Message Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ_ exercise L aps . value Ġ= Ġit . lap Summary . lap Count ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ// ĠIf Ġour Ġprocess Ġis Ġstopped , Ġwe Ġmight Ġhave Ġan Ġactive Ġexercise . ĠWe Ġwant Ġthe Ġsystem Ġto ĊĠĠĠĠĠĠĠ Ġ// Ġrecreate Ġour Ġservice Ġso Ġthat Ġwe Ġcan Ġpresent Ġthe Ġongoing Ġnotification Ġin Ġthat Ġcase . ĊĠĠĠĠĠĠĠ Ġreturn ĠService . START _ STICK Y ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġgo Foreground Or Stop Self () Ġ{ ĊĠĠĠĠĠĠĠ Ġlifecycle Scope . launch Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠWe Ġmay Ġhave Ġbeen Ġrestarted Ġby Ġthe Ġsystem . ĠCheck Ġfor Ġan Ġongoing Ġexercise . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( health Services Manager . is Exercise InProgress ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠOur Ġexercise Ġis Ġrunning . ĠGive Ġthe Ġuser Ġa Ġway Ġinto Ġthe Ġapp . ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpost O ngo ing Activity Notification () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠWe Ġhave Ġnothing Ġto Ġdo , Ġso Ġwe Ġcan Ġstop . ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstop Self () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġprocess Exercise Update ( exercise Update : ĠExercise Update ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġold State Ġ= Ġ_ exercise State . value ĊĠĠĠĠĠĠĠ Ġif Ġ(! old State . is Ended Ġ&& Ġexercise Update . state . is Ended ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠOur Ġexercise Ġended . ĠThis Ġcould Ġbe Ġbecause Ġanother Ġapp 's Ġexercise Ġhas Ġsuper se ded Ġour s , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġso Ġdismiss Ġany Ġongoing Ġactivity Ġnotification . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġremove O ngo ing Activity Notification () ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġif Ġ( old State . is Ended Ġ&& Ġexercise Update . state Ġ== ĠExercise State . ACTIVE ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠReset Ġl aps . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ_ exercise L aps . value Ġ= Ġ 0 ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ_ exercise State . value Ġ= Ġexercise Update . state ĊĠĠĠĠĠĠĠ Ġ_ exercise Metrics . value Ġ= Ġexercise Update . latest Metrics ĊĠĠĠĠĠĠĠ Ġ_ exercise Duration Update . value Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ ĠActive Duration Update ( exercise Update . active Duration , ĠInstant . now ()) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġon Bind ( intent : ĠIntent ): ĠI Binder ? Ġ{ ĊĠĠĠĠĠĠĠ Ġsuper . on Bind ( intent ) ĊĠĠĠĠĠĠĠ Ġhandle Bind () ĊĠĠĠĠĠĠĠ Ġreturn Ġlocal Binder ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġon Re bind ( intent : ĠIntent ?) Ġ{ ĊĠĠĠĠĠĠĠ Ġsuper . on Re bind ( intent ) ĊĠĠĠĠĠĠĠ Ġhandle Bind () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġhandle Bind () Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ(! is Bound ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġis Bound Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠStart Ġour self . ĠThis Ġwill Ġbegin Ġcollecting Ġexercise Ġstate Ġif Ġwe Ġaren 't Ġalready . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġstart Service ( Intent ( this , Ġthis :: class . java )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠAs Ġlong Ġas Ġa ĠUI Ġclient Ġis Ġbound Ġto Ġus , Ġwe Ġcan Ġhide Ġthe Ġongoing Ġactivity Ġnotification . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġremove O ngo ing Activity Notification () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġon Un bind ( intent : ĠIntent ?): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġis Bound Ġ= Ġfalse ĊĠĠĠĠĠĠĠ Ġlifecycle Scope . launch Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠClient Ġcan Ġun bind Ġbecause Ġit Ġwent Ġthrough Ġa Ġconfiguration Ġchange , Ġin Ġwhich Ġcase Ġit ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġwill Ġbe Ġre created Ġand Ġbind Ġagain Ġshortly . ĠWait Ġa Ġfew Ġseconds , Ġand Ġif Ġstill Ġnot Ġbound , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġmanage Ġour Ġlifetime Ġaccordingly . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdelay ( UN BIND _ DELAY _ M ILL IS ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! is Bound ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġgo Foreground Or Stop Self () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ// ĠAllow Ġclients Ġto Ġre - bind . ĠWe Ġwill Ġbe Ġin formed Ġof Ġthis Ġin Ġon Re bind (). ĊĠĠĠĠĠĠĠ Ġreturn Ġtrue ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġremove O ngo ing Activity Notification () Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( is Foreground ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" Removing Ġongoing Ġactivity Ġnotification ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġis Foreground Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġstop Foreground ( true ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġpost O ngo ing Activity Notification () Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ(! is Foreground ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġis Foreground Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" Post ing Ġongoing Ġactivity Ġnotification ") ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġcreate Notification Channel () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġstart Foreground ( NOTIFICATION _ ID , Ġbuild Notification ()) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġcreate Notification Channel () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġnotification Channel Ġ= ĠNotification Channel ( ĊĠĠĠĠĠĠĠĠĠĠĠ ĠNOT IFICATION _ CHANNEL , ĊĠĠĠĠĠĠĠĠĠĠĠ ĠNOT IFICATION _ CHANNEL _ DISPLAY , ĊĠĠĠĠĠĠĠĠĠĠĠ ĠNotification Manager . IMPORT ANCE _ DEFAULT ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġval Ġmanager Ġ= Ġget System Service ( NOTIFICATION _ SERVICE ) Ġas ĠNotification Manager ĊĠĠĠĠĠĠĠ Ġmanager . create Notification Channel ( notification Channel ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġbuild Notification (): ĠNotification Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠMake Ġan Ġintent Ġthat Ġwill Ġtake Ġthe Ġuser Ġstraight Ġto Ġthe Ġexercise ĠUI . ĊĠĠĠĠĠĠĠ Ġval Ġpending Intent Ġ= ĠNav Deep Link Builder ( this ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. set Graph ( R . navigation . nav _ graph ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. set Destination ( R . id . exercise Fragment ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. create Pending Intent () ĊĠĠĠĠĠĠĠ Ġ// ĠBuild Ġthe Ġnotification . ĊĠĠĠĠĠĠĠ Ġval Ġnotification Builder Ġ= ĠNotification Compat . Builder ( this , ĠNOT IFICATION _ CHANNEL ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. setContent Title ( NOTIFICATION _ TITLE ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. setContent Text ( NOTIFICATION _ TEXT ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. set Small Icon ( R . drawable . ic _ run ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. setContent Intent ( pending Intent ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. set O ngo ing ( true ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. set Category ( Notification Compat . CATEGORY _ WORK OUT ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. setVisibility ( Notification Compat . VIS IBILITY _ PUBLIC ) ĊĊĠĠĠĠĠĠĠ Ġ// ĠO ngo ing ĠActivity Ġallows Ġan Ġongoing ĠNotification Ġto Ġappear Ġon Ġadditional Ġsurfaces Ġin Ġthe ĊĠĠĠĠĠĠĠ Ġ// ĠW ear ĠOS Ġuser Ġinterface , Ġso Ġthat Ġusers Ġcan Ġstay Ġmore Ġeng aged Ġwith Ġlong Ġrunning Ġtasks . ĊĠĠĠĠĠĠĠ Ġval Ġlast Update Ġ= Ġexercise Duration Update . value ĊĠĠĠĠĠĠĠ Ġval Ġduration Ġ= Ġlast Update . duration Ġ+ ĠDuration . between ( last Update . timestamp , ĠInstant . now ()) ĊĠĠĠĠĠĠĠ Ġval Ġstart Millis Ġ= ĠSystem Clock . elapsed Realtime () Ġ- Ġduration . to Millis () ĊĠĠĠĠĠĠĠ Ġval Ġongoing Activity Status Ġ= ĠStatus . Builder () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. add Template ( ONGO ING _ STATUS _ TEMPLATE ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. add Part (" duration ", ĠStatus . Stop watch Part ( start Millis )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. build () ĊĠĠĠĠĠĠĠ Ġval Ġongoing Activity Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ ĠO ngo ing Activity . Builder ( application Context , ĠNOT IFICATION _ ID , Ġnotification Builder ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. set Animated Icon ( R . drawable . ic _ run ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. set Static Icon ( R . drawable . ic _ run ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. set Touch Intent ( pending Intent ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. setStatus ( ongo ing Activity Status ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. build () ĊĠĠĠĠĠĠĠ Ġongoing Activity . apply ( application Context ) ĊĊĠĠĠĠĠĠĠ Ġreturn Ġnotification Builder . build () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĠLocal Ġclients Ġwill Ġuse Ġthis Ġto Ġaccess Ġthe Ġservice . Ġ*/ ĊĠĠĠ Ġinner Ġclass ĠLocal Binder Ġ: ĠB inder () Ġ{ ĊĠĠĠĠĠĠĠ Ġfun Ġget Service () Ġ= Ġthis @ Exercise Service ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠNOT IFICATION _ ID Ġ= Ġ 1 ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠNOT IFICATION _ CHANNEL Ġ= Ġ" com . example . exercise . ONGO ING _ EX ER CI SE " ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠNOT IFICATION _ CHANNEL _ DISPLAY Ġ= Ġ" O ngo ing ĠExercise " ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠNOT IFICATION _ TITLE Ġ= Ġ" Exercise ĠSample " ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠNOT IFICATION _ TEXT Ġ= Ġ" O ngo ing ĠExercise " ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠON GO ING _ STATUS _ TEMPLATE Ġ= Ġ" O ngo ing ĠExercise Ġ# duration #" ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠUN BIND _ DELAY _ M ILL IS Ġ= Ġ 3 _ 0 0 0 L ĊĠĠĠ Ġ} Ċ } Ċ Ċ /** ĠKeep s Ġtrack Ġof Ġthe Ġlast Ġtime Ġwe Ġreceived Ġan Ġupdate Ġfor Ġactive Ġexercise Ġduration . Ġ*/ Ċ data Ġclass ĠActive Duration Update ( ĊĠĠĠ Ġ/** ĠThe Ġlast Ġactive Ġduration Ġreported . Ġ*/ ĊĠĠĠ Ġval Ġduration : ĠDuration Ġ= ĠDuration . ZERO , ĊĠĠĠ Ġ/** ĠThe Ġinstant Ġat Ġwhich Ġthe Ġlast Ġduration Ġwas Ġreported . Ġ*/ ĊĠĠĠ Ġval Ġtimestamp : ĠInstant Ġ= ĠInstant . now () Ċ ) Ċ