Всем привет. Я 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? Какие сложности вы заметили при переходе или использовании? Будет интересно обсудить.
402d
queryPurchasesAsync введен в 3й версии библиотеки, билдеры параметров там же. Статья наверное для тех, кто перескочил через тройку.
m_bordunova Автор
Добрый день. Метод
queryPurchasesAsync
и интерфейсPurchasesResponseListener
доступны с 4-ой версии библиотеки. Возможно, вы имели в виду метод queryPurchaseHistoryAsync в связке с PurchaseHistoryResponseListener, но я их не освящала в этой статье, они остались без изменений.402d
Извините, почему-то был уверен, что сижу на тройке. Заглянул в градле файл, а там 4.0.0