Всем привет. Я SDK Engineer в Qonversion Мария Бордунова.

Сегодня речь пойдет о библиотеке Google Play Billing Library 4.0.0, которая к концу этого года должна открыть новые возможности для приложений со встроенными покупками. 

Согласно анонсу Google, четвертая версия Billing Library позволит оптимизировать покупки внутри приложений:

  • Появится возможность приобретать несколько расходуемых (consumable) in-app продуктов единовременно. На данный момент можно покупать только 1 единицу продукта за раз. 

  • Пользователь сможет сам определять состав подписки, то есть приобрести несколько продуктов как часть одной подписки.

Подробнее о типах продуктов для продажи внутри приложения можно почитать здесь.  

Так как еще не все перешли на Billing Library v4, я бы хотела рассказать, на что стоит обратить внимание при миграции на новую версию.

Основные изменения в 4-й версии Google Play Billing Library

1. Background & Main: фоновый и главный потоки

Теперь callback-и методов вызываются в фоновом потоке (в предыдущей версии они вызывались из главного).  Чтобы убедиться в этом, можно вывести в лог название текущего потока, например, в методе onBillingSetupFinished интерфейса BillingClientStateListener:

if (Looper.getMainLooper().thread == Thread.currentThread()) {
   Log.d("TestThread", "Main thread is running.")
} else {
   Log.d("TestThread", "${Thread.currentThread().name} thread is running.")
}

В логах можно будет увидеть следующий результат для разных версий библиотеки:

  • Billing Library v4: D/TestThread: PlayBillingLibrary-1 thread is running.

  • Billing Library v3: D/TestThread: Main thread is running.

Если требуется изменить пользовательский интерфейс прямо из callback-а, важно помнить, что взаимодействие с UI невозможно без переключения обратно в главный поток. 

2. queryPurchasesAsync() для извлечения активных покупок пользователя

 Метод queryPurchases() больше не актуален. Теперь, чтобы получить  информацию об активных подписках и нерасходуемых покупках (они же non-consumable) в приложении, нужно использовать метод queryPurchasesAsync():

private fun queryPurchasesAsync() {
   // Fetch active subscriptions and non-consumable in-app purchases
   billingClient.queryPurchasesAsync(BillingClient.SkuType.SUBS, this)
   billingClient.queryPurchasesAsync(BillingClient.SkuType.INAPP, this)
}

Чтобы получить ответ, необходимо реализовать интерфейс PurchasesResponseListener и переопределить его метод onQueryPurchasesResponse:

/**
* Callback that will be called when queryPurchasesAsync is called
*/
override fun onQueryPurchasesResponse(
   billingResult: BillingResult,
   purchases: MutableList<Purchase>
) {
   // process purchases
}

3. Новый способ для downgrade/upgrade подписок

Раньше для обновления подписки необходимо было предоставить значение SkuDetails, sku (он же идентификатор) и токен старой подписки, а также опционально ProrationMode:

private fun updatePurchase(skuDetails: SkuDetails) {
   val params = BillingFlowParams.newBuilder()
       .setSkuDetails(skuDetails)
       .setOldSku("oldSku", "oldPurchaseToken")
       .setReplaceSkusProrationMode(BillingFlowParams.ProrationMode.IMMEDIATE_AND_CHARGE_PRORATED_PRICE)
       .build()
 
   billingClient.launchBillingFlow(this, params)
}

Теперь для выполнения downgrade или upgrade подписки нужно вызвать BillingFlowParams.Builder.setSubscriptionUpdateParams() и передать объект SubscriptionUpdateParams в качестве параметра. Метод setOldSku() был удален.

private fun updatePurchase(skuDetails: SkuDetails) {
   val updateParams = BillingFlowParams.SubscriptionUpdateParams.newBuilder()
       .setOldSkuPurchaseToken("oldPurchaseToken")
       .setReplaceSkusProrationMode(BillingFlowParams.ProrationMode.IMMEDIATE_AND_CHARGE_PRORATED_PRICE)
       .build()
 
   val billingFlowParams = BillingFlowParams.newBuilder()
       .setSkuDetails(skuDetails)
       .setSubscriptionUpdateParams(updateParams)
       .build()
 
   billingClient.launchBillingFlow(this, billingFlowParams)
}

4. Multi-quantity purchases (пока недоступны, ждем релиза)

Google анонсировал планы по оптимизации покупок внутри приложения: пользователям будет доступен выбор нужного количества продуктов прямо из корзины. Из Google Play Console можно будет настроить, какой именно продукт доступен для такой опции.

Это сильно упрощает процессы покупки и продажи. Теперь пользователи смогут купить несколько единиц расходуемого продукта  (они же consumable in-app продукты, например, монетки, мана) в один клик, а не покупать их многократно разными транзакциями. 

Чтобы получить количество купленного продукта, можно использовать новые методы Purchase.getQuantity() и PurchaseHistoryRecord.getQuantity().

5. Multi-line subscriptions (пока недоступны, ждем релиза)

В дополнение к предыдущей фиче, Google  позволит продавать несколько продуктов в рамках одной подписки. Пользователи смогут управлять составом такой подписки в любое время (добавлять, отменять и заменять продукты при оформлении подписки или в процессе ее использования). 

Например, пользователь сможет купить курс по изучению Java, Kotlin, а потом дополнить этот набор Swift.

Чтобы получить идентификаторы продуктов покупки, используйте методы Purchase.getSkus() и PurchaseHistoryRecord.getSkus() (метод getSku() более недоступен). 

Что в итоге? 

Конечно, Google Play Billing Library 4.0.0 здорово оптимизирует процессы покупок внутри приложения. Если говорить о технических деталях, то новшества на мобильной стороне могут показаться не фундаментальными. Но нужно учитывать и изменения на сервере. Например, если вы собираете аналитику по покупкам, в запросе purchase появится новое поле “quantity”; в поле для идентификатора продукта теперь может передаваться массив ids. Также выглядит, что количество запросов на ваш сервер хоть и на малую долю, но уменьшится за счет единовременных покупок. Почитать о прочих изменениях в библиотеке можно в release notes.

Кто уже перешел на Google billing 4.0.0? Какие сложности вы заметили при переходе или использовании? Будет интересно обсудить.

Комментарии (3)


  1. 402d
    22.10.2021 08:34

    queryPurchasesAsync введен в 3й версии библиотеки, билдеры параметров там же. Статья наверное для тех, кто перескочил через тройку.


    1. m_bordunova Автор
      22.10.2021 08:58
      +2

      Добрый день. Метод queryPurchasesAsync и интерфейсPurchasesResponseListenerдоступны с 4-ой версии библиотеки. Возможно, вы имели в виду метод queryPurchaseHistoryAsync в связке с PurchaseHistoryResponseListener, но я их не освящала в этой статье, они остались без изменений.


      1. 402d
        22.10.2021 09:39

        Извините, почему-то был уверен, что сижу на тройке. Заглянул в градле файл, а там 4.0.0