package Ġcom . sample . android . t mdb . ui . start Ċ Ċ import Ġandroid . app . Activity Ċ import Ġandroidx . appcompat . app . AppCompatActivity Ċ import Ġcom . google . android . play . core . app update . App Update ManagerFactory Ċ import Ġcom . google . android . play . core . install . Install State Updated Listener Ċ import Ġcom . google . android . play . core . install . model . App Update Type Ċ import Ġcom . google . android . play . core . install . model . Install Status Ċ import Ġcom . google . android . play . core . install . model . Update Availability Ċ import Ġcom . google . firebase . remote config . Firebase Remote Config Ċ import Ġcom . sample . android . t mdb . util . await Ċ import Ġkotlinx . coroutines . Comp letable Deferred Ċ import Ġkotlinx . coroutines . Timeout Cancellation Exception Ċ import Ġkotlinx . coroutines . with Timeout Ċ import Ġtim ber . log . Tim ber Ċ import Ġjavax . inject . Inject Ċ Ċ class ĠIn App Update Handler Ġ@ Inject Ġconstructor ( ĊĠĠĠ Ġprivate Ġval Ġactivity : ĠActivity Ċ ) Ġ{ ĊĊĠĠĠ Ġprivate Ġval Ġapp Update Manager Ġby Ġlazy Ġ{ ĠApp Update ManagerFactory . create ( activity . base Context ) Ġ} ĊĊĠĠĠ Ġsuspend Ġfun Ġensure Updated (): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ ĠTim ber . d (" Ens uring Ġapp Ġis Ġup Ġto Ġdate .") ĊĠĠĠĠĠĠĠ Ġval Ġapp Update Info Ġ= Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwith Timeout ( TIMEOUT _ M ILL IS ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġapp Update Manager . app Update Info . await () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( timeout : ĠTimeout Cancellation Exception ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . w (" Timed Ġout Ġwhen Ġgetting ĠApp Update Info .") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġtrue ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( throwable : ĠThrowable ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . w ( throwable , Ġ" Failed Ġto Ġget ĠApp Update Info .") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġtrue ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġwhen Ġ( app Update Info . update Availability ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠUpdate Availability . UPDATE _ AVAILABLE Ġ-> ĠUnit ĊĠĠĠĠĠĠĠĠĠĠĠ ĠUpdate Availability . DE VELO PER _ TRIGGER ED _ UPDATE _ IN _ PROGRESS Ġ-> ĠUnit ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . i (" No Ġupdate Ġavailable .") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġimmediate Ġ= Ġis Immediate Update () ĊĠĠĠĠĠĠĠ Ġval Ġupdate Type Ġ= Ġif Ġ( immediate ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . i (" Immediate Ġupdate Ġavailable .") ĊĠĠĠĠĠĠĠĠĠĠĠ ĠApp Update Type . IM MEDI ATE ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . i (" Flex ible Ġupdate Ġavailable .") ĊĠĠĠĠĠĠĠĠĠĠĠ ĠApp Update Type . FLEX IBLE ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġstarted Ġ= Ġapp Update Manager . start Update Flow For Result ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġapp Update Info , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġupdate Type , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġactivity , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( immediate ) ĠREQUEST _ CODE _ IM MEDI ATE Ġelse ĠREQUEST _ CODE _ FLEX IBLE , ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġif Ġ(! started ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . w (" Failed Ġto Ġstart Ġupdate Ġflow Ġfor Ġresult ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġtrue ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġsuspend Ġfun Ġcomplete Update ( request Code : ĠInt , ĠresultCode : ĠInt ): ĠCompletion Result Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġimmediate Ġ= Ġwhen Ġ( request Code ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠREQUEST _ CODE _ FLEX IBLE Ġ-> Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠ ĠREQUEST _ CODE _ IM MEDI ATE Ġ-> Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġreturn ĠCompletion Result . IN CORRECT _ REQUEST _ CODE ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġif Ġ( result Code Ġ== ĠAppCompatActivity . RESULT _ OK ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( immediate ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠCompletion Result . OK ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdownload And Install () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠCompletion Result . OK ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( immediate ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . w (" Immediate Ġupdate Ġnot Ġcompleted . ĠApp Ġis Ġblocked .") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠCompletion Result . BLOCK ED ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠCompletion Result . OK ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġsuspend Ġfun Ġdownload And Install () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġinstalled Ġ= ĠComp letable Deferred < Unit >() ĊĠĠĠĠĠĠĠ Ġval Ġlistener Ġ= ĠInstall State Updated Listener Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ( it . install Status ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠInstall Status . FAILED Ġ-> Ġinstalled . complete Exception ally ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠIllegalStateException (" Failed Ġto Ġdownload Ġupdate .") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠInstall Status . DOWN LOADED Ġ-> Ġinstalled . complete ( Unit ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġapp Update Manager . register Listener ( listener ) ĊĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġinstalled . await () ĊĠĠĠĠĠĠĠ Ġ} Ġfinally Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġapp Update Manager . unregister Listener ( listener ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġapp Update Manager . complete Update (). await () ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( throwable : ĠThrowable ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . w ( throwable , Ġ" Failed Ġto Ġinstall Ġupdate .") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġis Immediate Update (): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġremote Config Ġ= ĠFirebase Remote Config . getInstance () ĊĠĠĠĠĠĠĠ Ġval Ġmaximum Version For Immediate Update Ġ= Ġremote Config . getString Ġ(" maximum _ version _ for _ immediate _ update ") ĊĠĠĠĠĠĠĠ Ġif Ġ( maximum Version For Immediate Update . isNotEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcurrent Version Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ( activity . package Manager . get Package Info ( activity . packageName , Ġ 0 ). version Name ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . i (" current Ġversion Ġname : Ġ$ current Version ") ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . i (" maximum Ġversion Ġfor Ġimmediate Ġupdate : Ġ$ maximum Version For Immediate Update ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġcompare Semantic Versions ( current Version , Ġmaximum Version For Immediate Update ) Ġ<= Ġ 0 ĊĠĠĠĠĠĠĠ Ġ} Ġelse ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . w (" something 's Ġwrong Ġwith Ġgetting Ġ\" maximum _ version _ for _ immediate _ update \" Ġfrom Ġremote Ġconfig ") ĊĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġenum Ġclass ĠCompletion Result Ġ{ ĊĠĠĠĠĠĠĠ ĠIN CORRECT _ REQUEST _ CODE , ĊĠĠĠĠĠĠĠ ĠOK , ĊĠĠĠĠĠĠĠ ĠBLOCK ED , ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠTIME OUT _ M ILL IS Ġ= Ġ 5 0 0 0 L ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠREQUEST _ CODE _ FLEX IBLE Ġ= Ġ 1 0 0 ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠREQUEST _ CODE _ IM MEDI ATE Ġ= Ġ 2 0 0 ĊĊĠĠĠĠĠĠĠ Ġ/** ĊĠĠĠĠĠĠĠĠ Ġ* ĠComp ares Ġtwo Ġsemantic Ġversions . ĊĠĠĠĠĠĠĠĠ Ġ* ĠReturns Ġ- 1 Ġif Ġthe Ġfirst Ġversion Ġis Ġless Ġthan Ġthe Ġsecond . ĊĠĠĠĠĠĠĠĠ Ġ* ĠReturns Ġ 0 Ġif Ġthe Ġversions Ġare Ġidentical . ĊĠĠĠĠĠĠĠĠ Ġ* ĠReturns Ġ 1 Ġif Ġthe Ġfirst Ġversion Ġis Ġgreater Ġthan Ġthe Ġsecond . ĊĠĠĠĠĠĠĠĠ Ġ*/ ĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġcompare Semantic Versions ( a : ĠString , Ġb : ĠString ): ĠInt Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġa List Ġ= Ġa . split ('.') ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġb List Ġ= Ġb . split ('.') ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( i Ġin Ġ 0 Ġuntil ĠMath . max ( a List . size , Ġb List . size )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( a List . size Ġ< Ġi Ġ+ Ġ 1 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġ- 1 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( b List . size Ġ< Ġi Ġ+ Ġ 1 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġ 1 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġa Int Ġ= Ġa List [ i ]. toInt () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġb Int Ġ= Ġb List [ i ]. toInt () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( a Int Ġ< Ġb Int ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġ- 1 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( a Int Ġ> Ġb Int ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġ 1 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġ 0 ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ }