/* Ċ Ġ* ĠCopyright Ġ( c ) Ġ 2 0 1 9 ĠApp li very Ċ Ġ* Ċ Ġ* Ġ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 Ċ Ġ* Ċ Ġ* Ġhttp :// 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 . app li very . updates Ċ Ċ import Ġandroid . app . Intent Service Ċ import Ġandroid . app . Notification Channel Ċ import Ġandroid . app . Notification Manager Ċ import Ġandroid . content . Context Ċ import Ġandroid . content . Intent Ċ import Ġandroid . os . Build Ċ import Ġandroidx . core . app . Notification Compat Ċ import Ġcom . app li very . base . App li very DataManager Ċ import Ġcom . app li very . base . util . App li very Log Ċ import Ġcom . app li very . data . App li very ApiService Ċ import Ġcom . app li very . data . Download ApiService Ċ import Ġcom . app li very . data . response . Api Build Token Ċ import Ġcom . app li very . data . response . LIMIT _ EX CE EDED _ ERROR Ċ import Ġcom . app li very . data . response . Server Response Ċ import Ġcom . app li very . updates . domain . Download Info Ċ import Ġcom . app li very . updates . util . A pk Installer Ċ import Ġcom . google . gson . Gson Ċ import Ġcom . google . gson . Json Syntax Exception Ċ import Ġokhttp 3 . ResponseBody Ċ import Ġretrofit 2 . Response Ċ import Ġjava . io . File Ċ import Ġjava . io . IOException Ċ Ċ private Ġconst Ġval ĠNOT IFICATION _ CHANNEL _ ID Ġ= Ġ" NOTIFICATION _ CHANNEL _ 8 7 2 3 4 " Ċ private Ġconst Ġval ĠNOT IFICATION _ ID Ġ= Ġ 0 x 2 1 Ċ private Ġconst Ġval ĠMAX _ PROGRESS Ġ= Ġ 1 0 0 Ċ Ċ class ĠDownload Service Ġ: ĠIntent Service (" Download Ġapk Ġservice ") Ġ{ ĊĊĠĠĠ Ġprivate Ġvar Ġnotification Builder : ĠNotification Compat . Builder ? Ġ= Ġnull ĊĠĠĠ Ġprivate Ġvar Ġnotification Manager : ĠNotification Manager ? Ġ= Ġnull ĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġfile Manager : ĠFile Manager ĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġdownload ApiService : ĠDownload ApiService ĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġapi Service : ĠApp li very ApiService ĊĊĠĠĠ Ġoverride Ġfun Ġon Handle Intent ( intent : ĠIntent ?) Ġ{ ĊĠĠĠĠĠĠĠ ĠApp li very DataManager . app Data ?. run Ġ{ ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġis Download Started Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfile Manager Ġ= ĠFile Manager ( application Context ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġapi Service Ġ= ĠApp li very ApiService . getInstance () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdownload ApiService Ġ= ĠDownload ApiService . getInstance () ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġapk FileName Ġ= Ġname . replace (" Ġ", Ġ"- ") Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"-" Ġ+ Ġapp Config . last Build Id Ġ+ Ġ". apk " ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠTODO Ġcheck Ġif Ġfile Ġexits ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbuild Token Ġ= Ġget Build Token ( app Config . last Build Id ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( build Token . isNotEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġinit Download ( name , Ġapk FileName , Ġbuild Token ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} Ġ?: Ġalso Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġis Download Started Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠ ĠApp li very Log . error (" The Ġdownload Ġcannot Ġbe Ġstarted Ġwith Ġnull Ġapp Ġdata ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġget Build Token ( build Id : ĠString ): ĠString Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġtoken Response : ĠResponse < Server Response < Api Build Token >> Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġapi Service . obtain Build Token ( build Id ). execute () ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( token Response . is Successful ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtoken Response . body ()?. data ?. token Ġas ĠString ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġhandle Error ( token Response ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"" ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠIOException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠApp li very Log . error (" Cannot Ġget Ġthe Ġbuild Ġtoken ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ"" ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġhandle Error ( response : ĠResponse < Server Response < Api Build Token >>) Ġ{ ĊĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġerror Ġ= ĠGson (). fromJson < Server Response < Api Build Token >>( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresponse . error Body ()?. string (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠServer Response :: class . java ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ). error ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( error . code Ġ== ĠLIMIT _ EX CE EDED _ ERROR ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġlimit Ġ= Ġerror . data ?. get (" limit ") Ġ?: Ġ"- 1 " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠApp li very Log . error (" Install ations Ġlimit Ġexceeded . ĠLimit : Ġ$ limit / month ") ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠApp li very Log . error (" Cannot Ġget Ġthe Ġbuild Ġtoken . Ġ${ error . message }") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( exception : ĠJson Syntax Exception ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠApp li very Log . error (" Cannot Ġget Ġthe Ġbuild Ġtoken . ĠInvalid Ġconfig ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġinit Download ( appName : ĠString , Ġapk FileName : ĠString , Ġbuild Token : ĠString ) Ġ{ ĊĠĠĠĠĠĠĠ Ġshow Notification ( appName ) ĊĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġrequest Ġ= Ġdownload ApiService . download Build ( build Token ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrequest . execute (). body ()?. run Ġ{ Ġdownload File ( apk FileName , Ġthis ) Ġ} ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠIOException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnotification Manager ?. cancel ( 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠApp li very Log . error (" Error Ġdownloading Ġapk ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠ Ġprivate Ġfun Ġdownload File ( apk FileName : ĠString , Ġbody : ĠResponse Body ) Ġ{ ĊĊĠĠĠĠĠĠĠ Ġval ĠoutputFile Ġ= Ġif Ġ( Build . VERSION . SDK _ INT Ġ>= ĠBuild . VERSION _ CODES . N ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠFile ( cacheDir , Ġapk FileName ) ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠFile ( files Dir , Ġapk FileName ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfile Manager . write ResponseBody To Disk ( body Ġ= Ġbody , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfile Ġ= ĠoutputFile , ĊĠĠĠĠĠĠĠĠĠĠĠ ĠonUpdate Ġ= Ġ{ Ġdownload Info Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġupdate Progress ( download Info ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠProgress Listener . download Info Ġ= Ġdownload Info ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}, ĊĠĠĠĠĠĠĠĠĠĠĠ Ġon Finish Ġ= Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠProgress Listener . on Finish ?. invoke () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis Download Started Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġon Download Complete ( outputFile . path ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}, ĊĠĠĠĠĠĠĠĠĠĠĠ ĠonError Ġ= Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis Download Started Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠApp li very Log . error (" Error Ġsaving Ġapk ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġshow Notification ( appName : ĠString ) Ġ{ ĊĠĠĠĠĠĠĠ Ġcreate Notification Channel () ĊĠĠĠĠĠĠĠ Ġnotification Manager Ġ= Ġget System Service ( Context . NOTIFICATION _ SERVICE ) Ġas ĠNotification Manager ĊĊĠĠĠĠĠĠĠ Ġnotification Builder Ġ= ĠNotification Compat . Builder ( this , ĠNOT IFICATION _ CHANNEL _ ID ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. set Small Icon ( R . drawable . ic _ app li very _ blue ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. setContent Title ( getString ( R . string . app li very _ updates _ app _ name )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. setContent Text ( getString ( R . string . app li very _ updates _ notification _ text , ĠappName )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. setAuto Cancel ( false ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. set O ngo ing ( true ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. set Sound ( null ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. set V ibrate ( null ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. set Progress ( MAX _ PROGRESS , Ġ 0 , Ġtrue ) ĊĠĠĠĠĠĠĠ Ġnotification Manager ?. notify ( NOTIFICATION _ ID , Ġnotification Builder ?. build ()) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġupdate Progress ( download Info : ĠDownload Info ) Ġ{ ĊĠĠĠĠĠĠĠ Ġnotification Builder ?. set Progress ( MAX _ PROGRESS , Ġdownload Info . progress , Ġfalse ) ĊĠĠĠĠĠĠĠ Ġnotification Builder ?. setContent Text ( ĊĠĠĠĠĠĠĠĠĠĠĠ ĠgetString ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠR . string . app li very _ updates _ notification _ progress , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdownload Info . current FileSize , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdownload Info . total FileSize ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġnotification Manager ?. notify ( NOTIFICATION _ ID , Ġnotification Builder !!. build ()) ĊĊĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġon Download Complete ( filePath : ĠString ) Ġ{ ĊĠĠĠĠĠĠĠ Ġnotification Manager ?. cancel ( NOTIFICATION _ ID ) ĊĠĠĠĠĠĠĠ ĠA pk Installer . install Application ( this , ĠfilePath ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġon Task Removed ( root Intent : ĠIntent ) Ġ{ ĊĠĠĠĠĠĠĠ Ġnotification Manager ?. cancel ( NOTIFICATION _ ID ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġcreate Notification Channel () Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( Build . VERSION . SDK _ INT Ġ>= ĠBuild . VERSION _ CODES . O ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġname Ġ= ĠgetString ( R . string . app li very _ updates _ channel _ name ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdescription Ġ= ĠgetString ( R . string . app li very _ updates _ channel _ description ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġimportance Ġ= ĠNotification Manager . IMPORT ANCE _ DEFAULT ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġchannel Ġ= ĠNotification Channel ( NOTIFICATION _ CHANNEL _ ID , Ġname , Ġimportance ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġchannel . set Sound ( null , Ġnull ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġchannel . enable V ibration ( false ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġchannel . description Ġ= Ġdescription ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnotification Manager Ġ= Ġget System Service ( Notification Manager :: class . java ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnotification Manager !!. create Notification Channel ( channel ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġprivate Ġvar Ġis Download Started Ġ= Ġfalse ĊĊĠĠĠĠĠĠĠ Ġfun Ġstart Download Service ( context : ĠContext ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! is Download Started ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġintent Ġ= ĠIntent ( context , ĠDownload Service :: class . java ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontext . start Service ( intent ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ