首页 > Java > java教程 > 正文

Android应用内购:在Java中实现用户订阅状态的准确检查

碧海醫心
发布: 2025-11-28 18:46:11
原创
136人浏览过

Android应用内购:在Java中实现用户订阅状态的准确检查

本教程详细阐述了如何在android应用中,使用google play billing library的`querypurchasesasync()`方法来检查用户的现有订阅状态,尤其是在应用启动时。文章将解释该方法与实时购买事件监听器(`purchasesupdatedlistener`)的区别,并提供完整的代码示例和最佳实践,确保用户订阅状态的准确性与安全性。

在Android应用中,管理用户订阅状态是实现内购功能的核心环节。当用户购买了订阅服务后,应用需要能够随时查询并验证该订阅的有效性,而不仅仅是在购买流程完成的当下。例如,当用户重新打开应用时,应用需要知道用户是否仍然拥有有效的订阅。

Google Play Billing Library 提供了两种主要机制来处理购买信息:

  1. PurchasesUpdatedListener: 用于监听实时发生的购买事件,例如用户完成新的购买流程或取消支付。
  2. queryPurchasesAsync(): 用于查询用户当前已拥有的所有有效购买(包括订阅)。这是在应用启动或需要验证用户现有订阅状态时应使用的主要方法。

核心方法:查询现有订阅 queryPurchasesAsync()

queryPurchasesAsync() 方法是专门设计用来检索与用户Google账户关联的所有有效购买(包括订阅和非消耗性商品)的。它是一个异步操作,通过回调 PurchasesResponseListener 返回查询结果。

实现步骤与代码示例

在使用 queryPurchasesAsync() 之前,请确保您的 BillingClient 实例已正确初始化并连接到 Google Play 服务。

立即学习Java免费学习笔记(深入)”;

怪兽智能全息舱
怪兽智能全息舱

专业的AI数字人平台,定制数字人专属IP

怪兽智能全息舱 16
查看详情 怪兽智能全息舱
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());
            }
        });
    }
    */
}
登录后复制

代码解释:

  • QueryPurchasesParams.newBuilder().setProductType(BillingClient.ProductType.SUBS).build(): 指定我们只查询订阅类型的商品。
  • PurchasesResponseListener: 这是 queryPurchasesAsync 的回调接口,它接收 BillingResult 和一个 Purchase 列表。
  • billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK: 检查查询操作本身是否成功。
  • purchase.getProducts().contains("your_subscription_product_id"): 这一步至关重要,它确保我们检查的是我们关心的特定订阅商品。务必将 "your_subscription_product_id" 替换为您的实际商品ID。
  • purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED: 验证购买的状态是否为“已购买”。
  • purchase.isAcknowledged(): 对于所有购买(包括订阅),Google Play 都要求进行确认。如果 isAcknowledged() 返回 false,则需要调用 acknowledgePurchase() 方法进行确认。未确认的购买将在3天后自动退款
  • acknowledgePurchase(purchase): 这是一个辅助方法,用于执行购买确认操作。

何时调用 checkSubscriptionStatus()?

为了确保用户订阅状态的及时性和准确性,您应该在以下关键时刻调用 checkSubscriptionStatus() 方法:

  1. 应用启动时: 在主 Activity 的 onResume() 方法中或应用初始化流程中调用,确保用户进入应用时,其订阅状态是最新的。
  2. 从后台返回前台时: 同样可以在 onResume() 中处理,以防用户在应用处于后台期间订阅状态发生变化(例如,订阅到期或在其他设备上取消)。
  3. 用户尝试访问受限内容时: 在用户尝试访问仅限订阅用户可用的高级功能之前进行检查。
  4. 网络恢复时: 如果应用在离线状态下启动,当网络连接恢复后,应重新检查订阅状态。
  5. BillingClient 连接成功后: 确保 BillingClient 已准备就绪且连接成功。

PurchasesUpdatedListener 的角色

虽然 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 逻辑,通常用于处理可消耗商品,不适用于订阅。

重要注意事项与最佳实践

  1. 购买确认 (Acknowledgement): 这是Google Play Billing中最关键的环节之一。所有购买(包括订阅和非消耗性商品)都必须在购买成功后的3天内通过 acknowledgePurchase() 方法进行确认。如果未在规定时间内确认,Google Play 将自动退款给用户,并且购买会被撤销。
  2. 服务器端验证: 尽管客户端可以检查订阅状态,但为了防止作弊和提供更强大的安全性,强烈建议在您的后端服务器上

以上就是Android应用内购:在Java中实现用户订阅状态的准确检查的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号