package Ġo uss aki . libs . rx kot l ind own loader Ċ Ċ import Ġandroid . content . Context Ċ import Ġandroid . util . Log Ċ import Ġandroid . util . Patterns Ċ import Ġio . reactivex . Observable Ċ import Ġio . reactivex . Observer Ċ import Ġio . reactivex . Single Ċ import Ġio . reactivex . android . schedul ers . Android Schedulers Ċ import Ġio . reactivex . schedul ers . Schedulers Ċ import Ġio . reactivex . subjects . Replay Subject Ċ import Ġokhttp 3 . Ok HttpClient Ċ import Ġokhttp 3 . Request Ċ import Ġjava . io . File Ċ import Ġjava . io . IOException Ċ import Ġjava . util .* Ċ import Ġjava . util . concurrent . TimeUnit Ċ Ċ /** Ċ Ġ* ĠCreated Ġby Ġo uss ama Ġab d all ah Ġ, ĠA KA Ġo uss aki Ġon Ġ 1 0 / 5 / 2 0 1 7 Ġ, Ġ 3 : 2 8 ĠPM . Ċ Ġ*/ Ċ class ĠRx Downloader Ġ{ ĊĠĠĠ Ġval ĠTAG : ĠString Ġ= Ġ" Rx Downloader " ĊĠĠĠ Ġprivate Ġvar Ġcanceled : ĠBoolean Ġ= Ġfalse ĊĠĠĠ Ġvar ĠORDER : ĠInt Ġ= ĠDownload Strategy . FLAG _ PAR ALLEL ĊĠĠĠ Ġprivate Ġvar Ġerrors : ĠInt Ġ= Ġ 0 ĊĠĠĠ Ġprivate Ġvar Ġsize : ĠInt Ġ= Ġ 0 ĊĠĠĠ Ġprivate Ġvar Ġremains : ĠInt Ġ= Ġ 0 ĊĠĠĠ Ġprivate Ġvar Ġdownloaded : ĠInt Ġ= Ġ 0 ĊĠĠĠ Ġvar Ġcontext : ĠContext ĊĠĠĠ Ġvar Ġclient : ĠOk HttpClient ĊĠĠĠ Ġvar ĠSTORAGE : ĠFile ĊĠĠĠ Ġvar ĠSTR ATE GY : ĠInt Ġ= ĠDownload Strategy . DEFAULT ĊĊĠĠĠ Ġprivate Ġvar Ġsubject : ĠRe play Subject < File Container > ĊĠĠĠ Ġprivate Ġvar Ġitems Observer : ĠItems Observer ĊĠĠĠ Ġprivate Ġvar Ġrx Storage : ĠRx Storage ĊĠĠĠ Ġ/* ĠActions Ġ*/ ĊĠĠĠ Ġprivate Ġlateinit Ġvar ĠonStart : Ġ() Ġ-> ĠUnit ĊĠĠĠ Ġprivate Ġlateinit Ġvar ĠonError : Ġ( e : ĠThrowable ) Ġ-> ĠUnit ĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġon Progress : Ġ( progress : ĠInt ) Ġ-> ĠUnit ĊĊĠĠĠ Ġprivate Ġlateinit Ġvar ĠonComplete With Success : Ġ() Ġ-> ĠUnit ĊĠĠĠ Ġprivate Ġlateinit Ġvar ĠonComplete WithError : Ġ() Ġ-> ĠUnit ĊĠĠĠ Ġprivate Ġvar Ġfiles : ĠMutable List < File Container > ĊĊĠĠĠ Ġfun ĠOn Progress x ( predicate : Ġ( progress : ĠInt ) Ġ-> ĠUnit ): ĠRx Downloader Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġthis ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġconstructor ( builder : ĠBuilder ) Ġ{ ĊĠĠĠĠĠĠĠ Ġthis . context Ġ= Ġbuilder . context ĊĠĠĠĠĠĠĠ Ġthis . client Ġ= Ġbuilder . client ĊĠĠĠĠĠĠĠ Ġthis . STR ATE GY Ġ= Ġbuilder . STR ATE GY ĊĠĠĠĠĠĠĠ Ġthis . files Ġ= ĠArrayList ( builder . files . size ) ĊĠĠĠĠĠĠĠ Ġthis . files . addAll ( builder . files ) ĊĠĠĠĠĠĠĠ Ġthis . STORAGE Ġ= Ġbuilder . STORAGE ĊĠĠĠĠĠĠĠ Ġthis . subject Ġ= ĠRe play Subject . create () ĊĠĠĠĠĠĠĠ Ġthis . rx Storage Ġ= Ġbuilder . rx Storage ĊĠĠĠĠĠĠĠ Ġthis . items Observer Ġ= ĠItems Observer ( rx Storage ) ĊĠĠĠĠĠĠĠ Ġthis . ORDER Ġ= Ġbuilder . ORDER ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠAction Ġto Ġbe Ġtaken Ġwhen Ġerror Ġthrown Ġfor Ġone Ġsingle Ġfile ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ param Ġaction ĊĠĠĠĠ Ġ* Ġ@ return ĠRx Downloader ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġdo On Each Single Error ( action : Ġ( e : ĠThrowable ) Ġ-> ĠUnit ): ĠRx Downloader Ġ{ ĊĠĠĠĠĠĠĠ Ġthis . onError Ġ= Ġaction ĊĠĠĠĠĠĠĠ Ġthis . items Observer . onError ( action ) ĊĠĠĠĠĠĠĠ Ġreturn Ġthis ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* Ġdo On Start Ġ: ĠAction Ġto Ġbe Ġtaken Ġbefore Ġstart Ġdownloading ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ param Ġaction ĊĠĠĠĠ Ġ* Ġ@ return ĠRx Downloader ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġdo On Start ( action : Ġ() Ġ-> ĠUnit ): ĠRx Downloader Ġ{ ĊĠĠĠĠĠĠĠ Ġthis . onStart Ġ= Ġaction ĊĠĠĠĠĠĠĠ Ġthis . items Observer . onStart ( action ) ĊĠĠĠĠĠĠĠ Ġreturn Ġthis ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* Ġdo On Complete With Success Ġ: ĠAction Ġto Ġbe Ġtaken Ġwhen Ġsuccessfully Ġfinish Ġdownloading Ġall Ġthe Ġfiles ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ param Ġaction ĊĠĠĠĠ Ġ* Ġ@ return ĠRx Downloader ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġdo On Complete With Success ( action : Ġ() Ġ-> ĠUnit ): ĠRx Downloader Ġ{ ĊĠĠĠĠĠĠĠ Ġthis . onComplete With Success Ġ= Ġaction ĊĠĠĠĠĠĠĠ Ġthis . items Observer . onComplete With Success ( action ) ĊĠĠĠĠĠĠĠ Ġreturn Ġthis ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* Ġdo On Complete WithError Ġ: ĠAction Ġto Ġbe Ġtaken Ġwhen Ġdownloading Ġends Ġwith Ġan Ġerror ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ param Ġaction ĊĠĠĠĠ Ġ* Ġ@ return ĠRx Downloader ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġdo On Complete WithError ( action : Ġ() Ġ-> ĠUnit ): ĠRx Downloader Ġ{ ĊĠĠĠĠĠĠĠ Ġthis . onComplete WithError Ġ= Ġaction ĊĠĠĠĠĠĠĠ Ġthis . items Observer . onComplete WithError ( action ) ĊĠĠĠĠĠĠĠ Ġreturn Ġthis ĊĠĠĠ Ġ} ĊĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* Ġdo On Progress ( int Ġprogress ) Ġ: ĠOn Ġdownloading Ġfiles ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ param Ġaction ĊĠĠĠĠ Ġ* Ġ@ return ĠRx Downloader ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġdo On Progress ( action : Ġ( progress : ĠInt ) Ġ-> ĠUnit ): ĠRx Downloader Ġ{ ĊĠĠĠĠĠĠĠ Ġthis . on Progress Ġ= Ġaction ĊĠĠĠĠĠĠĠ Ġthis . items Observer . on Progress ( action ) ĊĠĠĠĠĠĠĠ Ġreturn Ġthis ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠCheck Ġif ĠObject Ġis Ġnull Ġot Ġnot ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ param Ġobj ĊĠĠĠĠ Ġ* Ġ@ return Ġboolean ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġinternal Ġfun Ġis Null ( obj : ĠAny ?): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( obj Ġ== Ġnull ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLog . i ( TAG , Ġ" Object Ġis Ġnull ") ĊĠĠĠĠĠĠĠ Ġelse ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLog . i ( TAG , Ġ" Object Ġ" Ġ+ Ġobj . java Class . toString () Ġ+ Ġ" Ġis Ġnot Ġnull ") ĊĠĠĠĠĠĠĠ Ġreturn Ġobj Ġ== Ġnull ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/* ĊĠĠĠ Ġ* ĠPrint Ġthe Ġcurrent Ġthread Ġname . ĊĠĠĠ Ġ* Ġ*/ ĊĠĠĠ Ġprivate Ġfun Ġcurrent _ thread () Ġ{ ĊĠĠĠĠĠĠĠ ĠLog . e ( TAG , Ġ" Thread :" Ġ+ ĠThread . currentThread (). name ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠDownload Ġa Ġfile Ġfrom Ġusing Ġan ĠHTTP Ġclient ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ param Ġurl ĊĠĠĠĠ Ġ* Ġ@ return Ġbyte [] ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠ Ġinternal Ġfun Ġdownload File ( url : ĠString ): ĠByteArray Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġclient . new Call ( Request . Builder (). url ( url ). build ()). execute (). body (). bytes () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* Ġ@ param Ġbytes ĊĠĠĠĠ Ġ* Ġ@ param Ġempty Container ĊĠĠĠĠ Ġ* Ġ@ return ĠFile Container ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġinternal Ġfun Ġproduce File Container From Bytes ( bytes : ĠByteArray , Ġempty Container : ĠFile Container ): ĠFile Container Ġ{ ĊĠĠĠĠĠĠĠ Ġcurrent _ thread () Ċ // ĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" file Container Ġsuccess " Ġ+ Ġempty Container . is Suc ceed ) ĊĠĠĠĠĠĠĠ Ġif Ġ( c anceled Ġ&& Ġempty Container . is Suc ceed ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ/* ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ* ĠC anceled Ġfile Ġwant Ġbe Ġconsidered Ġas Ġdownloaded Ġfiles Ġ( ĠIgnore d Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ* Ġ*/ Ċ // ĠĠĠĠĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" empty Container . set Canceled ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġempty Container . is Canceled Ġ= Ġtrue Ġ// Ġto Ġhelp Ġfil tration Ġin ĠALL ĠStrategy ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġif Ġ( empty Container . is Suc ceed Ġ&& Ġ! c anceled ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġfilename Ġ= Ġempty Container . filename ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġfile Ġ= ĠFile ( STORAGE . toString () Ġ+ ĠFile . separator Ġ+ Ġfilename ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġprogress Ġ= Ġ 0 ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( size Ġ> Ġ 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprogress Ġ= ĠMath . abs ( remain s Ġ* Ġ 1 0 0 Ġ/ Ġsize Ġ- Ġ 1 0 0 ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġempty Container . Bytes ( bytes ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġempty Container . progress Ġ= Ġprogress ; ĊĠĠĠĠĠĠĠĠĠĠĠ Ġempty Container . file Ġ= Ġfile ; ĊĠĠĠĠĠĠĠ Ġ} Ċ // ĠĠĠĠĠĠĠ ĠLog . e ( TAG , Ġ" Empty Ġcontainer Ġreturn ") ĊĠĠĠĠĠĠĠ Ġreturn Ġempty Container ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* Ġ@ param Ġfile Container ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġfun Ġpublish Container ( file Container : ĠFile Container ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( file Container . is Suc ceed ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsubject . onNext ( file Container ) Ċ Ċ // ĠĠĠĠĠĠĠ ĠLog . e ( TAG , Ġ" publish Container Ġon Ġnext Ġsubject ") ĊĠĠĠĠĠĠĠ Ġif Ġ( remain s Ġ== Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( errors Ġ== Ġ 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis . items Observer . Complete With Success () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis . items Observer . Complete WithError () Ċ // ĠĠĠĠĠĠĠĠĠĠĠ ĠLog . i ( TAG , Ġremains . toString () Ġ+ Ġ" Ġi Ġwill Ġthrow Ġon Ġcomplete ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* Ġ@ param Ġbytes ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġfun Ġcatch Cancel ing ( bytes : ĠByteArray ) Ġ{ ĊĠĠĠĠĠĠĠ Ġ// Ġcancel Ġonly Ġif Ġthe Ġstrategy Ġis ĠALL Ġstrategy Ċ // ĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" catch Cancel ing Ġ Ġ" Ġ+ Ġ( bytes . size Ġ== Ġ 1 Ġ&& ĠSTR ATE GY Ġ== ĠDownload Strategy . ALL )) ĊĠĠĠĠĠĠĠ Ġif Ġ( bytes . size Ġ== Ġ 1 Ġ&& ĠSTR ATE GY Ġ== ĠDownload Strategy . ALL ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcanceled Ġ= Ġtrue ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* Ġ@ param Ġbytes ĊĠĠĠĠ Ġ* Ġ@ param Ġfile Container ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġfun Ġcatch Download Error ( bytes : ĠByteArray , Ġfile Container : ĠFile Container ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( bytes . size Ġ== Ġ 1 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġerrors ++ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfile Container . is Suc ceed Ġ= Ġfalse ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdownloaded ++ Ġ// Ġthis Ġvariable Ġis Ġonly Ġfor Ġtesting ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfile Container . is Suc ceed Ġ= Ġtrue ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġremains -- ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* Ġ@ param Ġfile Container ĊĠĠĠĠ Ġ* Ġ@ throws ĠIOException ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠ Ġprivate Ġfun Ġhandle Download Error ( file Container : ĠFile Container ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ(! file Container . is Suc ceed ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIOException (" Can Ġnot Ġdownload Ġthe Ġfile Ġ" Ġ+ Ġfile Container . filename ) ĊĠĠĠ Ġ} ĊĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠGet Ġan Ġobservable Ġof Ġone Ġfile Ġdown loader ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ param Ġfile Container ĊĠĠĠĠ Ġ* Ġ@ return ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġfun ĠObservable File Downloader ( file Container : ĠFile Container ): ĠObservable < File Container > Ġ{ ĊĠĠĠĠĠĠĠ Ġvar Ġobservable Ġ= ĠObservable ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. from Callable ({ Ġdownload File ( file Container . url ) Ġ}) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. onError Return ({ Ġthrowable Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠByteArray ( 1 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ}) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. subscribe On ( Schedulers . io ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. do On Next ({ Ġbytes Ġ-> Ġcatch Download Error ( bytes , Ġfile Container ) Ġ}) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. do On Next ({ Ġbytes Ġ-> Ġcatch Cancel ing ( bytes ) Ġ}) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. map ({ Ġbytes Ġ-> Ġproduce File Container From Bytes ( bytes , Ġfile Container ) Ġ}) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. observe On ( Android Schedulers . main Thread ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. do On Next ({ Ġfile Container Error Ġ-> Ġhandle Download Error ( file Container Error ) Ġ}) ĊĊĠĠĠĠĠĠĠ Ġif Ġ( STR ATE GY Ġ== ĠDownload Strategy . ALL ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġobservable Ġ= Ġall Strategy ( observable ) ĊĠĠĠĠĠĠĠ Ġelse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġobservable Ġ= Ġmax Strategy ( observable , Ġfile Container ) ĊĊĠĠĠĠĠĠĠ Ġreturn Ġobservable . do On Next ({ Ġfile Container On Next Ġ-> Ġpublish Container ( file Container On Next ) Ġ}) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. filter ({ Ġfile Container 1 Ġ-> Ġfile Container 1 . is Suc ceed Ġ&& Ġ! file Container 1 . is Canceled Ġ}) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* Ġ@ param Ġobservable ĊĠĠĠĠ Ġ* Ġ@ param Ġfile Container ĊĠĠĠĠ Ġ* Ġ@ return ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġfun Ġmax Strategy ( observable : ĠObservable < File Container >, Ġfile Container : ĠFile Container ): ĠObservable < File Container > Ġ{ ĊĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" Go ing Ġto Ġuse Ġmax Ġstrategy ") ĊĠĠĠĠĠĠĠ Ġreturn Ġobservable ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. do OnError ({ Ġthrowable Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠLog . d ( TAG , Ġ" do OnError ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis . items Observer . onError ( throwable ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ}) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. onError Return ({ Ġ_ Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠLog . d ( TAG , Ġ" onError Return ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfile Container ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ}) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* Ġ@ param Ġobservable ĊĠĠĠĠ Ġ* Ġ@ return ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġfun Ġall Strategy ( observable : ĠObservable < File Container >): ĠObservable < File Container > Ġ{ ĊĠĠĠĠĠĠĠ Ġ// Ġ ĠLog . d ( TAG , Ġ" Go ing Ġto Ġuse Ġall Ġstrategy ") ĊĠĠĠĠĠĠĠ Ġreturn Ġobservable ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. do OnError ({ Ġthrowable Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠĠ ĠLog . d ( TAG , Ġ" do OnError ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis . items Observer . onError ( throwable ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ}) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. onError Resume Next Ġ{ Ġobserver : ĠObserver < in ĠFile Container > Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠLog . d ( TAG , Ġ" onError Resume Next Ġall Ġstrategy ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġobserver . onComplete () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsubject . onComplete () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis . items Observer . Complete WithError () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠDownloading Ġfiles Ġse quent ially Ġusing Ġconcat Map ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ param Ġobservable ĊĠĠĠĠ Ġ* Ġ@ return ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġfun Ġsequential Downloading ( observable : ĠObservable < File Container >): ĠObservable < File Container > Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġobservable . concat Map ({ Ġfile Container Ġ-> ĠObservable File Downloader ( file Container ) Ġ}) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠDownloading Ġthe Ġfiles Ġin ĠParallel Ġusing ĠFlat Map ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ param Ġobservable ĊĠĠĠĠ Ġ* Ġ@ return ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġfun Ġparallel Downloading ( observable : ĠObservable < File Container >): ĠObservable < File Container > Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġobservable . flatMap ({ Ġfile Container Ġ-> ĠObservable File Downloader ( file Container ) Ġ}) ĊĠĠĠ Ġ} ĊĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠConverts Ġthe Ġdownloaded Ġfiles Ġto Ġbe Ġobservable Ġand Ġconsumed ĠReact ively ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ return ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġas List (): ĠSingle < List < File Container >> Ġ{ ĊĠĠĠĠĠĠĠ Ġthis . subject . subscribe ( this . items Observer ) ĊĠĠĠĠĠĠĠ Ġthis . size Ġ= Ġthis . files . size ĊĠĠĠĠĠĠĠ Ġthis . remain s Ġ= Ġthis . size ĊĠĠĠĠĠĠĠ Ġvar Ġobservable Ġ= ĠObservable ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. from Iterable ( this . files ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. observe On ( Android Schedulers . main Thread ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. subscribe On ( Schedulers . io ()) ĊĊĠĠĠĠĠĠĠ Ġif Ġ( this . ORDER Ġ== ĠDownload Strategy . FLAG _ PAR ALLEL ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġobservable Ġ= Ġparallel Downloading ( observable ) ĊĠĠĠĠĠĠĠ Ġelse Ġif Ġ( this . ORDER Ġ== ĠDownload Strategy . FLAG _ SEQUENTIAL ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġobservable Ġ= Ġsequential Downloading ( observable ) ĊĊĠĠĠĠĠĠĠ Ġreturn Ġobservable . toList () ĊĠĠĠ Ġ} ĊĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠBuilder ĠClass ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġclass ĠBuilder ĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* Ġ@ param Ġcontext ĠThe Ġcontext ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġ( internal Ġvar Ġcontext : ĠContext ) Ġ{ ĊĠĠĠĠĠĠĠ Ġinternal Ġvar Ġclient : ĠOk HttpClient ĊĠĠĠĠĠĠĠ Ġinternal Ġvar ĠSTR ATE GY : ĠInt Ġ= Ġ 0 ĊĠĠĠĠĠĠĠ Ġinternal Ġvar ĠORDER : ĠInt Ġ= Ġ 0 ĊĠĠĠĠĠĠĠ Ġinternal Ġvar ĠSTORAGE : ĠFile ĊĠĠĠĠĠĠĠ Ġinternal Ġvar Ġrx Storage : ĠRx Storage ĊĠĠĠĠĠĠĠ Ġ/** ĊĠĠĠĠĠĠĠĠ Ġ* ĠList Ġof Ġurl Ġto Ġbe Ġdownloaded ĊĠĠĠĠĠĠĠĠ Ġ*/ ĊĠĠĠĠĠĠĠ Ġinternal Ġvar Ġfiles : ĠMutable List < File Container > ĊĊĠĠĠĠĠĠĠ Ġinit Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠSTR ATE GY Ġ= ĠDownload Strategy . DEFAULT ĊĠĠĠĠĠĠĠĠĠĠĠ ĠORDER Ġ= ĠDownload Strategy . FLAG _ PAR ALLEL Ġ// Ġdefault Ġvalue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġclient Ġ= ĠOk HttpClient . Builder () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. connect Timeout ( 5 0 0 , ĠTimeUnit . MILLISECONDS ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. build () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfiles Ġ= ĠArrayList < File Container >() ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthis . STORAGE Ġ= Ġcontext . cacheDir ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthis . rx Storage Ġ= ĠRx Storage ( context ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġ ĠLog . i (" Rx Downloader ", Ġ" Builder ĠConstructor Ġcalled ") ĊĠĠĠĠĠĠĠ Ġ} ĊĊĊĠĠĠĠĠĠĠ Ġ/** ĊĠĠĠĠĠĠĠĠ Ġ* ĠSet Ġa Ġcustom ĠHttp ĠClient Ġ( Ok HttpClient Ġ) ĊĠĠĠĠĠĠĠĠ Ġ* ĊĠĠĠĠĠĠĠĠ Ġ* Ġ@ param Ġclient Ġand ĠOk Http Ġinstance ĊĠĠĠĠĠĠĠĠ Ġ* Ġ@ return ĠBuilder ĊĠĠĠĠĠĠĠĠ Ġ*/ ĊĠĠĠĠĠĠĠ Ġfun Ġclient ( client : ĠOk HttpClient ): ĠBuilder Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( client Ġ!= Ġnull ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis . client Ġ= Ġclient ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġthis ĊĠĠĠĠĠĠĠ Ġ} ĊĊĊĠĠĠĠĠĠĠ Ġ/** ĊĠĠĠĠĠĠĠĠ Ġ* ĠSet Ġthe Ġorder Ġof Ġdownloading Ġfiles ĊĠĠĠĠĠĠĠĠ Ġ* Ġit Ġcould Ġbe Ġparallel Ġor Ġsequential ĊĠĠĠĠĠĠĠĠ Ġ* ĊĠĠĠĠĠĠĠĠ Ġ* Ġ@ param Ġorder ĊĠĠĠĠĠĠĠĠ Ġ* Ġ@ return ĠBuilder ĊĠĠĠĠĠĠĠĠ Ġ*/ ĊĠĠĠĠĠĠĠ Ġfun ĠOrder ( order : ĠInt ): ĠBuilder Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠORDER Ġ= Ġorder ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġthis ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ/** ĊĠĠĠĠĠĠĠĠ Ġ* ĠSet Ġstrategy Ġfor Ġdownloading Ġfiles ĊĠĠĠĠĠĠĠĠ Ġ* Ġ( MAX Ġor ĠALL ) ĊĠĠĠĠĠĠĠĠ Ġ* ĊĠĠĠĠĠĠĠĠ Ġ* Ġ@ param Ġstrategy ĊĠĠĠĠĠĠĠĠ Ġ* Ġ@ return ĠBuilder ĊĠĠĠĠĠĠĠĠ Ġ*/ ĊĠĠĠĠĠĠĠ Ġfun Ġstrategy ( strategy : ĠInt ): ĠBuilder Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠSTR ATE GY Ġ= Ġstrategy ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġthis ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ/** ĊĠĠĠĠĠĠĠĠ Ġ* ĠAdd Ġa ĠURL Ġof Ġa Ġfile Ġto Ġthe Ġlist Ġof Ġdownloading ĊĠĠĠĠĠĠĠĠ Ġ* Ġand Ġrename Ġit Ġto Ġthe Ġgiven Ġname ĊĠĠĠĠĠĠĠĠ Ġ* ĊĠĠĠĠĠĠĠĠ Ġ* Ġ@ param ĠnewName ĊĠĠĠĠĠĠĠĠ Ġ* Ġ@ param Ġurl ĊĠĠĠĠĠĠĠĠ Ġ* Ġ@ return ĠBuilder ĊĠĠĠĠĠĠĠĠ Ġ*/ ĊĠĠĠĠĠĠĠ Ġfun Ġadd File ( new Name : ĠString , Ġurl : ĠString ): ĠBuilder Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( is Url ( url ) Ġ&& ĠnewName . indexOf (".") Ġ< Ġ 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfiles . add ( File Container ( url , ĠnewName Ġ+ ĠExtract Extension ( url ))) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġthis ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġis Url ( url : ĠString ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠPattern s . WEB _ URL . matcher ( url . toLowerCase ()). matches () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ/** ĊĠĠĠĠĠĠĠĠ Ġ* ĠExtract Ġthe Ġextension Ġof Ġfile Ġfrom Ġa Ġgiven ĠURL ĊĠĠĠĠĠĠĠĠ Ġ* ĊĠĠĠĠĠĠĠĠ Ġ* Ġ@ param Ġurl ĊĠĠĠĠĠĠĠĠ Ġ* Ġ@ return ĠBuilder ĊĠĠĠĠĠĠĠĠ Ġ*/ ĊĠĠĠĠĠĠĠ Ġprotected Ġfun ĠExtract Extension ( url : ĠString ): ĠString Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġurl . substring ( url . lastIndexOf (". ")) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ/** ĊĠĠĠĠĠĠĠĠ Ġ* Ġ Ù ı Extract Ġthe ĠName Ġand Ġextension Ġof Ġa Ġgiven Ġfile ĠURL ĊĠĠĠĠĠĠĠĠ Ġ* ĊĠĠĠĠĠĠĠĠ Ġ* Ġ@ param Ġurl ĊĠĠĠĠĠĠĠĠ Ġ* Ġ@ return ĠBuilder ĊĠĠĠĠĠĠĠĠ Ġ*/ ĊĠĠĠĠĠĠĠ Ġprotected Ġfun ĠExtract Name And Extension ( url : ĠString ): ĠString Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġurl . substring ( url . lastIndexOf ("/") Ġ+ Ġ 1 ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĊĠĠĠĠĠĠĠ Ġ/** ĊĠĠĠĠĠĠĠĠ Ġ* ĠAdd Ġfile Ġto Ġdownloading Ġlist ĊĠĠĠĠĠĠĠĠ Ġ* ĊĠĠĠĠĠĠĠĠ Ġ* Ġ@ param Ġurl ĊĠĠĠĠĠĠĠĠ Ġ* Ġ@ return ĠBuilder ĊĠĠĠĠĠĠĠĠ Ġ*/ ĊĠĠĠĠĠĠĠ Ġfun Ġadd File ( url : ĠString ): ĠBuilder Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( is Url ( url )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfiles . add ( File Container ( url Ġ= Ġurl , Ġfilename Ġ= ĠExtract Name And Extension ( url ))) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġthis ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ/** ĊĠĠĠĠĠĠĠĠ Ġ* ĠSet Ġthe Ġstorage Ġtype Ġto Ġsave Ġfiles Ġin ĊĠĠĠĠĠĠĠĠ Ġ* ĊĠĠĠĠĠĠĠĠ Ġ* Ġ@ param Ġstorage Path ĊĠĠĠĠĠĠĠĠ Ġ* Ġ@ return ĠBuilder ĊĠĠĠĠĠĠĠĠ Ġ*/ ĊĠĠĠĠĠĠĠ Ġfun Ġstorage ( storage Path : ĠFile ): ĠBuilder Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( storage Path Ġ!= Ġnull ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis . STORAGE Ġ= Ġstorage Path ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġthis ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ/** ĊĠĠĠĠĠĠĠĠ Ġ* ĠAdd ĠBulk Ġof Ġfiles Ġto Ġthe ĠList Ġof Ġfiles ĊĠĠĠĠĠĠĠĠ Ġ* ĊĠĠĠĠĠĠĠĠ Ġ* Ġ@ param Ġurls ĊĠĠĠĠĠĠĠĠ Ġ* Ġ@ return ĠBuilder ĊĠĠĠĠĠĠĠĠ Ġ*/ ĊĠĠĠĠĠĠĠ Ġfun Ġadd Files ( urls : ĠList < String >): ĠBuilder Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġurls . forEach Ġ{ Ġfiles . add ( File Container ( it , ĠExtract Name And Extension ( it ))) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġthis ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfun Ġbuild (): ĠRx Downloader Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠRx Downloader ( builder Ġ= Ġthis ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊ Ċ }