package Ġdan b roid . ipfs d . client Ċ Ċ import Ġandroid . app . Activity Ċ import Ġandroid . app . AlertDialog Ċ import Ġandroid . content . Component Name Ċ import Ġandroid . content . Context Ċ import Ġandroid . content . Service Connection Ċ import Ġandroid . content . pm . PackageManager Ċ import Ġandroid . os . Handler Ċ import Ġandroid . os . IB inder Ċ import Ġandroid . os . Looper Ċ import Ġandroid . os . Messenger Ċ import Ġandroidx . annotation . MainThread Ċ import Ġandroidx . lifecycle . LiveData Ċ import Ġandroidx . lifecycle . Mutable LiveData Ċ import Ġandroidx . lifecycle . as Flow Ċ import Ġdan b roid . ipfs d . IP F SD Ċ import Ġkotlinx . coroutines . Dispatch ers Ċ import Ġkotlinx . coroutines . flow . filter Ċ import Ġkotlinx . coroutines . flow . first Ċ import Ġkotlinx . coroutines . flow . flow On Ċ import Ġkotlinx . coroutines . with Context Ċ import Ġjava . lang . ref . Weak Reference Ċ Ċ /** Ċ Ġ* Ċ Ġ*/ Ċ open Ġclass ĠService Client ( val Ġcontext : ĠContext ) Ġ{ ĊĊĠ Ġenum Ġclass ĠConnection State Ġ{ ĊĠĠĠ ĠDIS CONNECTED , ĠCONNECT ING , ĠCONNECT ED , ĠSTART ED ; ĊĠ Ġ} ĊĊĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠ Ġ@ Volatile ĊĠĠĠ Ġprivate Ġvar Ġinstance : ĠWeak Reference < ServiceClient >? Ġ= Ġnull ĊĊĠĠĠ Ġ@ Jvm Static ĊĠĠĠ Ġfun ĠgetInstance ( context : ĠContext ) Ġ= Ġinstance ?. get () Ġ?: Ġsynchronized ( ServiceClient :: class . java ) Ġ{ ĊĠĠĠĠĠ Ġinstance ?. get () Ġ?: ĠService Client ( context ). also Ġ{ ĊĠĠĠĠĠĠĠ Ġinstance Ġ= ĠWeak Reference ( it ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġprivate Ġvar Ġservice Is Installed Ġ= Ġfalse ĊĊĠ Ġfun Ġis Service Installed ( re check : ĠBoolean Ġ= Ġfalse ): ĠBoolean Ġ{ ĊĠĠĠ Ġif Ġ( service Is Installed Ġ&& Ġ! re check ) Ġreturn Ġtrue ĊĊĠĠĠ Ġrun Catch ing Ġ{ ĊĠĠĠĠĠ Ġcontext . package Manager . get Package Info ( IP F SD . SERVICE _ PKG , ĠPackage Manager . GET _ META _ DATA ). also Ġ{ ĊĠĠĠĠĠĠĠ Ġlog . info (" service Ġversion Name :${ it . version Name }") ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ}. on Success Ġ{ ĊĠĠĠĠĠ Ġservice Is Installed Ġ= Ġtrue ĊĠĠĠ Ġ}. on Failure Ġ{ ĊĠĠĠĠĠ Ġservice Is Installed Ġ= Ġfalse ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn Ġservice Is Installed ĊĠ Ġ} ĊĊĠ Ġprivate Ġval Ġ_ connection State : ĠMutable LiveData < Connection State > Ġ= ĊĠĠĠ Ġobject Ġ: ĠMutable LiveData < Connection State >( Connection State . DIS CONNECTED ) Ġ{ ĊĠĠĠĠĠ Ġoverride Ġfun Ġon Active () Ġ{ ĊĠĠĠĠĠĠĠ Ġconnect () ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠ Ġval Ġconnection State : ĠLive Data < Connection State > Ġ= Ġ_ connection State ĊĊĠ Ġsuspend Ġfun Ġwait T ill Started () Ġ{ ĊĠĠĠ Ġif Ġ( connection State . value Ġ!= ĠConnection State . STARTED ) Ġ{ ĊĠĠĠĠĠ Ġlog . debug (" not Ġconnected Ġ.. Ġwaiting Ġfor Ġflow Ġ.. ") ĊĠĠĠĠĠ Ġconnection State . as Flow (). filter Ġ{ Ġit Ġ== ĠConnection State . STARTED Ġ}. first () ĊĠĠĠĠĠ Ġlog . debug (" finished Ġwaiting Ġfor Ġflow Ġwith Ġstate Ġ${ connection State . value }") ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġprivate Ġval Ġmessage Callback Ġ= ĠHandler . Callback Ġ{ ĊĊĠĠĠ Ġval Ġmsg Ġ= Ġit . to IP FS Message ( this @ ServiceClient . java Class . class Loader !! ) ĊĠĠĠ Ġlog . debug (" in Message : Ġ$ msg ") ĊĊĠĠĠ Ġwhen Ġ( msg ) Ġ{ ĊĠĠĠĠĠ ĠIP FS Message . SERVICE _ STARTED Ġ-> Ġ{ ĊĠĠĠĠĠĠĠ Ġ_ connection State . value Ġ= ĠConnection State . STARTED ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ ĠIP FS Message . SERVICE _ STOP PING Ġ-> Ġ{ ĊĠĠĠĠĠĠĠ Ġlog . warn (" SERVICE ĠSTO PP ING ") ĊĠĠĠĠĠĠĠ Ġdisconnect () ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġis ĠIP FS Message . BAND WIDTH Ġ-> Ġ{ ĊĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġelse Ġ-> Ġlog . error (" un handled Ġmessage : Ġ$ msg ") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġtrue ĊĠ Ġ} ĊĊĠ Ġprivate Ġval Ġmessage Handler Ġ= ĠHandler ( Looper . get Main Looper (), Ġmessage Callback ) ĊĊĠ Ġprivate Ġval Ġin Messenger Ġ= ĠMess enger ( message Handler ) ĊĊĠ Ġprivate Ġvar Ġout Messenger : ĠMess enger ? Ġ= Ġnull ĊĊĠ Ġprivate Ġval Ġservice Connection Ġ= ĠIP FS Service Connection () ĊĊĠ Ġ@ MainThread ĊĠ Ġfun Ġconnect () Ġ{ ĊĠĠĠ Ġlog . error (" connect () Ġstate : Ġ${ _ connection State . value }") ĊĠĠĠ Ġif Ġ(_ connection State . value Ġ== ĠConnection State . DIS CONNECTED ) Ġ{ ĊĠĠĠĠĠ Ġlog . debug (" connecting Ġ.. ") ĊĠĠĠĠĠ Ġ_ connection State . value Ġ= ĠConnection State . CONNECT ING ĊĊĠĠĠĠĠ Ġlog . warn (" binding Ġto Ġservice Ġ.. ") ĊĠĠĠĠĠ Ġcontext . bind Service ( ĊĠĠĠĠĠĠĠ ĠIP F SD . intent . service _ intent , ĊĠĠĠĠĠĠĠ Ġservice Connection , ĊĠĠĠĠĠĠĠ ĠContext . BIND _ AUTO _ CREATE ĊĠĠĠĠĠ Ġ) ĊĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġfun Ġdisconnect () Ġ{ ĊĠĠĠ Ġlog . info (" disconnect () Ġconnection State : Ġ${ _ connection State . value }") ĊĠĠĠ Ġmessage Handler . remove Callbacks And Messages ( null ) ĊĊĠĠĠ Ġif Ġ(_ connection State . value Ġ!= ĠConnection State . DIS CONNECTED ) Ġ{ ĊĠĠĠĠĠ Ġout Messenger ?. send ( IP FS Message . CLIENT _ DIS CONNECT . to Message ()) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġif Ġ(_ connection State . value Ġ!= ĠConnection State . DIS CONNECTED Ġ&& Ġ_ connection State . value Ġ!= ĠConnection State . DIS CONNECTED ) Ġ{ ĊĠĠĠĠĠ Ġ// ĠsendMessage ( Register Event . UN REGISTER ) ĊĠĠĠĠĠ Ġlog . trace (" un binding Ġservice Ġ.. ") ĊĠĠĠĠĠ Ġcontext . unbind Service ( service Connection ) ĊĠĠĠ Ġ} ĊĠĠĠ Ġ_ connection State . post Value ( Connection State . DIS CONNECTED ) ĊĊĠ Ġ} ĊĊĠ Ġprotected Ġfun Ġfinalize () Ġ{ ĊĠĠĠ Ġlog . debug (" finalize () ") ĊĠĠĠ Ġdisconnect () ĊĠ Ġ} ĊĊĊĠ Ġprivate Ġvar Ġcall Count Ġ= Ġ 0 ĊĊĠ Ġ@ MainThread ĊĠ Ġfun Ġincrement Call Count () Ġ{ ĊĠĠĠ Ġcall Count ++ ĊĠĠĠ Ġlog . trace (" call Count : Ġ$ call Count ") ĊĠĠĠ Ġconnect () ĊĠ Ġ} ĊĊĠ Ġ@ MainThread ĊĠ Ġfun Ġdecrement Call Count () Ġ{ ĊĠĠĠ Ġcall Count -- ĊĠĠĠ Ġlog . trace (" call Ġcomplete : Ġ$ call Count ") ĊĠ Ġ} ĊĊĠ Ġsuspend Ġfun Ġ< T > Ġrun When Connected ( job : Ġsuspend Ġ() Ġ-> ĠT ) Ġ{ ĊĊĠĠĠ Ġwith Context ( Dispatch ers . Main ) Ġ{ ĊĠĠĠĠĠ Ġlog . trace (" run When Connected () ") ĊĠĠĠĠĠ Ġrun Catch ing Ġ{ ĊĠĠĠĠĠĠĠ Ġincrement Call Count () ĊĊĊĠĠĠĠĠĠĠ Ġif Ġ( connection State . value Ġ!= ĠConnection State . STARTED ) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġlog . trace (" waiting Ġto Ġbe Ġconnected Ġ.. ") ĊĠĠĠĠĠĠĠĠĠ Ġconnection State . as Flow (). flow On ( Dispatch ers . IO ). filter Ġ{ Ġit Ġ== ĠConnection State . STARTED Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. first () ĊĠĠĠĠĠĠĠĠĠ Ġlog . trace (" connection Ġstate : Ġ${ connection State . value }") ĊĠĠĠĠĠĠĠ Ġ} ĊĊĊĠĠĠĠĠĠĠ Ġif Ġ( connection State . value Ġ== ĠConnection State . STARTED ) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġ// ĠsendMessage ( IP FS Message . TIMEOUT _ RESET ) ĊĠĠĠĠĠĠĠĠĠ Ġjob . invoke () ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġthrow ĠIllegalStateException (" Failed Ġto Ġconnect ") ĊĊĠĠĠĠĠ Ġ}. also Ġ{ ĊĠĠĠĠĠĠĠ Ġdecrement Call Count () ĊĠĠĠĠĠĠĠ Ġit . exception OrNull ()?. also Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġlog . error ( it . message , Ġit ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĊĠ Ġsuspend Ġfun ĠsendMessage ( msg : ĠIP FS Message ) Ġ= Ġrun When Connected Ġ{ ĊĠĠĠ Ġout Messenger ?. send ( msg . to Message ()) ĊĠ Ġ} ĊĊĊĠ Ġprotected Ġinner Ġclass ĠIP FS Service Connection Ġ: ĠService Connection Ġ{ ĊĊĠĠĠ Ġoverride Ġfun Ġon Binding Di ed ( name : ĠComponent Name ?) Ġ{ ĊĠĠĠĠĠ Ġlog . warn (" on Bind ind Di ed () Ġname :$ name ") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġon Service Connected ( name : ĠComponent Name , Ġservice : ĠI Binder ) Ġ{ ĊĠĠĠĠĠ Ġlog . info (" on Service Connected () ") ĊĠĠĠĠĠ Ġout Messenger Ġ= ĠMess enger ( service ) ĊĠĠĠĠĠ Ġ_ connection State . value Ġ= ĠConnection State . CONNECTED ĊĊĠĠĠĠĠ Ġlog . debug (" sending ĠCLIENT _ CONNECT ") ĊĠĠĠĠĠ Ġout Messenger ?. send ( IP FS Message . CLIENT _ CONNECT . to Message ( in Messenger )) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġon Service Disconnected ( name : ĠComponent Name ) Ġ{ ĊĠĠĠĠĠ Ġlog . warn (" on Service Disconnected () ") ĊĠĠĠĠĠ Ġ_ connection State . value Ġ= ĠConnection State . DIS CONNECTED ĊĠĠĠĠĠ Ġout Messenger Ġ= Ġnull ĊĠĠĠĠĠ Ġconnect () ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊ Ċ } ĊĊ Ċ // TODO Ġadd Ġlink Ġto Ġinstall Ġthe Ġip fs d Ġservice Ġapp ĊĊ Ċ internal Ġfun Ġshow IP F SD Not Installed Dialog ( context : ĠContext ) Ġ{ ĊĠ ĠAlertDialog . Builder ( context ) ĊĠĠĠ Ġ. setTitle ( android . R . string . dialog _ alert _ title ) ĊĠĠĠ Ġ. setMessage ( R . string . msg _ ipfs d _ not _ installed ) ĊĠĠĠ Ġ. set Positive Button ( android . R . string . ok ) Ġ{ Ġ_, Ġ_ Ġ-> ĊĠĠĠĠĠ Ġif Ġ( context Ġis ĠActivity ) ĊĠĠĠĠĠĠĠ Ġcontext . finish () ĊĠĠĠ Ġ} ĊĠĠĠ Ġ. setOn Dismiss Listener Ġ{ ĊĠĠĠĠĠ Ġif Ġ( context Ġis ĠActivity ) ĊĠĠĠĠĠĠĠ Ġcontext . finish () ĊĠĠĠ Ġ}. show () Ċ Ċ } Ċ Ċ val ĠContext . ipfs ServiceClient : ĠService Client ĊĠ Ġget () Ġ= ĠService Client . getInstance ( this ) Ċ Ċ private Ġval Ġlog Ġ= Ġdan b roid . logging . getLog ( ServiceClient :: class ) ĊĊ