package Ġcom . x ently . payment čĊč Ċ import Ġandroid . annotation . Suppress Lint č Ċ import Ġcom . x ently . payment . utils . Constants . connect TO č Ċ import Ġcom . x ently . payment . utils . Constants . read TO č Ċ import Ġcom . x ently . payment . utils . Constants . write TO č Ċ import Ġcom . x ently . payment . utils . JSON _ CONVER TER č Ċ import Ġcom . x ently . payment . utils . Log č Ċ import Ġcom . x ently . payment . utils . web . Headers č Ċ import Ġcom . x ently . payment . utils . web . Server Response č Ċ import Ġcom . x ently . payment . utils . web . Task Result č Ċ import Ġkotlinx . coroutines . Dispatch ers č Ċ import Ġkotlinx . coroutines . with Context č Ċ import Ġokhttp 3 . Interceptor č Ċ import Ġokhttp 3 . Ok HttpClient č Ċ import Ġokhttp 3 . ResponseBody č Ċ import Ġokhttp 3 . logging . Http Logging Interceptor č Ċ import Ġretrofit 2 . Response č Ċ import Ġretrofit 2 . Ret rofit č Ċ import Ġretrofit 2 . converter . gson . Gson Converter Factory č Ċ import Ġjava . io .* č Ċ import Ġjava . util .* č Ċ import Ġjava . util . concurrent . TimeUnit čĊč Ċ object ĠWeb Service Builder Ġ{ čĊčĊĠĠĠ Ġval ĠLOG _ TAG Ġ= ĠWeb Service Builder :: class . java . simple Name čĊĠĠĠ Ġprivate Ġconst Ġval ĠBASE _ URL : ĠString Ġ= Ġ" http :// 1 0 . 0 . 2 . 2 : 8 0 0 0 /" čĊčĊĠĠĠ Ġprivate Ġval Ġlogging Interceptor Ġ= ĠHttp Logging Interceptor () čĊĠĠĠĠĠĠĠ Ġ. apply Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠ Ġlevel Ġ= Ġ( if Ġ( Build Config . DEBUG ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠHttp Logging Interceptor . Level . BODY čĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse ĠHttp Logging Interceptor . Level . NONE ) čĊĠĠĠĠĠĠĠĠĠĠĠ Ġred act Header ( Headers . AUTHORIZATION ) Ġ Ġ// ĠPre vents Ġheader Ġcontent Ġlogging čĊĠĠĠĠĠĠĠĠĠĠĠ Ġred act Header ( Headers . DEVICE _ IP _ ADDRESS ) čĊĠĠĠĠĠĠĠĠĠĠĠ Ġred act Header ( Headers . DEVICE _ ID ) čĊĠĠĠĠĠĠĠĠĠĠĠ Ġred act Header ( Headers . DEVICE _ TOKEN ) čĊĠĠĠĠĠĠĠĠĠĠĠ Ġred act Header ( Headers . COOKIE ) čĊĠĠĠĠĠĠĠ Ġ} čĊčĊĠĠĠ Ġ@ Suppress Lint (" Constant Locale ") čĊĠĠĠ Ġprivate Ġval Ġheader Interceptor Ġ= ĠInter ceptor Ġ{ Ġchain Ġ-> čĊĠĠĠĠĠĠĠ Ġval Ġrequest Ġ= Ġchain . request (). newBuilder () čĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. add Header ( Headers . DEVICE _ IP _ ADDRESS , Ġ" 1 2 7 . 0 . 0 . 1 ") čĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. add Header ( Headers . ACCEPT _ LANGUAGE , ĠLocale . getDefault (). language ) čĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. build () čĊčĊĠĠĠĠĠĠĠ Ġreturn @ Interceptor Ġchain . proceed ( request ) čĊĠĠĠ Ġ} čĊčĊĠĠĠ Ġprivate Ġval Ġok HttpClient Ġ= ĠOk HttpClient . Builder () čĊĠĠĠĠĠĠĠ Ġ. add Interceptor ( header Interceptor ) čĊĠĠĠĠĠĠĠ Ġ. add Interceptor ( logging Interceptor ) čĊĠĠĠĠĠĠĠ Ġ. connect Timeout ( connect TO , ĠTimeUnit . SECONDS ) čĊĠĠĠĠĠĠĠ Ġ. read Timeout ( read TO , ĠTimeUnit . SECONDS ) čĊĠĠĠĠĠĠĠ Ġ. write Timeout ( write TO , ĠTimeUnit . SECONDS ) čĊĠĠĠĠĠĠĠ Ġ. build () čĊčĊĠĠĠ Ġprivate Ġval Ġretrofit : ĠRet rofit Ġ= ĠRet rofit . Builder () čĊĠĠĠĠĠĠĠ Ġ. baseUrl ( BASE _ URL ) čĊĠĠĠĠĠĠĠ Ġ. add Converter Factory ( Gson Converter Factory . create ( JSON _ CONVER TER )) čĊĠĠĠĠĠĠĠ Ġ. client ( ok HttpClient ) čĊĠĠĠĠĠĠĠ Ġ. build () čĊčĊĠĠĠ Ġfun Ġ< T > Ġget Service ( service Class : ĠClass < T >): ĠT Ġ= Ġretrofit . create ( service Class ) čĊčĊĠĠĠ Ġ/** čĊĠĠĠĠ Ġ* ĠSends Ġa Ġnetwork Ġweb - service Ġrequest Ġand Ġreturns Ġthe Ġresponse Ġpayload Ġbundled Ġin Ġ[ Task Result ]. čĊĠĠĠĠ Ġ* čĊĠĠĠĠ Ġ* Ġ@ param Ġrequest Ġ** Ret rofit ** Ġnetwork Ġrequest Ġto Ġbe Ġsent čĊĠĠĠĠ Ġ* Ġ@ param Ġwith Response ĠContains Ġthe Ġwhole Ġserver Ġresponse . ĠAlso Ġthe Ġdefault Ġimplementation Ġfor čĊĠĠĠĠ Ġ* Ġ** 2 0 4 ** Ġstatus Ġcode Ġ( with Ġno Ġresponse Ġdata ). ĠIn Ġthis Ġscenario , Ġan Ġassumption Ġis Ġmade Ġthat Ġthe čĊĠĠĠĠ Ġ* Ġnetwork Ġresource Ġwas Ġdeleted Ġand Ġno Ġresponse Ġcould Ġbe Ġreturned ... čĊĠĠĠĠ Ġ*/ čĊĠĠĠ Ġ@ Suppress (" UN CHECK ED _ CAST ") čĊĠĠĠ Ġsuspend Ġfun Ġ< P , ĠM , ĠR Ġ: ĠServer Response < P , ĠM >> Ġsend WebRequest ( čĊĠĠĠĠĠĠĠ Ġrequest : Ġsuspend Ġ() Ġ-> ĠResponse < R >, čĊĠĠĠĠĠĠĠ Ġwith Response : Ġ( suspend Ġ( response : ĠR ) Ġ-> ĠUnit )? Ġ= Ġnull čĊĠĠĠ Ġ): ĠTask Result < P > Ġ{ čĊĠĠĠĠĠĠĠ Ġreturn Ġtry Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġresponse Ġ= Ġrequest . invoke () Ġ// ĠDo Ġactual Ġnetwork Ġrequest / call čĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġ( statusCode , Ġbody , Ġerror Body ) Ġ= ĠTrip le ( čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresponse . code (), čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresponse . body (), čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresponse . error Body () čĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) čĊĠĠĠĠĠĠĠĠĠĠĠ Ġresponse . body ()?. let Ġ{ Ġwith Response ?. invoke ( it ) Ġ} čĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( response . is Successful ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdata Ġ= Ġif Ġ( statusCode Ġ== Ġ 2 0 4 ) ĠAny () Ġas ĠP Ġelse Ġbody ?. payload Ġ?: ĠAny () Ġas ĠP čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTask Result . Success ( data ) čĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwith Context < Task Result < P >>( Dispatch ers . IO ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTask Result . Error ( Exception ( error Body ?. string ())) čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} čĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} čĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( ex : ĠException ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠ ĠLog . show ( LOG _ TAG , Ġex . message , Ġex , ĠLog . Type . ERROR ) čĊĠĠĠĠĠĠĠĠĠĠĠ ĠTask Result . Error ( ex ) čĊĠĠĠĠĠĠĠ Ġ} čĊĠĠĠ Ġ} čĊčĊĠĠĠ Ġ@ Throws ( Exception :: class ) čĊĠĠĠ Ġsuspend Ġfun Ġrequest File Download ( čĊĠĠĠĠĠĠĠ Ġresponse : Ġsuspend Ġ() Ġ-> ĠResponse < ResponseBody >, čĊĠĠĠĠĠĠĠ Ġdownload Location : ĠString , čĊĠĠĠĠĠĠĠ Ġon Progress Updated : Ġ(( downloaded : ĠLong , Ġtotal : ĠLong ) Ġ-> ĠUnit )? čĊĠĠĠ Ġ): ĠTask Result < File > Ġ{ čĊĠĠĠĠĠĠĠ Ġreturn Ġtry Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġresponse Body Ġ= Ġresponse . invoke (). body () čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ?: Ġthrow Ġ ĠException (" Unexpected Ġserver Ġresponse ") čĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġfile Ġ= Ġsave Downloaded File ( download Location , Ġresponse Body , Ġon Progress Updated ) čĊĠĠĠĠĠĠĠĠĠĠĠ ĠTask Result . Success ( file ) čĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( ex : ĠException ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠ ĠTask Result . Error ( ex ) čĊĠĠĠĠĠĠĠ Ġ} čĊĠĠĠ Ġ} čĊčĊĠĠĠ Ġprivate Ġsuspend Ġfun Ġsave Downloaded File ( čĊĠĠĠĠĠĠĠ Ġdownload Location : ĠString , čĊĠĠĠĠĠĠĠ Ġresponse Body : ĠResponse Body , čĊĠĠĠĠĠĠĠ Ġon Progress Updated : Ġ(( downloaded : ĠLong , Ġtotal : ĠLong ) Ġ-> ĠUnit )? čĊĠĠĠ Ġ): ĠFile Ġ= Ġwith Context ( Dispatch ers . IO ) Ġ{ čĊĠĠĠĠĠĠĠ Ġval Ġfile Ġ= ĠFile ( download Location ) čĊčĊĠĠĠĠĠĠĠ Ġvar ĠinputStream : ĠInputStream ? Ġ= Ġnull čĊĠĠĠĠĠĠĠ Ġvar ĠoutputStream : ĠOutputStream ? Ġ= Ġnull čĊčĊĠĠĠĠĠĠĠ Ġtry Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġfile Reader Ġ= ĠByteArray ( 4 0 9 6 ) čĊčĊĠĠĠĠĠĠĠĠĠĠĠ Ġval ĠfileSize Ġ= Ġresponse Body . content Length () čĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar ĠfileSize Downloaded : ĠLong Ġ= Ġ 0 čĊčĊĠĠĠĠĠĠĠĠĠĠĠ ĠinputStream Ġ= Ġresponse Body . byte Stream () čĊĠĠĠĠĠĠĠĠĠĠĠ ĠoutputStream Ġ= ĠFileOutputStream ( file ) čĊčĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhile Ġ( true ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġread Ġ= ĠinputStream . read ( file Reader ) čĊčĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( read Ġ== Ġ- 1 ) Ġbreak čĊčĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠoutputStream . write ( file Reader , Ġ 0 , Ġread ) čĊčĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠfileSize Downloaded Ġ+= Ġread . to Long () čĊčĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġon Progress Updated ?. invoke ( file Size Downloaded , ĠfileSize ) čĊčĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLog . show ( LOG _ TAG , Ġ" file Ġdownload : Ġ$ file Size Downloaded Ġof Ġ$ file Size ") čĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} čĊčĊĠĠĠĠĠĠĠĠĠĠĠ ĠoutputStream . flush () čĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠIOException ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠ ĠLog . show ( LOG _ TAG , Ġe . message , Ġe , ĠLog . Type . ERROR ) čĊĠĠĠĠĠĠĠ Ġ} Ġfinally Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠ ĠinputStream ?. close () čĊĠĠĠĠĠĠĠĠĠĠĠ ĠoutputStream ?. close () čĊĠĠĠĠĠĠĠ Ġ} čĊĠĠĠĠĠĠĠ Ġfile čĊĠĠĠ Ġ} čĊč Ċ }