
本教程详细阐述了如何在android应用中,使用google play billing library的`querypurchasesasync()`方法来检查用户的现有订阅状态,尤其是在应用启动时。文章将解释该方法与实时购买事件监听器(`purchasesupdatedlistener`)的区别,并提供完整的代码示例和最佳实践,确保用户订阅状态的准确性与安全性。
在Android应用中,管理用户订阅状态是实现内购功能的核心环节。当用户购买了订阅服务后,应用需要能够随时查询并验证该订阅的有效性,而不仅仅是在购买流程完成的当下。例如,当用户重新打开应用时,应用需要知道用户是否仍然拥有有效的订阅。
Google Play Billing Library 提供了两种主要机制来处理购买信息:
queryPurchasesAsync() 方法是专门设计用来检索与用户Google账户关联的所有有效购买(包括订阅和非消耗性商品)的。它是一个异步操作,通过回调 PurchasesResponseListener 返回查询结果。
在使用 queryPurchasesAsync() 之前,请确保您的 BillingClient 实例已正确初始化并连接到 Google Play 服务。
立即学习“Java免费学习笔记(深入)”;
import android.util.Log;
import com.android.billingclient.api.AcknowledgePurchaseParams;
import com.android.billingclient.api.BillingClient;
import com.android.billingclient.api.BillingResult;
import com.android.billingclient.api.Purchase;
import com.android.billingclient.api.QueryPurchasesParams;
import java.util.List;
public class SubscriptionManager {
private BillingClient billingClient;
private static final String TAG = "SubscriptionManager";
// 构造函数或初始化方法中传入 BillingClient 实例
public SubscriptionManager(BillingClient client) {
this.billingClient = client;
}
/**
* 检查用户当前的订阅状态。
* 此方法应在 BillingClient 连接成功后调用。
*/
public void checkSubscriptionStatus() {
if (billingClient != null && billingClient.isReady()) {
// 查询订阅类型商品
billingClient.queryPurchasesAsync(
QueryPurchasesParams.newBuilder().setProductType(BillingClient.ProductType.SUBS).build(),
(billingResult, purchases) -> {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
boolean hasActiveSubscription = false;
if (purchases != null && !purchases.isEmpty()) {
for (Purchase purchase : purchases) {
// 验证购买状态和商品ID
// 请替换 "your_subscription_product_id" 为您实际的订阅商品ID
if (purchase.getProducts().contains("your_subscription_product_id") &&
purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
// 如果购买未被确认,则需要确认
if (!purchase.isAcknowledged()) {
acknowledgePurchase(purchase);
}
// 购买已确认且状态为已购买,则视为有效订阅
if (purchase.isAcknowledged()) {
hasActiveSubscription = true;
Log.d(TAG, "用户拥有有效订阅: OrderId = " + purchase.getOrderId());
// TODO: 根据您的应用逻辑更新UI或应用状态
// 例如: Constant.subscription = true;
break; // 找到一个有效订阅即可
}
}
}
}
if (!hasActiveSubscription) {
Log.d(TAG, "用户没有有效的订阅。");
// TODO: 根据您的应用逻辑更新UI或应用状态
// 例如: Constant.subscription = false;
}
} else {
Log.e(TAG, "查询订阅失败: " + billingResult.getDebugMessage());
}
}
);
} else {
Log.e(TAG, "BillingClient 未准备好或为空,无法查询订阅。");
}
}
/**
* 辅助方法:确认购买。
* Google Play 要求所有购买(包括订阅)必须在3天内确认。
* 未确认的购买会在3天后自动退款。
*/
private void acknowledgePurchase(Purchase purchase) {
AcknowledgePurchaseParams acknowledgePurchaseParams =
AcknowledgePurchaseParams.newBuilder()
.setPurchaseToken(purchase.getPurchaseToken())
.build();
billingClient.acknowledgePurchase(acknowledgePurchaseParams, billingResult -> {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
Log.d(TAG, "购买已成功确认: OrderId = " + purchase.getOrderId());
// 确认成功后,可以再次触发订阅状态检查或直接更新UI
// checkSubscriptionStatus(); // 重新检查以更新状态
} else {
Log.e(TAG, "购买确认失败: " + billingResult.getDebugMessage());
}
});
}
// 您可能还需要一个方法来处理可消耗商品的消耗逻辑,如果您的应用有此类商品。
// 订阅商品不需要消耗。
/*
void handleConsumablePurchase(Purchase purchase) {
ConsumeParams consumeParams = ConsumeParams.newBuilder()
.setPurchaseToken(purchase.getPurchaseToken())
.build();
billingClient.consumeAsync(consumeParams, (billingResult, purchaseToken) -> {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
Log.d(TAG, "可消耗商品已成功消耗。");
// TODO: 授予用户商品
} else {
Log.e(TAG, "可消耗商品消耗失败: " + billingResult.getDebugMessage());
}
});
}
*/
}为了确保用户订阅状态的及时性和准确性,您应该在以下关键时刻调用 checkSubscriptionStatus() 方法:
虽然 queryPurchasesAsync() 用于查询现有订阅,但 PurchasesUpdatedListener 仍然是处理 新发生购买事件 的关键。当用户完成购买流程(无论是成功、取消还是其他错误)时,此监听器会被触发。
import android.util.Log;
import com.android.billingclient.api.BillingClient;
import com.android.billingclient.api.BillingResult;
import com.android.billingclient.api.Purchase;
import com.android.billingclient.api.PurchasesUpdatedListener;
import java.util.List;
public class MyBillingClientLifecycleManager implements PurchasesUpdatedListener {
private SubscriptionManager subscriptionManager; // 假设您有SubscriptionManager实例
public MyBillingClientLifecycleManager(SubscriptionManager manager) {
this.subscriptionManager = manager;
}
@Override
public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && purchases != null) {
for (Purchase purchase : purchases) {
// 对于新购买的订阅,需要进行确认
if (purchase.getProducts().contains("your_subscription_product_id")) {
// 确认操作应在 SubscriptionManager 中处理
if (!purchase.isAcknowledged()) {
subscriptionManager.acknowledgePurchase(purchase);
}
Log.d("BillingFlow", "新订阅购买成功并处理: OrderId = " + purchase.getOrderId());
// TODO: 更新应用状态,例如 Constant.subscription = true;
}
// 如果是可消耗商品,则需要消耗
// else if (purchase.getProducts().contains("your_consumable_product_id")) {
// subscriptionManager.handleConsumablePurchase(purchase);
// }
}
// 无论新购买成功与否,都建议重新查询一次以同步最新状态
subscriptionManager.checkSubscriptionStatus();
} else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.USER_CANCELED){
Log.d("BillingFlow", "用户取消了购买流程。");
// TODO: 更新应用状态,例如 Constant.subscription = false;
} else {
Log.e("BillingFlow", "购买流程出现错误: " + billingResult.getDebugMessage());
}
}
}注意: 订阅商品不需要像可消耗商品那样进行“消耗”。订阅只需在购买后进行一次“确认”即可。原始问题中 handlePurchase 方法中包含的 consumeAsync 逻辑,通常用于处理可消耗商品,不适用于订阅。
以上就是Android应用内购:在Java中实现用户订阅状态的准确检查的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号