{"id":137877,"date":"2021-03-24T00:00:00","date_gmt":"2021-03-24T00:00:00","guid":{"rendered":"https:\/\/adapty.io\/de-android-in-app-purchases-google-play-billing-library-part-2\/"},"modified":"2021-03-24T00:00:00","modified_gmt":"2021-03-24T00:00:00","slug":"android-in-app-purchases-google-play-billing-library-part-2","status":"publish","type":"post","link":"https:\/\/adapty.io\/de\/blog\/android-in-app-purchases-google-play-billing-library-part-2\/","title":{"rendered":"Android In-App-K\u00e4ufe, Teil 2: Verarbeitung von K\u00e4ufen mit der Google Play Billing Library"},"content":{"rendered":"\n

Im vorherigen Artikel haben wir eine Wrapper-Klasse erstellt, um mit der Billing Library zu arbeiten:<\/p>\n\n\n\n

<\/path><\/path><\/svg><\/span>
import<\/span> <\/span>android.content.Context<\/span><\/span>\nimport<\/span> <\/span>com.android.billingclient.api.*<\/span><\/span>\nclass<\/span> <\/span>BillingClientWrapper<\/span>(<\/span>context<\/span>:<\/span> <\/span>Context<\/span>)<\/span> <\/span>:<\/span> <\/span>PurchasesUpdatedListener<\/span> <\/span>{<\/span><\/span>\n   <\/span>interface<\/span> <\/span>OnQueryProductsListener<\/span> <\/span>{<\/span><\/span>\n       <\/span>fun<\/span> <\/span>onSuccess<\/span>(<\/span>products<\/span>:<\/span> <\/span>List<\/span><<\/span>SkuDetails<\/span>><\/span>)<\/span><\/span>\n       <\/span>fun<\/span> <\/span>onFailure<\/span>(<\/span>error<\/span>:<\/span> <\/span>Error<\/span>)<\/span><\/span>\n   <\/span>}<\/span><\/span>\n   <\/span>class<\/span> <\/span>Error<\/span>(<\/span>val<\/span> <\/span>responseCode<\/span>:<\/span> <\/span>Int<\/span>,<\/span> <\/span>val<\/span> <\/span>debugMessage<\/span>:<\/span> <\/span>String<\/span>)<\/span><\/span>\n   <\/span>private<\/span> <\/span>val<\/span> billingClient <\/span>=<\/span> <\/span>BillingClient<\/span><\/span>\n       <\/span>.<\/span>newBuilder<\/span>(<\/span>context<\/span>)<\/span><\/span>\n       <\/span>.<\/span>enablePendingPurchases<\/span>()<\/span><\/span>\n       <\/span>.<\/span>setListener<\/span>(<\/span>this<\/span>)<\/span><\/span>\n       <\/span>.<\/span>build<\/span>()<\/span><\/span>\n   <\/span>fun<\/span> <\/span>queryProducts<\/span>(<\/span>listener<\/span>:<\/span> <\/span>OnQueryProductsListener<\/span>)<\/span> <\/span>{<\/span><\/span>\n       <\/span>val<\/span> skusList <\/span>=<\/span> <\/span>listOf<\/span>(<\/span>"<\/span>premium_sub_month<\/span>"<\/span>,<\/span> <\/span>"<\/span>premium_sub_year<\/span>"<\/span>,<\/span> <\/span>"<\/span>some_inapp<\/span>"<\/span>)<\/span><\/span>\n       queryProductsForType<\/span>(<\/span><\/span>\n           skusList<\/span>,<\/span><\/span>\n           <\/span>BillingClient<\/span>.<\/span>SkuType<\/span>.<\/span>SUBS<\/span><\/span>\n       <\/span>)<\/span> <\/span>{<\/span> billingResult<\/span>,<\/span> skuDetailsList <\/span>-><\/span><\/span>\n           <\/span>if<\/span> <\/span>(<\/span>billingResult<\/span>.<\/span>responseCode <\/span>==<\/span> <\/span>BillingClient<\/span>.<\/span>BillingResponseCode<\/span>.<\/span>OK<\/span>)<\/span> <\/span>{<\/span><\/span>\n               <\/span>val<\/span> products <\/span>=<\/span> skuDetailsList <\/span>?:<\/span> <\/span>mutableListOf<\/span>()<\/span><\/span>\n               queryProductsForType<\/span>(<\/span><\/span>\n                   skusList<\/span>,<\/span><\/span>\n                   <\/span>BillingClient<\/span>.<\/span>SkuType<\/span>.<\/span>INAPP<\/span><\/span>\n               <\/span>)<\/span> <\/span>{<\/span> billingResult<\/span>,<\/span> skuDetailsList <\/span>-><\/span><\/span>\n                   <\/span>if<\/span> <\/span>(<\/span>billingResult<\/span>.<\/span>responseCode <\/span>==<\/span> <\/span>BillingClient<\/span>.<\/span>BillingResponseCode<\/span>.<\/span>OK<\/span>)<\/span> <\/span>{<\/span><\/span>\n                       products<\/span>.<\/span>addAll<\/span>(<\/span>skuDetailsList <\/span>?:<\/span> <\/span>listOf<\/span>())<\/span><\/span>\n                       listener<\/span>.<\/span>onSuccess<\/span>(<\/span>products<\/span>)<\/span><\/span>\n                   <\/span>}<\/span> <\/span>else<\/span> <\/span>{<\/span><\/span>\n                       listener<\/span>.<\/span>onFailure<\/span>(<\/span><\/span>\n                           <\/span>Error<\/span>(<\/span>billingResult<\/span>.<\/span>responseCode<\/span>,<\/span> billingResult<\/span>.<\/span>debugMessage<\/span>)<\/span><\/span>\n                       <\/span>)<\/span><\/span>\n                   <\/span>}<\/span><\/span>\n               <\/span>}<\/span><\/span>\n           <\/span>}<\/span> <\/span>else<\/span> <\/span>{<\/span><\/span>\n               listener<\/span>.<\/span>onFailure<\/span>(<\/span><\/span>\n                   <\/span>Error<\/span>(<\/span>billingResult<\/span>.<\/span>responseCode<\/span>,<\/span> billingResult<\/span>.<\/span>debugMessage<\/span>)<\/span><\/span>\n               <\/span>)<\/span><\/span>\n           <\/span>}<\/span><\/span>\n       <\/span>}<\/span><\/span>\n   <\/span>}<\/span><\/span>\n   <\/span>private<\/span> <\/span>fun<\/span> <\/span>queryProductsForType<\/span>(<\/span><\/span>\n       <\/span>skusList<\/span>:<\/span> <\/span>List<\/span><<\/span>String<\/span>><\/span>,<\/span><\/span>\n       <\/span>@BillingClient.SkuType<\/span> <\/span>type<\/span>:<\/span> <\/span>String<\/span>,<\/span><\/span>\n       <\/span>listener<\/span>:<\/span> <\/span>SkuDetailsResponseListener<\/span><\/span>\n   <\/span>)<\/span> <\/span>{<\/span><\/span>\n       onConnected <\/span>{<\/span><\/span>\n           billingClient<\/span>.<\/span>querySkuDetailsAsync<\/span>(<\/span><\/span>\n               <\/span>SkuDetailsParams<\/span>.<\/span>newBuilder<\/span>().<\/span>setSkusList<\/span>(<\/span>skusList<\/span>).<\/span>setType<\/span>(<\/span>type<\/span>).<\/span>build<\/span>(),<\/span><\/span>\n               listener<\/span><\/span>\n           <\/span>)<\/span><\/span>\n       <\/span>}<\/span><\/span>\n   <\/span>}<\/span><\/span>\n   <\/span>private<\/span> <\/span>fun<\/span> <\/span>onConnected<\/span>(<\/span>block<\/span>:<\/span> <\/span>()<\/span> <\/span>-><\/span> <\/span>Unit<\/span>)<\/span> <\/span>{<\/span><\/span>\n       billingClient<\/span>.<\/span>startConnection<\/span>(<\/span>object<\/span> <\/span>:<\/span> <\/span>BillingClientStateListener<\/span> {<\/span><\/span>\n           override fun onBillingSetupFinished<\/span>(<\/span>billingResult<\/span>:<\/span> <\/span>BillingResult<\/span>)<\/span> {<\/span><\/span>\n               block<\/span>()<\/span><\/span>\n           }<\/span><\/span>\n           override fun onBillingServiceDisconnected<\/span>()<\/span> {<\/span><\/span>\n               <\/span>\/\/<\/span> <\/span>Try<\/span> to restart the connection on the next request to<\/span><\/span>\n               <\/span>\/\/<\/span> <\/span>Google<\/span> <\/span>Play<\/span> by calling the startConnection<\/span>()<\/span> method<\/span>.<\/span><\/span>\n           }<\/span><\/span>\n       }<\/span>)<\/span><\/span>\n   <\/span>}<\/span><\/span>\n   <\/span>override<\/span> <\/span>fun<\/span> <\/span>onPurchasesUpdated<\/span>(<\/span>billingResult<\/span>:<\/span> <\/span>BillingResult<\/span>,<\/span> <\/span>purchaseList<\/span>:<\/span> <\/span>MutableList<\/span><<\/span>Purchase<\/span>><\/span>?<\/span>)<\/span> <\/span>{<\/span><\/span>\n       <\/span>\/\/ here come callbacks about new purchases<\/span><\/span>\n   <\/span>}<\/span><\/span>\n}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n

Lassen Sie uns nun mit der Kaufimplementierung fortfahren und unsere Klasse verbessern.<\/p>\n\n\n\n\n\n

Das Design eines Abonnement-Screens<\/h2>\n\n\n\n

Jede App mit In-App-K\u00e4ufen hat einen Paywall-Screen. Es gelten Google-Richtlinien<\/a>, die das Minimum an Elementen und Anleitungstexten definieren und in solchen Screens ersichtlich sein m\u00fcssen. Wir fassen uns kurz und stellen sie Ihnen zusammenfassend vor. Im Paywall-Screen m\u00fcssen Sie explizit Ihre Abonnement-Bedingungen erl\u00e4utern. Dazu geh\u00f6ren die Kosten, die Dauer und ob das Abonnement notwendig ist, um die App nutzen zu k\u00f6nnen. Sie m\u00fcssen vermeiden, dass Nutzer zus\u00e4tzliche Schritte unternehmen m\u00fcssen, um jene Bedingungen einsehen zu k\u00f6nnen. Sie m\u00fcssen direkt ersichtlich sein. <\/p>\n\n\n\n

Hier nutzen wir einen vereinfachten Paywall-Screen als Beispiel.<\/p>\n\n\n

\n
\"\"
Android Sample Paywall<\/em><\/figcaption><\/figure><\/div>\n\n\n

Wir haben die folgenden Elemente auf unserem Paywall-Screen:<\/p>\n\n\n\n