/* čĊ Ġ* ĠCopyright Ġ( c ) Ġ 2 0 1 9 . čĊ Ġ* ĠJo Ã£o ĠP au lo ĠS ena Ġ< jo aop au lo 7 6 1 @ gmail . com > čĊ Ġ* čĊ Ġ* ĠThis Ġfile Ġis Ġpart Ġof Ġthe ĠUN ES ĠOpen ĠSource ĠProject . čĊ Ġ* čĊ Ġ* ĠUN ES Ġis Ġlicensed Ġunder Ġthe ĠMIT ĠLicense čĊ Ġ* čĊ Ġ* ĠPermission Ġis Ġhereby Ġgranted , Ġfree Ġof Ġcharge , Ġto Ġany Ġperson Ġobtaining Ġa Ġcopy čĊ Ġ* Ġof Ġthis Ġsoftware Ġand Ġassociated Ġdocumentation Ġfiles Ġ( the Ġ" Software "), Ġto Ġdeal čĊ Ġ* Ġin Ġthe ĠSoftware Ġwithout Ġrestriction , Ġincluding Ġwithout Ġlimitation Ġthe Ġrights čĊ Ġ* Ġto Ġuse , Ġcopy , Ġmodify , Ġmerge , Ġpublish , Ġdistribute , Ġsublicense , Ġand / or Ġsell čĊ Ġ* Ġcopies Ġof Ġthe ĠSoftware , Ġand Ġto Ġpermit Ġpersons Ġto Ġwhom Ġthe ĠSoftware Ġis čĊ Ġ* Ġfurnished Ġto Ġdo Ġso , Ġsubject Ġto Ġthe Ġfollowing Ġconditions : čĊ Ġ* čĊ Ġ* ĠThe Ġabove Ġcopyright Ġnotice Ġand Ġthis Ġpermission Ġnotice Ġshall Ġbe Ġincluded Ġin Ġall čĊ Ġ* Ġcopies Ġor Ġsubstantial Ġportions Ġof Ġthe ĠSoftware . čĊ Ġ* čĊ Ġ* ĠTHE ĠSOFTWARE ĠIS ĠPROVIDED Ġ" AS ĠIS ", ĠWITHOUT ĠWARRANTY ĠOF ĠANY ĠKIND , ĠEXPRESS ĠOR čĊ Ġ* ĠIMPLIED , ĠINCLUDING ĠBUT ĠNOT ĠLIMITED ĠTO ĠTHE ĠWARRANTIES ĠOF ĠMERCHANTABILITY , čĊ Ġ* ĠFITNESS ĠFOR ĠA ĠPARTICULAR ĠPURPOSE ĠAND ĠNONINFRINGEMENT . ĠIN ĠNO ĠEVENT ĠSHALL ĠTHE čĊ Ġ* ĠAUTHORS ĠOR ĠCOPYRIGHT ĠHOLDERS ĠBE ĠLIABLE ĠFOR ĠANY ĠCLAIM , ĠDAMAGES ĠOR ĠOTHER čĊ Ġ* ĠLIABILITY , ĠWHETHER ĠIN ĠAN ĠACTION ĠOF ĠCONTRACT , ĠTORT ĠOR ĠOTHERWISE , ĠARISING ĠFROM , čĊ Ġ* ĠOUT ĠOF ĠOR ĠIN ĠCONNECTION ĠWITH ĠTHE ĠSOFTWARE ĠOR ĠTHE ĠUSE ĠOR ĠOTHER ĠDEALINGS ĠIN ĠTHE čĊ Ġ* ĠSOFTWARE . čĊ Ġ*/ čĊč Ċ package Ġcom . for c et ower . ue fs . core . billing čĊč Ċ import Ġandroid . annotation . Suppress Lint č Ċ import Ġandroid . app . Activity č Ċ import Ġandroid . app . Application č Ċ import Ġandroidx . lifecycle . Lifecycle č Ċ import Ġandroidx . lifecycle . Lifecycle Observer č Ċ import Ġandroidx . lifecycle . LiveData č Ċ import Ġandroidx . lifecycle . Mutable LiveData č Ċ import Ġandroidx . lifecycle . On Lifecycle Event č Ċ import Ġcom . android . billing client . api . Billing Client č Ċ import Ġcom . android . billing client . api . Billing Client State Listener č Ċ import Ġcom . android . billing client . api . Billing Flow Params č Ċ import Ġcom . android . billing client . api . Purchase č Ċ import Ġcom . android . billing client . api . P urchases Updated Listener č Ċ import Ġcom . android . billing client . api . Sku Details Params č Ċ import Ġcom . for c et ower . ue fs . feature . shared . Single Live Event č Ċ import Ġtim ber . log . Tim ber čĊč Ċ class ĠBilling Client Lifecycle ( čĊĠĠĠ Ġprivate Ġval Ġapplication : ĠApplication č Ċ ) Ġ: ĠLifecycle Observer , ĠP urchases Updated Listener , ĠBilling Client State Listener Ġ{ čĊčĊĠĠĠ Ġval Ġpurchase Update Event Ġ= ĠSingle Live Event < List < Purchase >>() čĊĠĠĠ Ġval Ġpurch ases Ġ= ĠMutable LiveData < List < Purchase >>() čĊĠĠĠ Ġval Ġstate Ġ= ĠMutable LiveData < Boolean >() čĊčĊĠĠĠ Ġlateinit Ġvar Ġbilling Client : ĠBilling Client čĊčĊĠĠĠ Ġ@ On Lifecycle Event ( Lifecycle . Event . ON _ CREATE ) čĊĠĠĠ Ġfun Ġcreate () Ġ{ čĊĠĠĠĠĠĠĠ Ġbilling Client Ġ= ĠBilling Client . newBuilder ( application . application Context ). set Listener ( this ). build () čĊĠĠĠĠĠĠĠ Ġif Ġ(! billing Client . is Ready ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . d (" Starting ĠConnection ...") čĊĠĠĠĠĠĠĠĠĠĠĠ Ġbilling Client . start Connection ( this ) čĊĠĠĠĠĠĠĠ Ġ} čĊĠĠĠ Ġ} čĊčĊĠĠĠ Ġ@ On Lifecycle Event ( Lifecycle . Event . ON _ DESTROY ) čĊĠĠĠ Ġfun Ġdestroy () Ġ{ čĊĠĠĠĠĠĠĠ Ġif Ġ( billing Client . is Ready ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . d (" Closing Ġconnection ") čĊĠĠĠĠĠĠĠĠĠĠĠ Ġbilling Client . end Connection () čĊĠĠĠĠĠĠĠ Ġ} čĊĠĠĠ Ġ} čĊčĊĠĠĠ Ġoverride Ġfun Ġon Billing Setup Finished ( billing Response Code : ĠInt ) Ġ{ čĊĠĠĠĠĠĠĠ ĠTim ber . d (" on Billing Setup Finished : Ġ$ billing Response Code ") čĊĠĠĠĠĠĠĠ Ġif Ġ( billing Response Code Ġ== ĠBilling Client . Billing Response . OK ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠ Ġstate . post Value ( true ) čĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠThe Ġbilling Ġclient Ġis Ġready . ĠYou Ġcan Ġquery Ġpurch ases Ġhere . čĊĠĠĠĠĠĠĠĠĠĠĠ Ġupdate P urchases () čĊĠĠĠĠĠĠĠ Ġ} čĊĠĠĠ Ġ} čĊčĊĠĠĠ Ġoverride Ġfun Ġon Billing Service Disconnected () Ġ{ čĊĠĠĠĠĠĠĠ ĠTim ber . d (" on Billing Service Disconnected ") čĊĠĠĠĠĠĠĠ Ġstate . post Value ( false ) čĊĠĠĠĠĠĠĠ Ġ// ĠTODO : ĠTry Ġconnecting Ġagain Ġwith Ġexponential Ġbackoff . čĊĠĠĠĠĠĠĠ Ġ// Ġbilling Client . start Connection ( this ) čĊĠĠĠ Ġ} čĊčĊĠĠĠ Ġfun Ġstart Connection () Ġ{ čĊĠĠĠĠĠĠĠ Ġbilling Client . start Connection ( this ) čĊĠĠĠ Ġ} čĊčĊĠĠĠ Ġfun Ġquery Sku Details ( sk us : ĠList < String >): ĠLive Data < Sku Details Result > Ġ{ čĊĠĠĠĠĠĠĠ Ġval Ġresult Ġ= ĠMutable LiveData < Sku Details Result >() čĊĠĠĠĠĠĠĠ Ġval Ġparams Ġ= ĠSk u Details Params . newBuilder () čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. set Sk us List ( sk us ) čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. setType ( Billing Client . Sku Type . IN APP ) čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. build () čĊčĊĠĠĠĠĠĠĠ Ġbilling Client . query Sku Details Async ( params ) Ġ{ Ġresponse Code , Ġdetails Ġ-> čĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġvalue Ġ= ĠSk u Details Result ( response Code , Ġdetails ) čĊĠĠĠĠĠĠĠĠĠĠĠ Ġresult . post Value ( value ) čĊĠĠĠĠĠĠĠ Ġ} čĊĠĠĠĠĠĠĠ Ġreturn Ġresult čĊĠĠĠ Ġ} čĊčĊĠĠĠ Ġfun Ġconsume Token ( token : ĠString ): ĠLive Data < Sku Consume Result > Ġ{ čĊĠĠĠĠĠĠĠ Ġval Ġresult Ġ= ĠMutable LiveData < Sku Consume Result >() čĊčĊĠĠĠĠĠĠĠ Ġbilling Client . consume Async ( token ) Ġ{ Ġresponse Code , Ġpurchase Token Ġ-> čĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . d (" Code : Ġ$ response Code Ġ:: ĠToken : Ġ$ purchase Token ") čĊĠĠĠĠĠĠĠĠĠĠĠ Ġresult . post Value ( Sku Consume Result ( response Code , Ġpurchase Token )) čĊĠĠĠĠĠĠĠ Ġ} čĊĠĠĠĠĠĠĠ Ġreturn Ġresult čĊĠĠĠ Ġ} čĊčĊĠĠĠ Ġfun Ġupdate P urchases () Ġ{ čĊĠĠĠĠĠĠĠ Ġif Ġ(! billing Client . is Ready ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . e (" Billing Client Ġis Ġnot Ġready Ġto Ġquery Ġfor Ġexisting Ġpurch ases ") čĊĠĠĠĠĠĠĠ Ġ} čĊĠĠĠĠĠĠĠ Ġval Ġresult Ġ= Ġbilling Client . query P urchases ( Billing Client . Sku Type . SUB S ) čĊĠĠĠĠĠĠĠ Ġif Ġ( result Ġ== Ġnull ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . i (" Update Ġpurchase : ĠNull Ġpurchase Ġresult ") čĊĠĠĠĠĠĠĠĠĠĠĠ Ġhandle P urchases ( null ) čĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( result . p urchases List Ġ== Ġnull ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . i (" Update Ġpurchase : ĠNull Ġpurchase Ġlist ") čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġhandle P urchases ( null ) čĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġhandle P urchases ( result . p urchases List ) čĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} čĊĠĠĠĠĠĠĠ Ġ} čĊĠĠĠ Ġ} čĊčĊĠĠĠ Ġ/** čĊĠĠĠĠ Ġ* ĠCalled Ġby Ġthe ĠBilling ĠLibrary Ġwhen Ġnew Ġpurch ases Ġare Ġdetected . čĊĠĠĠĠ Ġ*/ čĊĠĠĠ Ġ@ Suppress Lint (" Binary Operation In Tim ber ") čĊĠĠĠ Ġoverride Ġfun Ġon P urchases Updated ( response Code : ĠInt , Ġpurch ases List : ĠList < Purchase > ?) Ġ{ čĊĠĠĠĠĠĠĠ ĠTim ber . d (" on P urchases Updated , Ġresponse Ġcode : Ġ$ response Code ") čĊĠĠĠĠĠĠĠ Ġwhen Ġ( response Code ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠ ĠBilling Client . Billing Response . OK Ġ-> Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( p urchases List Ġ== Ġnull ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . d (" Purchase Ġupdate : ĠNo Ġpurch ases ") čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġhandle P urchases ( null ) čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġhandle P urchases ( p urchases List ) čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} čĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} čĊĠĠĠĠĠĠĠĠĠĠĠ ĠBilling Client . Billing Response . USER _ C ANCE LED Ġ-> Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . i (" User Ġcanceled Ġthe Ġpurchase ") čĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} čĊĠĠĠĠĠĠĠĠĠĠĠ ĠBilling Client . Billing Response . ITEM _ AL READY _ OWN ED Ġ-> Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . i (" The Ġuser Ġalready Ġowns Ġthis Ġitem ") čĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} čĊĠĠĠĠĠĠĠĠĠĠĠ ĠBilling Client . Billing Response . DE VELO PER _ ERROR Ġ-> Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . e (" Developer Ġerror Ġmeans Ġthat ĠGoogle ĠPlay Ġdoes Ġnot Ġrecognize Ġthe Ġ" Ġ+ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" configuration . ĠIf Ġyou Ġare Ġjust Ġgetting Ġstarted , Ġmake Ġsure Ġyou Ġhave Ġ" Ġ+ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" configured Ġthe Ġapplication Ġcorrectly Ġin Ġthe ĠGoogle ĠPlay ĠConsole . Ġ" Ġ+ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" The ĠSK U Ġproduct ĠID Ġmust Ġmatch Ġand Ġthe ĠA PK Ġyou Ġare Ġusing Ġmust Ġbe Ġ" Ġ+ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" signed Ġwith Ġrelease Ġkeys .") čĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} čĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . e (" See Ġerror Ġcode Ġin ĠBilling Client . Billing Response : Ġ$ response Code ") čĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} čĊĠĠĠĠĠĠĠ Ġ} čĊĠĠĠ Ġ} čĊčĊĠĠĠ Ġ/** čĊĠĠĠĠ Ġ* ĠCheck Ġif Ġpurch ases Ġhave Ġchanged Ġbefore Ġupdating Ġother Ġpart Ġof Ġthe Ġapp . čĊĠĠĠĠ Ġ*/ čĊĠĠĠ Ġprivate Ġfun Ġhandle P urchases ( p urchases List : ĠList < Purchase > ?) Ġ{ čĊĠĠĠĠĠĠĠ Ġif Ġ( is Un changed Purchase List ( p urchases List )) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . d (" Same Ġ${ p urchases List ?. size } Ġpurchase ( s ), Ġno Ġneed Ġto Ġpost Ġan Ġupdate Ġto Ġthe Ġlive Ġdata ") čĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . d (" Handling Ġ${ p urchases List ?. size } Ġpurchase ( s )") čĊĠĠĠĠĠĠĠĠĠĠĠ Ġupdate P urchases ( p urchases List ) čĊĠĠĠĠĠĠĠ Ġ} čĊĠĠĠ Ġ} čĊčĊĠĠĠ Ġprivate Ġfun Ġis Un changed Purchase List ( p urchases List : ĠList < Purchase >? ): ĠBoolean Ġ{ čĊĠĠĠĠĠĠĠ Ġreturn Ġfalse čĊĠĠĠ Ġ} čĊčĊĠĠĠ Ġprivate Ġfun Ġupdate P urchases ( p urchases List : ĠList < Purchase > ?) Ġ{ čĊĠĠĠĠĠĠĠ ĠTim ber . i (" update P urchases : Ġ${ p urchases List ?. size } Ġpurchase ( s )") čĊĠĠĠĠĠĠĠ Ġpurchase Update Event . post Value ( p urchases List ) čĊĠĠĠĠĠĠĠ Ġpurch ases . post Value ( p urchases List ) čĊĠĠĠ Ġ} čĊčĊĠĠĠ Ġfun Ġlaunch Billing Flow ( activity : ĠActivity , Ġparams : ĠBilling Flow Params ): ĠInt Ġ{ čĊĠĠĠĠĠĠĠ Ġval Ġsku Ġ= Ġparams . sku čĊĠĠĠĠĠĠĠ Ġval Ġold Sku Ġ= Ġparams . old Sku čĊĠĠĠĠĠĠĠ ĠTim ber . i (" Launch ing Ġbilling Ġflow Ġw th Ġsku : Ġ$ sku , Ġold Sk us : Ġ$ old Sku ") čĊčĊĠĠĠĠĠĠĠ Ġif Ġ(! billing Client . is Ready ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . e (" Billing Client Ġis Ġnot Ġready Ġto Ġstart Ġbilling Ġflow ") čĊĠĠĠĠĠĠĠ Ġ} čĊčĊĠĠĠĠĠĠĠ Ġval Ġresponse Code Ġ= Ġbilling Client . launch Billing Flow ( activity , Ġparams ) čĊĠĠĠĠĠĠĠ ĠTim ber . d (" Launch ĠBilling ĠFlow ĠResponse ĠCode : Ġ$ response Code ") čĊĠĠĠĠĠĠĠ Ġreturn Ġresponse Code čĊĠĠĠ Ġ} č Ċ }