---
title: "Compras no aplicativo para Android, parte 1: configuração e adição ao projeto."
description: "Neste artigo, vamos mostrar como criar um produto e assinaturas no Play Market, incluir preços e opções de assinatura, e como receber a lista de produtos."
url: "https://adapty.io/pt/blog/android-in-app-subscriptions-part-1/"
language: "pt"
slug: "android-in-app-subscriptions-part-1"
category: "adapty-updates"
date: "2021-01-27T00:00:00.000Z"
date_modified: "2021-01-27T00:00:00.000Z"
author: "Vlad Guriev"
---

# Compras no aplicativo para Android, parte 1: configuração e adição ao projeto.

As compras no aplicativo (in-app purchases), especialmente as assinaturas, são os métodos mais populares de monetizar um aplicativo (app). Por um lado, uma assinatura permite a um desenvolvedor investir no desenvolvimento do conteúdo e do produto, por outro, ajuda os usuários a obter um aplicativo, em geral, de mais alta qualidade. As compras no aplicativo [estão sujeitas a 30% de comissão](https://support.google.com/googleplay/android-developer/answer/112622?hl=en), mas se um usuário é assinante há mais de um ano ou um aplicativo [ganha menos de US$1 milhão por ano](https://support.google.com/googleplay/android-developer/answer/10632485), a comissão é de 15%.

Neste artigo, explicaremos como proceder:

- Crie um produto no Google Play Console;
- Configure as assinaturas: especifique duração, preço, períodos de avaliação (trials);
- Adicione uma lista de produtos em um aplicativo.

## Como criar uma assinatura

Antes de começarmos, verifique se você:

1. Tem [uma conta de desenvolvedor no Google Play](https://support.google.com/googleplay/android-developer/answer/7161426?hl=en).
2. Assinou todos os acordos e está pronto para começar a trabalhar.

Agora, vamos ao que interessa: criar nosso primeiro produto.

Entre na sua [conta de desenvolvedor](https://play.google.com/apps/publish) e escolha o aplicativo.

![](https://adapty.io/wp-content/uploads/2023/01/60fef7a69f036b3bfc996258_jsaoezesquwst5gknnib6kc3xqckd8yldedvgpfkaagrqbg9xksbckpwo-g7ypda7kelwc_zzkmwkt2powjgjwok3yphfxvmaquf6fhiqrqtyz06nuu5yfdyta502n1saakxczfz.png)

Em seguida, no menu à esquerda, encontre a seção Produtos, selecione *Subscriptions* e depois clique em *Create a Subscription*.

![60fef7a7b3b5c7c37e286978 qy go34alibtdmnfdkaii3wg1fcjv5bexstyoefeazq 2oagsnx37gndqykcx6rcwcyu7ahpfzug gusku2bg0sxtq nkmglkw5uuvlabnnlnmp7j2ljfc9 nkzhyhbhegp1nl8r](https://adapty.io/wp-content/uploads/2023/01/60fef7a7b3b5c7c37e286978_qy-go34alibtdmnfdkaii3wg1fcjv5bexstyoefeazq_2oagsnx37gndqykcx6rcwcyu7ahpfzug_gusku2bg0sxtq-nkmglkw5uuvlabnnlnmp7j2ljfc9-nkzhyhbhegp1nl8r.png)

Depois, veremos o configurador de assinaturas. Seguem alguns pontos importantes.

![](https://adapty.io/wp-content/uploads/2023/01/60fef7a7d069f50dac0202a5_edgfvm0dhtqew-hin9r1uqwvyzuzna1nw4auk-hsl8kvgoc2uev8ulj5yhinnvdwv6xau1c1kzy2vd0fmpc8ezyurr3vtl-1qbj19ewbfwqspewed3d_echiz1gjqfrfpeiwm0yb.png)

1. Crie o ID *que será usado no aplicativo.* É uma boa ideia adicionar um período de assinatura ou alguma outra informação útil para identificar; assim, você pode criar produtos em um estilo, e facilitar a análise das estatísticas de vendas.
2. O nome da assinatura que o usuário verá na loja.
3. Descrição da assinatura. O usuário também a verá.

![](https://adapty.io/wp-content/uploads/2023/01/60fef7a755430242d074b04c_5mix72nt8rn7nbjrkxd7l7pfit6yuebw9f8x0bke47mx1pbvvagpf4uar-w_dlkpkkfl9q7udzodqctd451avnwnvqccvtmz0wwj90f8md8mbmrl464wo-ljps2wriusg8ax8p1c.png)

Role para baixo e escolha o período de assinatura. No nosso caso, é uma semana. Defina o preço.

![](https://adapty.io/wp-content/uploads/2023/01/60fef7a8d11d44258c894e7d_658mke-hovj_itrvd6mamegcdp6wvefdt0bdamvvssnwg0cca-hwzr7wcgvm9sxf7f6a5iipl2xuaxm9hwznynmah1ad4n7ttsl4uxjpt29aimx2swzisoplqaxcj5avpepiocum.png)

Normalmente, você define o preço na moeda básica da conta, e o sistema converte o preço automaticamente. Mas você também pode editar o preço para um país específico de modo manual.

Observe que o Google mostra o imposto para cada país. É ótimo, porque o App Store Connect não faz isso.

![](https://adapty.io/wp-content/uploads/2023/01/60fef7a7ebfe90328d0a6a28_3k-q7t5g7luv4axvw25thwlj3aibgsnnkahdtfeleaba31hqwgvo1yin2qayyh1r97tp4p_nyvavypbvrt2-9caldi51tr15xhj4tamhq6kuluec5gikmuya1irmfzibqu79mfj1.png)

Desça e escolha (se necessário):

1. Período de avaliação gratuito.
2. Preço inicial, que é uma oferta para os primeiros períodos de pagamento.
3. Período de carência (Grace period). Caso um usuário tenha problemas de pagamento, você ainda pode dar a ele acesso *premium* por alguns dias.
4. Uma oportunidade de se inscrever novamente na Play Store, e não no aplicativo, após o cancelamento.

## Comparação entre o processo de compra no Play Console e App Store Connect

Independentemente do fato de que as assinaturas são monetizadas mais efetivamente no iOS, o sistema administrativo da Play Console é mais prático, é mais bem organizado e localizado, e funciona com maior rapidez.

O processo de criação do produto é realizado da maneira mais simples possível. [Aqui](https://adapty.io/blog/ios-in-app-purchases-1/) explicamos como criar produtos no iOS.

## Obtenção de uma lista de produtos em um aplicativo

Uma vez criados os produtos, vamos trabalhar na arquitetura para aceitar e processar as compras. Em geral, o processo é assim:

1. Adicione uma Biblioteca de Faturamento.
2. Desenvolva uma classe para interação com produtos do Google Play.
3. Implemente todos os métodos para processar compras.
4. Adicione a validação do servidor para uma compra.
5. Colete dados de analytics.

Nesta parte, vamos analisar de modo mais detalhado os dois primeiros pontos.

Como adicionar uma biblioteca de faturamento a um projeto:

```kotlin
implementation "com.android.billingclient:billing:4.0.0"
```

*No momento desta publicação, a versão mais recente é a 4.0.0. Você pode substitui-la por qualquer outra versão a qualquer momento.  *

Vamos criar uma classe de wrapper que cobrirá a lógica de interação com o Google Play e iniciar o BillingClient a partir da Biblioteca de Faturamento nela contida. Vamos chamar esta classe de BillingClientWrapper.

Esta classe implementará a interface PurchasesUpdatedListener. Vamos agora substituir um método para isso – *onPurchasesUpdated(billingResult: BillingResult, purchaseList: MutableList<Purchase>?)* é necessário logo após a realização de uma compra, mas descreveremos o processo de implementação no próximo artigo.

```kotlin
import android.content.Context
import com.android.billingclient.api.*

class BillingClientWrapper(context: Context) : PurchasesUpdatedListener {

   private val billingClient = BillingClient
       .newBuilder(context)
       .enablePendingPurchases()
       .setListener(this)
       .build()

   override fun onPurchasesUpdated(billingResult: BillingResult, purchaseList: MutableList<Purchase>?) {
       // here come callbacks about new purchases
   }
}
```

Google [recomenda](https://developer.android.com/google/play/billing/integrate#initialize) evitar ter mais de uma conexão ativa entre o BillingClient e o Google Play para evitar que um retorno de chamada sobre uma compra realizada seja executada várias vezes. Assim, você deve ter um único BillingClient em uma em uma classe singleton. A classe no exemplo não é um singleton, mas podemos usar a [injeção de dependência](https://en.wikipedia.org/wiki/Dependency_injection) (por exemplo, com a ajuda de [Dagger](https://developer.android.com/training/dependency-injection/dagger-android) ou [Koin](https://insert-koin.io/docs/quickstart/android/)) neste sentido, permitindo que apenas uma instância exista em um único momento no tempo.

Para fazer qualquer solicitação com a Biblioteca de Faturamento, o BillingClient deve ter uma conexão ativa com o Google Play no momento em que a solicitação está sendo feita, mas a conexão pode ser perdida em algum momento. Por uma questão de praticidade, vamos escrever um wrapper que nos permita fazer qualquer solicitação somente quando a conexão estiver ativa.

Para obter os produtos, precisamos das IDs que definimos no mercado. Mas não é suficiente para uma solicitação, precisamos também do tipo de produto (assinaturas ou compras pontuais), por isso podemos obter uma lista geral de produtos "combinando" os resultados de duas solicitações.

A solicitação de produtos é assíncrona, portanto, precisamos de um retorno de chamada que nos forneça uma lista de produtos ou retorne um modelo de erro. Quando ocorre um erro, a Biblioteca de Faturamento [retorna](https://developer.android.com/reference/com/android/billingclient/api/BillingResult) um de seus [BillingResponseCodes](https://developer.android.com/reference/com/android/billingclient/api/BillingClient.BillingResponseCode#summary), bem como uma debugMessage. Vamos criar uma interface de retorno de chamada e um modelo para um erro:

```kotlin
interface OnQueryProductsListener {
  fun onSuccess(products: List < SkuDetails > )
  fun onFailure(error: Error)
}

class Error(val responseCode: Int, val debugMessage: String)
```

Segue o código de um método privado para obter dados sobre um tipo específico de produtos e um método público que irá "combinar" os resultados de duas solicitações e fornecer a um usuário a lista final de produtos ou exibir uma mensagem de erro.

```kotlin
fun queryProducts(listener: OnQueryProductsListener) {
   val skusList = listOf("premium_sub_month", "premium_sub_year", "some_inapp")

   queryProductsForType(
       skusList,
       BillingClient.SkuType.SUBS
   ) { billingResult, skuDetailsList ->
       if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
           val products = skuDetailsList ?: mutableListOf()
           queryProductsForType(
               skusList,
               BillingClient.SkuType.INAPP
           ) { billingResult, skuDetailsList ->
               if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
                   products.addAll(skuDetailsList ?: listOf())
                   listener.onSuccess(products)
               } else {
                   listener.onFailure(
                       Error(billingResult.responseCode, billingResult.debugMessage)
                   )
               }
           }
       } else {
           listener.onFailure(
               Error(billingResult.responseCode, billingResult.debugMessage)
           )
       }
   }
}

private fun queryProductsForType(
   skusList: List<String>,
   @BillingClient.SkuType type: String,
   listener: SkuDetailsResponseListener
) {
   onConnected {
       billingClient.querySkuDetailsAsync(
           SkuDetailsParams.newBuilder().setSkusList(skusList).setType(type).build(),
           listener
       )
   }
}
```

Assim, conseguimos informações valiosas sobre os produtos ([SkuDetails](https://developer.android.com/reference/com/android/billingclient/api/SkuDetails)) onde podemos ver nomes localizados, preços, tipo de produto, assim como período de cobrança e informações sobre preço inicial e período de avaliação (se estiver disponível para este usuário) de assinaturas. Veja como é a classe final:

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

Por hoje é isso. Nos próximos artigos, vamos tratar da implementação da compra, realização de testes e tratamento de erros.
