package Ġka ist . ic lab . abc . background . collector Ċ Ċ import Ġandroid . Manifest Ċ import Ġandroid . arch . lifecycle . Mutable LiveData Ċ import Ġandroid . content . Context Ċ import Ġandroid . media . Audio Format Ċ import Ġandroid . media . Audio Record Ċ import Ġandroid . media . Media Recorder Ċ import Ġandroid . os . System Clock Ċ import Ġandroid . util . Log Ċ import Ġio . object box . kotlin . box For Ċ import Ġka ist . ic lab . abc . App Ċ import Ġka ist . ic lab . abc . background . Status Ċ import Ġka ist . ic lab . abc . common . util . Permission Utils Ċ import Ġka ist . ic lab . abc . common . util . Utils Ċ import Ġka ist . ic lab . abc . data . entities . Record Entity Ċ import Ġjava . io . File Ċ import Ġjava . io . File OutputStream Ċ import Ġjava . util . concurrent . Executors Ċ import Ġjava . util . concurrent . Scheduled Future Ċ import Ġjava . util . concurrent . TimeUnit Ċ Ċ class ĠAmb ient Sound Collector ( val Ġcontext : ĠContext ) Ġ: ĠBase Collector Ġ{ ĊĠĠĠ Ġprivate Ġvar Ġscheduled Future : ĠScheduled Future < *> ? Ġ= Ġnull ĊĊĠĠĠ Ġoverride Ġfun Ġstart Collection ( uuid : ĠString , Ġgroup : ĠString , Ġemail : ĠString ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif ( scheduled Future ?. is Done Ġ== Ġfalse ) Ġreturn ĊĊĠĠĠĠĠĠĠ Ġstatus . post Value ( Status . STARTED ) ĊĠĠĠĠĠĠĠ Ġscheduled Future Ġ= ĠExec utors . new Single Thread Scheduled Executor (). schedule With Fixed Delay ({ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcollect ( uuid , Ġgroup , Ġemail ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( e Ġis ĠSecurity Exception ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstop Collection () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstatus . post Value ( Status . ABORT ED ( e )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ}, Ġ 0 , Ġ 1 5 , ĠTimeUnit . MIN UTES ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġstop Collection () Ġ{ ĊĠĠĠĠĠĠĠ Ġscheduled Future ?. cancel ( true ) ĊĠĠĠĠĠĠĠ Ġstatus . post Value ( Status . C ANCE LED ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġcollect ( uuid : ĠString , Ġgroup : ĠString , Ġemail : ĠString ) Ġ{ ĊĠĠĠĠĠĠĠ Ġstatus . post Value ( Status . RUNNING ) ĊĊĠĠĠĠĠĠĠ Ġif (! check Enable To Collect ( context )) Ġthrow ĠSecurity Exception (" Ambient Ġsound Ġis Ġnot Ġgranted Ġto Ġbe Ġcollected .") ĊĊĠĠĠĠĠĠĠ Ġval ĠfileName Ġ= Ġ"${ System . currentTimeMillis ()}. record " ĊĠĠĠĠĠĠĠ Ġval Ġbuf Size Ġ= ĠAudio Record . getMin BufferSize ( AUDIO _ SAMPLE _ RAT ES _ IN _ HZ , ĠA UDIO _ CHANNEL , ĠA UDIO _ ENCODING ) Ġ* Ġ 2 ĊĠĠĠĠĠĠĠ Ġvar Ġrecorder : ĠAudio Record ? Ġ= Ġnull ĊĊĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġfile Ġ= ĠFile ( context . get External Files Dir ( null ), ĠfileName ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrecorder Ġ= ĠAudio Record ( Media Recorder . Audio Source . MIC , ĠA UDIO _ SAMPLE _ RAT ES _ IN _ HZ , ĠA UDIO _ CHANNEL , ĠA UDIO _ ENCODING , Ġbuf Size ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġretry Count Ġ= Ġ 0 ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhile Ġ( recorder . state Ġ!= ĠAudio Record . STATE _ INITIAL IZED Ġ&& Ġretry Count Ġ< ĠMAX _ RE TR IES ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠSystem Clock . sleep ( 1 0 0 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġretry Count ++ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( recorder . state Ġ!= ĠAudio Record . STATE _ INITIAL IZED ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIllegalStateException (" Audio Ġstep 1 State Ġnot Ġinitialized .") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrecorder . start Recording () ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠFileOutputStream ( file ). use Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġlength Ġ= Ġ 0 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval ĠstartTime Ġ= ĠSystem Clock . uptime Millis () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġread Buffer Ġ= ĠShort Array ( buf Size ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġwrite Buffer Ġ= ĠByteArray ( buf Size Ġ* Ġ 2 ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhile Ġ( System Clock . uptime Millis () Ġ- ĠstartTime Ġ<= ĠA UDIO _ RECORD _ DURATION ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġret Ġ= Ġrecorder . read ( read Buffer , Ġ 0 , Ġread Buffer . size ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( ret Ġ> Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġoffset Ġ= Ġshort Array To ByteArray ( read Buffer , Ġwrite Buffer ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif ( offset Ġ> Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlength Ġ+= Ġoffset ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . write ( write Buffer ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif ( length Ġ<= Ġ 0 ) Ġthrow ĠIllegalStateException (" Record Ġfile Ġis Ġempty .") ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġentity = ĠRecord Entity ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsample Rate Ġ= ĠA UDIO _ SAMPLE _ RAT ES _ IN _ HZ , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġchannel Mask Ġ= Ġ" MON O ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġencoding Ġ= Ġ" PCM 1 6 BIT ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpath Ġ= Ġfile . absolute Path , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġduration Ġ= ĠA UDIO _ RECORD _ DURATION ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ). apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtimestamp Ġ= ĠSystem . currentTimeMillis () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġut c Offset Ġ= ĠUtils . utc Offset In Hour () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsubject Email Ġ= Ġemail ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġexperiment Uuid Ġ= Ġuuid ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġexperiment Group Ġ= Ġgroup ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis Uploaded Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠApp . box For < Record Entity >(). put ( entity ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" Box . put (" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" timestamp Ġ= Ġ${ entity . timestamp }, Ġsubject Email Ġ= Ġ${ entity . subject Email }, Ġexperiment Uuid Ġ= Ġ${ entity . experiment Uuid }, Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" experiment Group Ġ= Ġ${ entity . experiment Group }, Ġentity Ġ= Ġ$ entity )") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġrecorder . stop () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrecorder . release () ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠFile ( context . get External Files Dir ( null ), ĠfileName ). let Ġ{ Ġif ( it . exists ()) Ġit . delete () Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( ee : ĠException ) Ġ{ Ġ} ĊĠĠĠĠĠĠĠ Ġ} Ġfinally Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrecorder ?. stop () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrecorder ?. release () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠException ) Ġ{ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġshort Array To ByteArray ( short Array : ĠShort Array , ĠbyteArray : ĠByteArray , Ġis BigEndian : ĠBoolean Ġ= Ġtrue ): ĠInt Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( short Array . size Ġ* Ġ 2 Ġ> ĠbyteArray . size ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġ- 1 ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġvar Ġoffset Ġ= Ġ 0 ĊĠĠĠĠĠĠĠ Ġif Ġ( is BigEndian ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( i Ġin Ġ 0 Ġuntil Ġshort Array . size ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġoffset Ġ= Ġi Ġ* Ġ 2 Ġ+ Ġ 1 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠbyteArray [ i Ġ* Ġ 2 ] Ġ= Ġshort Array [ i ]. toInt (). and ( 0 xFF 0 0 ). shr ( 8 ). to Byte () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠbyteArray [ i Ġ* Ġ 2 Ġ+ Ġ 1 ] Ġ= Ġshort Array [ i ]. toInt (). and ( 0 x 0 0 FF ). to Byte () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( i Ġin Ġ 0 Ġuntil Ġshort Array . size ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġoffset Ġ= Ġi Ġ* Ġ 2 Ġ+ Ġ 1 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠbyteArray [ i Ġ* Ġ 2 ] Ġ= Ġshort Array [ i ]. toInt (). and ( 0 x 0 0 FF ). to Byte () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠbyteArray [ i Ġ* Ġ 2 Ġ+ Ġ 1 ] Ġ= Ġshort Array [ i ]. toInt (). and ( 0 xFF 0 0 ). shr ( 8 ). to Byte () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġoffset ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġval ĠREQUIRED _ PERMISSION S Ġ= ĠlistOf ( ĊĠĠĠĠĠĠĠĠĠĠĠ ĠManifest . permission . RECORD _ AUDIO , ĊĠĠĠĠĠĠĠĠĠĠĠ ĠManifest . permission . READ _ EXTERNAL _ STORAGE , ĊĠĠĠĠĠĠĠĠĠĠĠ ĠManifest . permission . WRITE _ EXTERNAL _ STORAGE ĊĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠMAX _ RE TR IES Ġ= Ġ 1 0 ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠA UDIO _ SAMPLE _ RAT ES _ IN _ HZ Ġ= Ġ 8 0 0 0 ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠA UDIO _ ENCODING Ġ= ĠAudio Format . ENCODING _ PCM _ 1 6 BIT ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠA UDIO _ CHANNEL Ġ= ĠAudio Format . CHANNEL _ IN _ MON O ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠA UDIO _ RECORD _ DURATION Ġ: ĠLong Ġ= Ġ 1 0 0 0 Ġ* Ġ 1 5 ĊĊĠĠĠĠĠĠĠ Ġval Ġstatus Ġ= ĠMutable LiveData < Status >(). apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpost Value ( Status . C ANCE LED ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĊĠĠĠĠĠĠĠ Ġprivate Ġval ĠTAG Ġ: ĠString Ġ= ĠAmb ient Sound Collector :: class . java . simple Name ĊĊĠĠĠĠĠĠĠ Ġfun Ġcheck Enable To Collect ( context : ĠContext ) Ġ= ĠPermission Utils . check Permission At Runtime ( context , ĠREQUIRED _ PERMISSION S ) ĊĠĠĠ Ġ} Ċ }