应用内购买(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
相关产品推荐
相关产品推荐

