/* Ċ Ġ* ĠCopyright Ġ 2 0 1 8 ĠGoogle ĠLLC . ĠAll Ġrights Ġreserved . Ċ Ġ* Ċ Ġ* Ġ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 . example . subscriptions . billing Ċ Ċ import Ġandroid . app . Activity Ċ import Ġandroid . app . Application Ċ import Ġandroid . arch . lifecycle . Lifecycle Ċ import Ġandroid . arch . lifecycle . Lifecycle Observer Ċ import Ġandroid . arch . lifecycle . Mutable LiveData Ċ import Ġandroid . arch . lifecycle . On Lifecycle Event Ċ import Ġandroid . util . Log Ċ import Ġcom . android . billing client . api .* Ċ import Ġcom . android . billing client . api . Billing Client .* Ċ import Ġcom . example . subscriptions . Constants Ċ import Ġcom . example . subscriptions . ui . Single Live Event Ċ Ċ /** Ċ Ġ* ĠWe Ġdon 't Ġimplement ĠCons ume Response Listener Ġbecause Ġthis Ġapp Ġis Ġabout Ġsubscriptions Ġonly . ĠAnd Ċ Ġ* Ġsubscriptions Ġcannot Ġbe Ġconsumed . Ċ Ġ*/ Ċ class ĠBilling Client Lifecycle Ġprivate Ġconstructor ( ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġapp : ĠApplication Ċ ) Ġ: ĠLifecycle Observer , ĠP urchases Updated Listener , ĠBilling Client State Listener , ĊĠĠĠĠĠĠĠ ĠSk u Details Response Listener Ġ{ ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠThe Ġpurchase Ġevent Ġis Ġobservable . ĠOnly Ġone Ġobserver Ġwill Ġbe Ġnotified . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġval Ġpurchase Update Event Ġ= ĠSingle Live Event < List < Purchase >>() ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠP urchases Ġare Ġobservable . ĠThis Ġlist Ġwill Ġbe Ġupdated Ġwhen Ġthe ĠBilling ĠLibrary ĊĠĠĠĠ Ġ* Ġdetect s Ġnew Ġor Ġexisting Ġpurch ases . ĠAll Ġob servers Ġwill Ġbe Ġnotified . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġval Ġpurch ases Ġ= ĠMutable LiveData < List < Purchase >>() ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠSk u Details Ġfor Ġall Ġknown ĠSK Us . ĊĠĠĠĠ Ġ* ĠRepresents Ġa Ġmap Ġof ĠproductId Ġto ĠSk u Details . ĠproductId Ġis Ġthe Ġsku Ġfield Ġfrom ĠSk u Details . ĊĠĠĠĠ Ġ* ĠProduct ĠID Ġis Ġa Ġunique , Ġhuman Ġreadable ĠID Ġfor Ġyour Ġproduct . ĊĠĠĠĠ Ġ* ĠProduct ĠIDs Ġare Ġalso Ġcalled ĠSK Us Ġin Ġthe ĠGoogle ĠPlay ĠBilling ĠLibrary . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġval Ġsk us With Sku Details Ġ= ĠMutable LiveData < Map < String , ĠSk u Details >>() ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠInstantiate Ġa Ġnew ĠBilling Client Ġinstance . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġbilling Client : ĠBilling Client ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠTAG Ġ= Ġ" Billing Lifecycle " ĊĊĠĠĠĠĠĠĠ Ġ@ Volatile ĊĠĠĠĠĠĠĠ Ġprivate Ġvar ĠINSTANCE : ĠBilling Client Lifecycle ? Ġ= Ġnull ĊĊĠĠĠĠĠĠĠ Ġfun ĠgetInstance ( app : ĠApplication ): ĠBilling Client Lifecycle Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠINSTANCE Ġ?: Ġsynchronized ( this ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠINSTANCE Ġ?: ĠBilling Client Lifecycle ( app ). also Ġ{ ĠINSTANCE Ġ= Ġit Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ On Lifecycle Event ( Lifecycle . Event . ON _ CREATE ) ĊĠĠĠ Ġfun Ġcreate () Ġ{ ĊĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" ON _ CREATE ") ĊĠĠĠĠĠĠĠ Ġ// ĠCreate Ġa Ġnew ĠBilling Client Ġin ĠonCreate (). ĊĠĠĠĠĠĠĠ Ġ// ĠSince Ġthe ĠBilling Client Ġcan Ġonly Ġbe Ġused Ġonce , Ġwe Ġneed Ġto Ġcreate Ġa Ġnew Ġinstance ĊĠĠĠĠĠĠĠ Ġ// Ġafter Ġending Ġthe Ġprevious Ġconnection Ġto Ġthe ĠGoogle ĠPlay ĠStore Ġin Ġon Destroy (). ĊĠĠĠĠĠĠĠ Ġbilling Client Ġ= ĠnewBuilder ( app . application Context ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. set Listener ( this ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. enable Pending P urchases () Ġ// ĠNot Ġused Ġfor Ġsubscriptions . ĠNote Ġthat Ġif Ġyou Ġdo Ġnot Ġcall Ġenable Pending P urchases (), Ġyou Ġcannot Ġinstantiate Ġthe ĠGoogle ĠPlay ĠBilling ĠLibrary . ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. build () ĊĠĠĠĠĠĠĠ Ġif Ġ(! billing Client . is Ready ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" Billing Client : ĠStart Ġconnection ...") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbilling Client . start Connection ( this ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ On Lifecycle Event ( Lifecycle . Event . ON _ DESTROY ) ĊĠĠĠ Ġfun Ġdestroy () Ġ{ ĊĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" ON _ DESTROY ") ĊĠĠĠĠĠĠĠ Ġif Ġ( billing Client . is Ready ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" Billing Client Ġcan Ġonly Ġbe Ġused Ġonce Ġ-- Ġclosing Ġconnection ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠBilling Client Ġcan Ġonly Ġbe Ġused Ġonce . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠAfter Ġcalling Ġend Connection (), Ġwe Ġmust Ġcreate Ġa Ġnew ĠBilling Client . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbilling Client . end Connection () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġon Billing Setup Finished ( billing Result : ĠBilling Result ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġresponse Code Ġ= Ġbilling Result . response Code ĊĠĠĠĠĠĠĠ Ġval Ġdebug Message Ġ= Ġbilling Result . debug Message ĊĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" on Billing Setup Finished : Ġ$ response Code Ġ$ debug Message ") ĊĠĠĠĠĠĠĠ Ġif Ġ( response Code Ġ== ĠBilling Response Code . OK ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠThe Ġbilling Ġclient Ġis Ġready . ĠYou Ġcan Ġquery Ġpurch ases Ġhere . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġquery Sku Details () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġquery P urchases () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġon Billing Service Disconnected () Ġ{ ĊĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" on Billing Service Disconnected ") ĊĠĠĠĠĠĠĠ Ġ// ĠTODO : ĠTry Ġconnecting Ġagain Ġwith Ġexponential Ġbackoff . ĊĠĠĠĠĠĠĠ Ġ// Ġbilling Client . start Connection ( this ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠIn Ġorder Ġto Ġmake Ġpurch ases , Ġyou Ġneed Ġthe Ġ[ Sku Details ] Ġfor Ġthe Ġitem Ġor Ġsubscription . ĊĠĠĠĠ Ġ* ĠThis Ġis Ġan Ġasynchronous Ġcall Ġthat Ġwill Ġreceive Ġa Ġresult Ġin Ġ[ on Sku Details Response ]. ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġquery Sku Details () Ġ{ ĊĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" query Sku Details ") ĊĠĠĠĠĠĠĠ Ġval Ġparams Ġ= ĠSk u Details Params . newBuilder () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. setType ( Sku Type . SUB S ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. set Sk us List ( listOf ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠConstants . BASIC _ SK U , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠConstants . PRE MI UM _ SK U ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ)) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. build () ĊĠĠĠĠĠĠĠ Ġparams ?. let Ġ{ Ġsku Details Params Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLog . i ( TAG , Ġ" query Sku Details Async ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbilling Client . query Sku Details Async ( sku Details Params , Ġthis ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠRe ceiv es Ġthe Ġresult Ġfrom Ġ[ query Sku Details ]. ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* ĠStore Ġthe ĠSk u Details Ġand Ġpost Ġthem Ġin Ġthe Ġ[ sk us With Sku Details ]. ĠThis Ġallows Ġother Ġparts ĊĠĠĠĠ Ġ* Ġof Ġthe Ġapp Ġto Ġuse Ġthe Ġ[ Sku Details ] Ġto Ġshow ĠSK U Ġinformation Ġand Ġmake Ġpurch ases . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġoverride Ġfun Ġon Sku Details Response ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbilling Result : ĠBilling Result ?, ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsku Details List : ĠMutable List < Sku Details >? ĊĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( billing Result Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLog . w tf ( TAG , Ġ" on Sku Details Response : Ġnull ĠBilling Result ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġresponse Code Ġ= Ġbilling Result . response Code ĊĠĠĠĠĠĠĠ Ġval Ġdebug Message Ġ= Ġbilling Result . debug Message ĊĠĠĠĠĠĠĠ Ġwhen Ġ( response Code ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠBilling Response Code . OK Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLog . i ( TAG , Ġ" on Sku Details Response : Ġ$ response Code Ġ$ debug Message ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( sku Details List Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLog . w ( TAG , Ġ" on Sku Details Response : Ġnull ĠSk u Details Ġlist ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsk us With Sku Details . post Value ( empty Map ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsk us With Sku Details . post Value ( HashMap < String , ĠSk u Details >(). apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( details Ġin Ġsku Details List ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġput ( details . sku , Ġdetails ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ}. also Ġ{ Ġposted Value Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLog . i ( TAG , Ġ" on Sku Details Response : Ġcount Ġ${ posted Value . size }") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ}) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠBilling Response Code . SERVICE _ DIS CONNECTED , ĊĠĠĠĠĠĠĠĠĠĠĠ ĠBilling Response Code . SERVICE _ UN AVAILABLE , ĊĠĠĠĠĠĠĠĠĠĠĠ ĠBilling Response Code . B ILL ING _ UN AVAILABLE , ĊĠĠĠĠĠĠĠĠĠĠĠ ĠBilling Response Code . ITEM _ UN AVAILABLE , ĊĠĠĠĠĠĠĠĠĠĠĠ ĠBilling Response Code . DE VELO PER _ ERROR , ĊĠĠĠĠĠĠĠĠĠĠĠ ĠBilling Response Code . ERROR Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLog . e ( TAG , Ġ" on Sku Details Response : Ġ$ response Code Ġ$ debug Message ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠBilling Response Code . USER _ C ANCE LED , ĊĠĠĠĠĠĠĠĠĠĠĠ ĠBilling Response Code . FEATURE _ NOT _ SUPPORTED , ĊĠĠĠĠĠĠĠĠĠĠĠ ĠBilling Response Code . ITEM _ AL READY _ OWN ED , ĊĠĠĠĠĠĠĠĠĠĠĠ ĠBilling Response Code . ITEM _ NOT _ OWN ED Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠThese Ġresponse Ġcodes Ġare Ġnot Ġexpected . ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLog . w tf ( TAG , Ġ" on Sku Details Response : Ġ$ response Code Ġ$ debug Message ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠQuery ĠGoogle ĠPlay ĠBilling Ġfor Ġexisting Ġpurch ases . ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* ĠNew Ġpurch ases Ġwill Ġbe Ġprovided Ġto Ġthe ĠP urchases Updated Listener . ĊĠĠĠĠ Ġ* ĠYou Ġstill Ġneed Ġto Ġcheck Ġthe ĠGoogle ĠPlay ĠBilling ĠAPI Ġto Ġknow Ġwhen Ġpurchase Ġtokens Ġare Ġremoved . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġquery P urchases () Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ(! billing Client . is Ready ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLog . e ( TAG , Ġ" query P urchases : ĠBilling Client Ġis Ġnot Ġready ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" query P urchases : ĠSUB S ") ĊĠĠĠĠĠĠĠ Ġval Ġresult Ġ= Ġbilling Client . query P urchases ( Sku Type . SUB S ) ĊĠĠĠĠĠĠĠ Ġif Ġ( result Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLog . i ( TAG , Ġ" query P urchases : Ġnull Ġpurchase Ġresult ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġprocess P urchases ( null ) ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( result . p urchases List Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLog . i ( TAG , Ġ" query P urchases : Ġnull Ġpurchase Ġlist ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprocess P urchases ( null ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprocess P urchases ( result . p urchases List ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠCalled Ġby Ġthe ĠBilling ĠLibrary Ġwhen Ġnew Ġpurch ases Ġare Ġdetected . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġoverride Ġfun Ġon P urchases Updated ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbilling Result : ĠBilling Result ?, ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpurch ases : ĠMutable List < Purchase >? ĊĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( billing Result Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLog . w tf ( TAG , Ġ" on P urchases Updated : Ġnull ĠBilling Result ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġresponse Code Ġ= Ġbilling Result . response Code ĊĠĠĠĠĠĠĠ Ġval Ġdebug Message Ġ= Ġbilling Result . debug Message ĊĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" on P urchases Updated : Ġ$ response Code Ġ$ debug Message ") ĊĠĠĠĠĠĠĠ Ġwhen Ġ( response Code ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠBilling Response Code . OK Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( p urchases Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" on P urchases Updated : Ġnull Ġpurchase Ġlist ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprocess P urchases ( null ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprocess P urchases ( p urchases ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠBilling Response Code . USER _ C ANCE LED Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLog . i ( TAG , Ġ" on P urchases Updated : ĠUser Ġcanceled Ġthe Ġpurchase ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠBilling Response Code . ITEM _ AL READY _ OWN ED Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLog . i ( TAG , Ġ" on P urchases Updated : ĠThe Ġuser Ġalready Ġowns Ġthis Ġitem ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠBilling Response Code . DE VELO PER _ ERROR Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLog . e ( TAG , Ġ" on P urchases Updated : Ġ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 ." ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠSend Ġpurchase ĠSingle Live Event Ġand Ġupdate Ġpurch ases ĠLive Data . ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* ĠThe ĠSingle Live Event Ġwill Ġtrigger Ġnetwork Ġcall Ġto Ġverify Ġthe Ġsubscriptions Ġon Ġthe Ġsever . ĊĠĠĠĠ Ġ* ĠThe ĠLive Data Ġwill Ġallow ĠGoogle ĠPlay Ġsettings ĠUI Ġto Ġupdate Ġbased Ġon Ġthe Ġlatest Ġpurchase Ġdata . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġfun Ġprocess P urchases ( p urchases List : ĠList < Purchase > ?) Ġ{ ĊĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" process P urchases : Ġ${ p urchases List ?. size } Ġpurchase ( s )") ĊĠĠĠĠĠĠĠ Ġif Ġ( is Un changed Purchase List ( p urchases List )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" process P urchases : ĠPurchase Ġlist Ġhas Ġnot Ġchanged ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġpurchase Update Event . post Value ( p urchases List ) ĊĠĠĠĠĠĠĠ Ġpurch ases . post Value ( p urchases List ) ĊĠĠĠĠĠĠĠ Ġpurch ases List ?. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlog Ack nowledge ment Status ( p urchases List ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠCheck Ġwhether Ġthe Ġpurch ases Ġhave Ġchanged Ġbefore Ġposting Ġchanges . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġfun Ġis Un changed Purchase List ( p urchases List : ĠList < Purchase >? ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠTODO : ĠOpt imize Ġto Ġavoid Ġupdates Ġwith Ġidentical Ġdata . ĊĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠLog Ġthe Ġnumber Ġof Ġpurch ases Ġthat Ġare Ġacknowled ged Ġand Ġnot Ġacknowled ged . ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġhttps :// developer . android . com / google / play / billing / billing _ library _ releases _ notes # 2 _ 0 _ ack nowledge ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* ĠWhen Ġthe Ġpurchase Ġis Ġfirst Ġreceived , Ġit Ġwill Ġnot Ġbe Ġacknowled ged . ĊĠĠĠĠ Ġ* ĠThis Ġapplication Ġsends Ġthe Ġpurchase Ġtoken Ġto Ġthe Ġserver Ġfor Ġregistration . ĠAfter Ġthe ĊĠĠĠĠ Ġ* Ġpurchase Ġtoken Ġis Ġregistered Ġto Ġan Ġaccount , Ġthe ĠAndroid Ġapp Ġacknowled ges Ġthe Ġpurchase Ġtoken . ĊĠĠĠĠ Ġ* ĠThe Ġnext Ġtime Ġthe Ġpurchase Ġlist Ġis Ġupdated , Ġit Ġwill Ġcontain Ġacknowled ged Ġpurch ases . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġfun Ġlog Ack nowledge ment Status ( p urchases List : ĠList < Purchase >) Ġ{ ĊĠĠĠĠĠĠĠ Ġvar Ġack _ yes Ġ= Ġ 0 ĊĠĠĠĠĠĠĠ Ġvar Ġack _ no Ġ= Ġ 0 ĊĠĠĠĠĠĠĠ Ġfor Ġ( purchase Ġin Ġpurch ases List ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( purchase . is Ack nowled ged ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġack _ yes ++ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġack _ no ++ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" log Ack nowledge ment Status : Ġacknowled ged =$ ack _ yes Ġun ack nowled ged =$ ack _ no ") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠLaunch ing Ġthe Ġbilling Ġflow . ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* ĠLaunch ing Ġthe ĠUI Ġto Ġmake Ġa Ġpurchase Ġrequires Ġa Ġreference Ġto Ġthe ĠActivity . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġlaunch Billing Flow ( activity : ĠActivity , Ġparams : ĠBilling Flow Params ): ĠInt Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġsku Ġ= Ġparams . sku ĊĠĠĠĠĠĠĠ Ġval Ġold Sku Ġ= Ġparams . old Sku ĊĠĠĠĠĠĠĠ ĠLog . i ( TAG , Ġ" launch Billing Flow : Ġsku : Ġ$ sku , Ġold Sku : Ġ$ old Sku ") ĊĠĠĠĠĠĠĠ Ġif Ġ(! billing Client . is Ready ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLog . e ( TAG , Ġ" launch Billing Flow : ĠBilling Client Ġis Ġnot Ġready ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġbilling Result Ġ= Ġbilling Client . launch Billing Flow ( activity , Ġparams ) ĊĠĠĠĠĠĠĠ Ġval Ġresponse Code Ġ= Ġbilling Result . response Code ĊĠĠĠĠĠĠĠ Ġval Ġdebug Message Ġ= Ġbilling Result . debug Message ĊĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" launch Billing Flow : ĠBilling Response Ġ$ response Code Ġ$ debug Message ") ĊĠĠĠĠĠĠĠ Ġreturn Ġresponse Code ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠAck nowledge Ġa Ġpurchase . ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġhttps :// developer . android . com / google / play / billing / billing _ library _ releases _ notes # 2 _ 0 _ ack nowledge ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* ĠApps Ġshould Ġacknowledge Ġthe Ġpurchase Ġafter Ġconfirm ing Ġthat Ġthe Ġpurchase Ġtoken ĊĠĠĠĠ Ġ* Ġhas Ġbeen Ġassociated Ġwith Ġa Ġuser . ĠThis Ġapp Ġonly Ġacknowled ges Ġpurch ases Ġafter ĊĠĠĠĠ Ġ* Ġsuccessfully Ġreceiving Ġthe Ġsubscription Ġdata Ġback Ġfrom Ġthe Ġserver . ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* ĠDevelopers Ġcan Ġchoose Ġto Ġacknowledge Ġpurch ases Ġfrom Ġa Ġserver Ġusing Ġthe ĊĠĠĠĠ Ġ* ĠGoogle ĠPlay ĠDeveloper ĠAPI . ĠThe Ġserver Ġhas Ġdirect Ġaccess Ġto Ġthe Ġuser Ġdatabase , ĊĠĠĠĠ Ġ* Ġso Ġusing Ġthe ĠGoogle ĠPlay ĠDeveloper ĠAPI Ġfor Ġacknowledge ment Ġmight Ġbe Ġmore Ġreliable . ĊĠĠĠĠ Ġ* ĠTODO ( 1 3 4 5 0 6 8 2 1 ): ĠAck nowledge Ġpurch ases Ġon Ġthe Ġserver . ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* ĠIf Ġthe Ġpurchase Ġtoken Ġis Ġnot Ġacknowled ged Ġwithin Ġ 3 Ġdays , ĊĠĠĠĠ Ġ* Ġthen ĠGoogle ĠPlay Ġwill Ġautomatically Ġrefund Ġand Ġre voke Ġthe Ġpurchase . ĊĠĠĠĠ Ġ* ĠThis Ġbehavior Ġhelps Ġensure Ġthat Ġusers Ġare Ġnot Ġchar ged Ġfor Ġsubscriptions Ġunless Ġthe ĊĠĠĠĠ Ġ* Ġuser Ġhas Ġsuccessfully Ġreceived Ġaccess Ġto Ġthe Ġcontent . ĊĠĠĠĠ Ġ* ĠThis Ġelim inates Ġa Ġcategory Ġof Ġissues Ġwhere Ġusers Ġcompl ain Ġto Ġdevelopers ĊĠĠĠĠ Ġ* Ġthat Ġthey Ġpaid Ġfor Ġsomething Ġthat Ġthe Ġapp Ġis Ġnot Ġgiving Ġto Ġthem . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġacknowledge Purchase ( purchase Token : ĠString ) Ġ{ ĊĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" ack nowledge Purchase ") ĊĠĠĠĠĠĠĠ Ġval Ġparams Ġ= ĠAck nowledge Purchase Params . newBuilder () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. set Purchase Token ( purchase Token ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. build () ĊĠĠĠĠĠĠĠ Ġbilling Client . ack nowledge Purchase ( params ) Ġ{ Ġbilling Result Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġresponse Code Ġ= Ġbilling Result . response Code ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdebug Message Ġ= Ġbilling Result . debug Message ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" ack nowledge Purchase : Ġ$ response Code Ġ$ debug Message ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ