Participe do evento ⁠#Android11: apresentação de lançamento da versão Beta no dia 3 de junho.

Guia de migração da AIDL para a Google Play Billing Library

Este tópico descreve como migrar de uma integração do Google Play Faturamento que usa a Linguagem de definição de interface do Android (AIDL, na sigla em inglês). O acesso ao Google Play Faturamento usando AIDL está suspenso e todas as integrações passarão a usar a Google Play Billing Library no futuro.

Etapas da migração

Importar a Google Play Billing Library

Primeiro, adicione uma dependência à Google Play Billing Library. Se você estiver usando o Gradle, é possível adicionar o seguinte ao arquivo build.gradle do seu app:

dependencies {
        implementation 'com.android.billingclient:billing:2.2.0'
    }
    

Você pode excluir qualquer código "agrupador", como IabHelper (link em inglês), que pode ter sido copiado do código de referência anterior. A funcionalidade oferecida pelo IabHelper agora faz parte da Google Play Billing Library.

Remover a permissão com.android.vending.BILLING

A Google Play Billing Library inclui a permissão com.android.vending.BILLING no manifesto. Não é mais necessário adicionar essa permissão explicitamente no manifesto do seu app.

Conectar-se ao Google Play Faturamento

O BillingClient da Google Play Billing Library processa o gerenciamento de conexão para você. Para migrar, faça as seguintes mudanças no seu app:

Os exemplos a seguir mostram a possível aparência do app antes e depois dessas mudanças:

Antes

mServiceConn = new ServiceConnection() {
        @Override
        public void onServiceDisconnected(ComponentName name) {
          ...
        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
          ...
        }
    };

    Intent serviceIntent = new Intent("com.android.vending.billing.InAppBillingService.BIND");
    serviceIntent.setPackage("com.android.vending");
    List<ResolveInfo> intentServices = mContext.getPackageManager()
        .queryIntentServices(serviceIntent, 0);
    if (intentServices != null && !intentServices.isEmpty()) {
        mContext.bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE);
    } else {
        // Handle errors.
        ...
    }

    ...

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        IabResult result;
        if (requestCode != mRequestCode || data == null) {
            // Handle errors.
            ...
        }

        int responseCode = getResponseCodeFromIntent(data);
        String purchaseData = data.getStringExtra(RESPONSE_INAPP_PURCHASE_DATA);
        String dataSignature = data.getStringExtra(RESPONSE_INAPP_SIGNATURE);

        if (resultCode != Activity.RESULT_OK || responseCode != BILLING_RESPONSE_RESULT_OK) {
            // Handle errors.
            ...
        }

        // Process successful purchase.
        ...

        return true;
    }
    

Depois

Kotlin

    class MyBillingImpl(private var billingClient: BillingClient) : PurchasesUpdatedListener {

        init {
            billingClient = BillingClient.newBuilder(activity).setListener(this).build()
            billingClient.startConnection(object : BillingClientStateListener {
                override fun onBillingSetupFinished(billingResult: BillingResult?) {
                    // Logic from ServiceConnection.onServiceConnected should be moved here.
                }

                override fun onBillingServiceDisconnected() {
                    // Logic from ServiceConnection.onServiceDisconnected should be moved here.
                }
            })
        }

        override fun onPurchasesUpdated(
            billingResult: BillingResult?,
            purchases: MutableList<Purchase>?
        ) {
            // Logic from onActivityResult should be moved here.
        }
    }
    

Java

    public class MyBillingImpl implements PurchasesUpdatedListener {
        private BillingClient billingClient;
        ...

        public void initialize() {
            billingClient = BillingClient.newBuilder(activity).setListener(this).build();
            billingClient.startConnection(new BillingClientStateListener() {
                @Override
                public void onBillingSetupFinished(BillingResult billingResult) {
                    // Logic from ServiceConnection.onServiceConnected should be moved here.
                }

                @Override
                public void onBillingServiceDisconnected() {
                    // Logic from ServiceConnection.onServiceDisconnected should be moved here.
                }
            });
        }

        @Override
        public void onPurchasesUpdated(
            @BillingResponse int responseCode, @Nullable List<Purchase> purchases) {
            // Logic from onActivityResult should be moved here.
        }
    }
    

Fazer uma compra

Para iniciar a caixa de diálogo de compras, faça o seguinte:

Os exemplos a seguir mostram a possível aparência do app antes e depois dessas mudanças:

Antes

// Query Skus
    String skuToSell = "premium_upgrade";
    ArrayList<String> skus = new Arraylist<>();
    skus.add(skuToSell);
    Bundle querySkus = new Bundle();
    querySkus.putStringArrayList(GET_SKU_DETAILS_ITEM_LIST, skus);
    Bundle skuDetails = mService.getSkuDetails(3,
                                               mContext.getPackageName(),
                                               itemType,
                                               querySkus);

    if (!skuDetails.containsKey(RESPONSE_GET_SKU_DETAILS_LIST)) {
        // Handle errors.
        ...
    }

    // Launch Buy Flow
    Bundle buyIntentBundle = mService.getBuyIntent(3,
                                                   mContext.getPackageName(),
                                                   skuToSell,
                                                   "Inapp",
                                                   "");

    int response = getResponseCodeFromBundle(buyIntentBundle);
    if (response != BILLING_RESPONSE_RESULT_OK) {
        // Handle errors.
        ...
    }

    PendingIntent pendingIntent = buyIntentBundle.getParcelable(RESPONSE_BUY_INTENT);
    act.startIntentSenderForResult(pendingIntent.getIntentSender(),
                                   requestCode,
                                   new Intent(),
                                   Integer.valueOf(0),
                                   Integer.valueOf(0),
                                   Integer.valueOf(0));

    // Purchase is handled in onActivityResult illustrated in the previous section.
    

Depois

Kotlin

    val skuToSell = "premium_upgrade"
    val skuList = mutableListOf<String>()
    skuList.add(skuToSell)
    val params = SkuDetailsParams.newBuilder()
    params.setSkusList(skuList).setType(BillingClient.SkuType.INAPP)
    billingClient.querySkuDetailsAsync(params.build(),
      object : SkuDetailsResponseListener {
        override fun onSkuDetailsResponse(
          billingResult: BillingResult?, skuDetailsList: MutableList<SkuDetails>?) {
            // Process the result.
            }
        })

    // SkuDetails object obtained above.
    val skuDetails = ...
    val purchaseParams = BillingFlowParams.newBuilder()
      .setSkuDetails(skuDetails)
       .build()

    billingClient.launchBillingFlow(activity, purchaseParams)

    // Purchase is handled in onPurchasesUpdated illustrated in the previous section
    

Java

    String skuToSell = "premium_upgrade";
    List<String> skuList = new ArrayList<> ();
    skuList.add(skuToSell);
    SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
    params.setSkusList(skuList).setType(SkuType.INAPP);
    billingClient.querySkuDetailsAsync(params.build(),
        new SkuDetailsResponseListener() {
            @Override
            public void onSkuDetailsResponse(BillingResult billingResult,
                                             List<SkuDetails> skuDetailsList) {
                // Process the result.
                ...
            }
        });

    // SkuDetails object obtained above.
    SkuDetails skuDetails = ...;

    BillingFlowParams purchaseParams =
        BillingFlowParams.newBuilder()
                .setSkuDetails(skuDetails)
                .build();

    mBillingClient.launchBillingFlow(mActivity, purchaseParams);

    // Purchase is handled in onPurchasesUpdated illustrated in the previous section.
    

Consumir compras

Para consumir compras usando a Google Play Billing Library, faça o seguinte:

Os exemplos a seguir mostram a possível aparência do app antes e depois dessas mudanças:

Antes

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        int responseCode = data.getIntExtra(RESPONSE_CODE);
        JSONObject purchaseData =
            new JSONObject(data.getStringExtra("INAPP_PURCHASE_DATA"));

        String token = purchaseData.get("purchaseToken");

        ...

        // Consume purchase
        int response = mService.consumePurchase(3, mContext.getPackageName(), token);
        if (response != BILLING_RESPONSE_RESULT_OK) {
            // Handle errors.
            ...
        }

        // Handle successful consumption.
    }
    

Depois

Kotlin

    class MyBillingImpl(private val billingClient: BillingClient) :
            ... , ConsumeResponseListener {

      fun consumePurchase(purchaseToken: String) {
        val consumeParams = ConsumeParams
          .newBuilder()
          .setPurchaseToken(purchaseToken)
          .build()
      }

      override fun onConsumeResponse(
        billingResult: BillingResult?,
        purchaseToken: String?) {
          // Handle consumption
        }
     }
    

Java

    public class MyBillingImpl implements ..., ConsumeResponseListener {
        private BillingClient billingClient;
        ...

        public void consumePurchase(String purchaseToken) {
            ConsumeParams consumeParams =
            ConsumeParams.newBuilder()
                    .setPurchaseToken(purchaseToken)
                    .build();
        }

        @Override
        void onConsumeResponse(BillingResult billingResult, String purchaseToken) {
            // Handle consumption.
            ...
        }
    }
    

Confirmar compras

A partir da versão 2.0 da Google Play Billing Library, o app precisa consumir ou confirmar todas as compras.

Se você não consumir ou confirmar uma compra em até três dias, o Google revogará a compra automaticamente e reembolsará o usuário. Para ver mais informações, consulte Confirmar uma compra.

Reconhecer compras fora do aplicativo

Para migrar o gerenciamento de compras fora do aplicativo para a Google Play Billing Library, faça o seguinte:

Antes, ao integrar o Google Play Faturamento com a AIDL, o app precisava registrar um listener para receber o intent com.android.vending.billing.PURCHASES_UPDATED para gerenciar compras feitas fora do app.

Com a Google Play Billing Library, o primeiro passo para garantir que todas as compras fora do app sejam reconhecidas é sempre chamar queryPurchases() no callback onResume(). Enquanto seu app está em execução, a biblioteca detecta automaticamente as compras fora do aplicativo e envia uma notificação por meio do PurchasesUpdatedListener.

Processar transações pendentes

A partir da versão 2.0 da Google Play Billing Library, o app precisa processar transações pendentes que exigem outras ações após a compra antes de conceder titularidade. Por exemplo, um usuário pode escolher comprar seu produto em uma loja física com dinheiro. Isso significa que a transação será concluída fora do seu app. Em casos como esse, a titularidade só pode ser concedida após o usuário ter concluído a transação.

Para ver mais informações, consulte Compatibilidade com transações pendentes.

Payload do desenvolvedor

Historicamente, o payload do desenvolvedor tem sido usado para várias finalidades, incluindo a prevenção de fraudes e a atribuição de compras ao usuário correto. Considerando que agora a Google Play Billing Library é compatível com esses casos de uso, o uso do payload do desenvolvedor foi suspenso a partir da versão 2.2 dessa biblioteca. Para ver mais informações, consulte payload do desenvolvedor.

Mensagens de erro detalhadas

A partir da versão 2.0 da Google Play Billing Library, todos os erros têm mensagens correspondentes relacionadas à depuração. Você pode ver essas mensagens chamando BillingResult.getDebugMessage().