You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

应用内购买(In App Purchases):如何处理卡牌游戏内购按钮二次点击?

解决Android内购按钮二次点击问题的实用方案

嘿,针对你卡牌游戏里内购按钮的二次点击问题,这里有几个贴合你场景的解决方案,帮你避免重复发起购买请求:

1. 点击后立即禁用按钮,请求完成后恢复

这是最直接有效的方式——用户点击按钮后,立刻把按钮置为不可点击状态,直到整个内购请求流程(查询SKU、购买操作等)完成(无论成功、失败还是用户取消),再恢复按钮的可点击性。

结合你的代码片段,修改后的示例如下:

go = (Button)findViewById(R.id.go); 
go.setOnClickListener(new View.OnClickListener() { 
    @Override 
    public void onClick(View view) { 
        // 第一步:点击后立即禁用按钮,防止重复触发
        go.setEnabled(false);
        
        ArrayList<String> skuList = new ArrayList<>(); 
        skuList.add(inappid); 
        Bundle querySkus = new Bundle(); 
        querySkus.putStringArrayList("ITEM_ID_LIST", skuList); 
        
        // 假设你使用的是Google Play Billing的旧版服务接口
        mService.querySkuDetails(3, getPackageName(), "inapp", querySkus, new IInAppBillingService.Stub() {
            @Override
            public int onQuerySkuDetailsFinished(int responseCode, Bundle skuDetails) throws RemoteException {
                // 关键:不管请求成功还是失败,都要恢复按钮状态
                go.setEnabled(true);
                
                if (responseCode == 0) { // 旧版响应码OK为0
                    ArrayList<String> responseList = skuDetails.getStringArrayList("DETAILS_LIST");
                    // 这里继续处理购买流程,比如拉起购买对话框
                } else {
                    // 处理查询失败的逻辑,比如提示用户网络问题
                }
            }
        });
        
        // 如果是新版BillingClient(v4+),在对应的回调方法最后恢复按钮即可
        // 比如在onSkuDetailsResponse、onPurchasesUpdated中添加go.setEnabled(true);
    } 
});

注意:如果用户在购买过程中取消了操作,也要确保按钮能重新启用,所以要在所有可能结束流程的回调里都加上恢复按钮的代码。

2. 添加点击防抖逻辑(防快速重复点击)

如果你不想完全禁用按钮,只是想防止短时间内的重复点击,可以添加一个时间间隔判断:记录上次点击的时间,当新的点击和上次点击间隔小于设定值(比如500ms)时,直接忽略本次点击。

示例代码:

go = (Button)findViewById(R.id.go); 
// 定义一个变量记录上次点击时间
private long lastPurchaseClickTime = 0;
private static final long CLICK_INTERVAL = 500; // 间隔500ms

go.setOnClickListener(new View.OnClickListener() { 
    @Override 
    public void onClick(View view) { 
        long currentTime = System.currentTimeMillis();
        // 判断是否在防抖间隔内
        if (currentTime - lastPurchaseClickTime < CLICK_INTERVAL) {
            return; // 忽略本次点击
        }
        lastPurchaseClickTime = currentTime;
        
        // 后续的SKU查询、购买逻辑和之前一样
        ArrayList<String> skuList = new ArrayList<>(); 
        skuList.add(inappid); 
        Bundle querySkus = new Bundle(); 
        querySkus.putStringArrayList("ITEM_ID_LIST", skuList); 
        // ... 剩余代码
    } 
});

3. 结合内购流程的状态管理

维护一个全局的状态变量,标记当前是否正在处理内购请求。点击按钮时先检查这个状态,如果正在处理就直接返回,否则开始处理并更新状态,流程结束后再重置状态。

示例:

go = (Button)findViewById(R.id.go); 
private boolean isProcessingPurchase = false; // 标记是否正在处理内购

go.setOnClickListener(new View.OnClickListener() { 
    @Override 
    public void onClick(View view) { 
        if (isProcessingPurchase) {
            return; // 正在处理中,忽略点击
        }
        isProcessingPurchase = true; // 更新状态为处理中
        
        ArrayList<String> skuList = new ArrayList<>(); 
        skuList.add(inappid); 
        Bundle querySkus = new Bundle(); 
        querySkus.putStringArrayList("ITEM_ID_LIST", skuList); 
        
        mService.querySkuDetails(3, getPackageName(), "inapp", querySkus, new IInAppBillingService.Stub() {
            @Override
            public int onQuerySkuDetailsFinished(int responseCode, Bundle skuDetails) throws RemoteException {
                isProcessingPurchase = false; // 重置状态
                
                if (responseCode == 0) {
                    // 处理购买逻辑
                } else {
                    // 处理失败
                }
            }
        });
    } 
});

推荐你优先使用第一种方案,因为它能从根本上避免用户在流程进行中重复操作,体验更清晰;如果需要保留按钮的视觉状态,再结合第二种或第三种方案。

内容的提问来源于stack exchange,提问作者Jolle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 04:00:45