package Ġde . se em oo . at _ tracking _ detection . detection Ċ Ċ import Ġandroid . content . Context Ċ import Ġandroid . content . SharedPreferences Ċ import Ġandroid . location . Location Ċ import Ġandroid . location . Location Manager Ċ import Ġandroidx . h ilt . work . H ilt Worker Ċ import Ġandroidx . work . Coroutine Worker Ċ import Ġandroidx . work . Data Ċ import Ġandroidx . work . Worker Parameters Ċ import Ġdagger . ass isted . Ass isted Ċ import Ġdagger . ass isted . Ass isted Inject Ċ import Ġde . se em oo . at _ tracking _ detection . database . repository . Beacon Repository Ċ import Ġde . se em oo . at _ tracking _ detection . database . repository . Device Repository Ċ import Ġde . se em oo . at _ tracking _ detection . database . models . Beacon Ċ import Ġde . se em oo . at _ tracking _ detection . database . models . device . Base Device Ċ import Ġde . se em oo . at _ tracking _ detection . database . models . device . DeviceType Ċ import Ġde . se em oo . at _ tracking _ detection . notifications . Notification Service Ċ import Ġtim ber . log . Tim ber Ċ import Ġjava . time . LocalDateTime Ċ import Ġjava . time . Zone Offset Ċ import Ġjava . time . temporal . Ch rono Unit Ċ Ċ @ H ilt Worker Ċ class ĠTracking Detector Worker Ġ@ Ass isted Inject Ġconstructor ( ĊĠĠĠ Ġ@ Ass isted Ġapp Context : ĠContext , ĊĠĠĠ Ġ@ Ass isted Ġworker Params : ĠWorker Parameters , ĊĠĠĠ Ġprivate Ġval Ġnotification Service : ĠNotification Service , ĊĠĠĠ Ġprivate Ġval Ġdevice Repository : ĠDevice Repository , ĊĠĠĠ Ġprivate Ġval Ġbe acon Repository : ĠBe acon Repository , ĊĠĠĠ Ġprivate Ġval Ġshared Preferences : ĠSharedPreferences Ċ ) Ġ: ĠCor outine Worker ( app Context , Ġworker Params ) Ġ{ ĊĊĠĠĠ Ġoverride Ġsuspend Ġfun Ġdo Work (): ĠResult Ġ{ ĊĠĠĠĠĠĠĠ ĠTim ber . d (" Tracking Ġdetection Ġbackground Ġjob Ġstarted !") ĊĠĠĠĠĠĠĠ Ġval Ġignored Devices Ġ= Ġdevice Repository . ignored Devices Sync ĊĠĠĠĠĠĠĠ Ġ// Ġremove Ġdevices Ġwhich Ġare Ġignored ĊĠĠĠĠĠĠĠ Ġval Ġcleaned Be ac ons Per Device Ġ= Ġget Latest Be ac ons Per Device (). filter Keys Ġ{ Ġaddress Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ! ignored Devices . map Ġ{ Ġit . address Ġ}. contains ( address ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġvar Ġnot ific ait ons Sent Ġ= Ġ 0 ĊĊĠĠĠĠĠĠĠ Ġ// TODO : ĠCan Ġwe Ġdo Ġthis Ġin Ġparallel ? ĊĠĠĠĠĠĠĠ Ġcleaned Be ac ons Per Device . forEach Ġ{ Ġmap Entry Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// TODO : ĠImplement Ġtracking Ġdetection Ġfor ĠTile ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdevice Ġ= Ġdevice Repository . getDevice ( map Entry . key ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Check Ġthat Ġwe Ġfound Ġenough Ġbe ac ons ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( map Entry . value . size Ġ< ĠMAX _ BE AC ONS _ BEFORE _ ALARM ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn @ forEach ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Checks Ġif Ġthe Ġtime Ġdifference Ġbetween Ġreceived Ġbe ac ons Ġis Ġlarge Ġenough ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! is Tracking For En ough Time ( device , Ġmap Entry . value )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn @ forEach ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Check Ġthat Ġwe Ġdo Ġnot Ġsend Ġnotifications Ġtoo Ġoften Ġ( one Ġnotification Ġevery Ġ 8 Ġhours ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( device ?. last Notification Sent Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġhours Passed Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdevice . last Notification Sent !!. until ( LocalDateTime . now (), ĠCh rono Unit . HOUR S ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( hours Passed Ġ< Ġ 8 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn @ forEach ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Check Ġif Ġthe Ġbe acon Ġhave Ġtravel led Ġfar Ġenough ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( use Location Ġ&& Ġ! has Min Beacon Distance ( map Entry . value )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn @ forEach ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . d (" Found Ġmore Ġthan Ġ$ MAX _ BE AC ONS _ BEFORE _ ALARM Ġbe ac ons Ġper Ġdevice ... ĠSending ĠNotification !") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnotification Service . send Tracking Notification ( map Entry . key ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdevice ?. notification Sent Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdevice ?. last Notification Sent Ġ= ĠLocalDateTime . now () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdevice ?. let Ġ{ Ġd Ġ-> Ġdevice Repository . update ( d ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnot ific ait ons Sent Ġ+= Ġ 1 ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ ĠTim ber . d (" Tracking Ġdetector Ġworker Ġfinished . ĠSent Ġ$ not ific ait ons Sent Ġnotifications ") ĊĠĠĠĠĠĠĠ Ġreturn ĠResult . success ( ĊĠĠĠĠĠĠĠĠĠĠĠ ĠData . Builder () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. put Int (" sent Notifications ", Ġnot ific ait ons Sent ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. build () ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġval Ġuse Location Ġ= Ġshared Preferences . getBoolean (" use _ location ", Ġfalse ) ĊĊĠĠĠ Ġprivate Ġfun Ġget Latest Be ac ons Per Device (): ĠHashMap < String , ĠList < Beacon >> Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġbe ac ons Per Device : ĠHashMap < String , ĠList < Beacon >> Ġ= ĠHashMap () ĊĠĠĠĠĠĠĠ Ġval Ġsince Ġ= ĠLocalDateTime . parse ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġshared Preferences . getString ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" last _ scan ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLocalDateTime . now ( Zone Offset . UTC ). toString () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ// Gets Ġall Ġbe ac ons Ġfound Ġin Ġthe Ġlast Ġscan . ĠThen Ġwe Ġget Ġall Ġbe ac ons Ġfor Ġthe Ġdevice Ġthat Ġemitted Ġone Ġof Ġthose ĊĠĠĠĠĠĠĠ Ġbe acon Repository . get Latest Be ac ons ( since ). forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbe ac ons Ġ= Ġbe acon Repository . getDevice Be ac ons ( it . device Address ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbe ac ons Per Device [ it . device Address ] Ġ= Ġbe ac ons ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġbe ac ons Per Device ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠMAX _ BE AC ONS _ BEFORE _ ALARM Ġ= Ġ 3 ĊĊĠĠĠĠĠĠĠ Ġ/// ĠMinimum Ġtracking Ġtime ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠMIN _ TRACK ING _ TIME _ SECONDS Ġ= Ġ 3 0 Ġ* Ġ 6 0 ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠMIN _ DISTANCE _ B ETWEEN _ BE AC ONS Ġ= Ġ 4 0 0 ĊĊĠĠĠĠĠĠĠ Ġ// Moving Ġsome Ġfunctions Ġto Ġthe Ġcompanion Ġobject Ġto Ġmake Ġthem Ġtest able ĊĊĠĠĠĠĠĠĠ Ġ/** ĊĠĠĠĠĠĠĠĠ Ġ* ĠGets Ġa Ġlist Ġof Ġbe ac ons Ġand Ġchecks Ġif Ġthe Ġuser Ġis Ġbe e ing Ġtracked Ġfor Ġthe Ġminimum Ġamount Ġof ĊĠĠĠĠĠĠĠĠ Ġ* Ġtime Ġbefore Ġa Ġnotification Ġis Ġsent . ĊĠĠĠĠĠĠĠĠ Ġ* Ġ@ param Ġbe ac ons ĊĠĠĠĠĠĠĠĠ Ġ* Ġ@ param Ġbase Device ĊĠĠĠĠĠĠĠĠ Ġ* Ġ@ return ĊĠĠĠĠĠĠĠĠ Ġ*/ ĊĠĠĠĠĠĠĠ Ġfun Ġis Tracking For En ough Time ( base Device : ĠBase Device ?, Ġbe ac ons : ĠList < Beacon >): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( be ac ons . isEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Sort Ġthe Ġlist Ġby Ġreceived Ġat ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Last Ġbe acon Ġreceived Ġis Ġlast Ġat Ġthe Ġlist ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbe ac ons Sorted Ġ= Ġbe ac ons . sorted By Ġ{ Ġit . received At Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġfirst Beacon Ġ= Ġbe ac ons Sorted . first () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġlast Beacon Ġ= Ġbe ac ons Sorted . last () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġtime Diff Ġ= ĠCh rono Unit . SECONDS . between ( first Beacon . received At , Ġlast Beacon . received At ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġmin Tracking Time Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbase Device ?. device ?. device Context ?. min Tracking Time Ġ?: ĠMIN _ TRACK ING _ TIME _ SECONDS ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġtime Diff Ġ>= Ġmin Tracking Time ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġhas Min Beacon Distance ( be ac ons : ĠList < Beacon >): ĠBoolean Ġ{ ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġdistance Reached Ġ= Ġfalse ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠCheck Ġfirst Ġif Ġany Ġbe ac ons Ġmeet Ġthe Ġminimal Ġdistance Ġrequirement ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbe ac ons . forEach Ġ{ Ġfirst Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbe ac ons . forEach Ġ{ Ġsecond Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfirst . latitude Ġ!= Ġnull Ġ&& Ġfirst . longitude Ġ!= Ġnull Ġ&& ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsecond . latitude Ġ!= Ġnull Ġ&& Ġsecond . longitude Ġ!= Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġfirst Location Ġ= Ġget Location ( first . latitude !! , Ġfirst . longitude !! ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġsecond Location Ġ= Ġget Location ( second . latitude !! , Ġsecond . longitude !! ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠReturn Ġtrue Ġif Ġany Ġbe acon Ġpair Ġfull Ġfill s Ġthe Ġminimal Ġdistance Ġrequirement ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( first Location . distance To ( second Location ) Ġ>= ĠMIN _ DISTANCE _ B ETWEEN _ BE AC ONS ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdistance Reached Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġdistance Reached ĊĠĠĠĠĠĠĠ Ġ} ĊĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġget Location ( latitude : ĠDouble , Ġlongitude : ĠDouble ): ĠLocation Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġlocation Ġ= ĠLocation ( Location Manager . GPS _ PROVIDER ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlocation . latitude Ġ= Ġlatitude ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlocation . longitude Ġ= Ġlongitude ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġlocation ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠ Ġ} Ċ Ċ }