google In-App Biling接入
1.productId列表,游戏启动的时候传入并记录,方便后续检索
static List<String> AllProductIds = new ArrayList<String>();
2.Purchase列表,暂时存储Purchase对象,等待上层逻辑指示
static Vector<Purchase> InventoryList = new Vector<Purchase>();
3.初始化IAB,提供给Unity上层调用的接口。传入许可密钥和产品Id列表,初始化IabHelper,调用queryInventoryAsync()查询订单状态
public void initIAB(final String base64EncodedPublicKey, final String productIds) { Log.i(TAG, "IAB=== initIAB called."); mHelper=new IabHelper(this, base64EncodedPublicKey); mHelper.enableDebugLogging(true); mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener()
{ public void onIabSetupFinished(IabResult result)
{ Log.i(TAG, "IAB=== Setup finished."); if (!result.isSuccess())
{ // Oh noes, there was a problem. complain("Problem setting up in-app billing: " + result); return; } mBroadcastReceiver = new IabBroadcastReceiver(IABEntryActivity.this); IntentFilter broadcastFilter = new IntentFilter(IabBroadcastReceiver.ACTION); registerReceiver(mBroadcastReceiver, broadcastFilter); AllProductIds = new ArrayList<String>(); String[] arr = productIds.split("#"); if (arr == null || arr.length == 0) { complain("arr is null or empty"); } else { for (int i = 0; i < arr.length; i++) { AllProductIds.add(arr[i]); } } // Hooray, IAB is fully set up. Now, let's get an inventory of stuff we own. Log.i(TAG, "IAB=== Setup successful. Querying inventory."); try { mHelper.queryInventoryAsync(mGotInventoryListener); } catch (IabAsyncInProgressException e) { complain("Error querying inventory. Another async operation in progress. e=" + e.getMessage()); } } }); }
4.处理订单状态回调。Sdk回调onQueryInventoryFinished(),检查是否有已经购买,但是尚未兑换的订单,
如果有需通知Unity,进行兑换。
IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener()
{ public void onQueryInventoryFinished(IabResult result, Inventory inventory)
{ Log.i(TAG, "IAB=== Query inventory finished."); // Have we been disposed of in the meantime? If so, quit. if (mHelper == null) return; // Is it a failure? if (result.isFailure())
{ complain("Failed to query inventory: " + result); return; } Log.i(TAG, "IAB=== Query inventory was successful."); String productIdsStr = ""; if (AllProductIds == null || AllProductIds.size() == 0) { complain("AllProductIds is null or empty"); } else { for (int i = 0; i < AllProductIds.size(); i++) { // 返回购买信息 Purchase p = inventory.getPurchase(AllProductIds.get(i)); if (p != null) { InventoryList.addElement(p); productIdsStr += p.getSku() + "#"; } } } UnityPlayer.UnitySendMessage("GameRoot","QueryInventoryFinish", productIdsStr); Log.i(TAG, "IAB=== Initial inventory query finished; enabling. strs = " + productIdsStr); } };
5.购买,提供给Unity上层调用。通过launchPurchaseFlow(),传入productId
public void buy(String productId) { String payload = ""; try
{ mHelper.launchPurchaseFlow(this, productId, 10001, mPurchaseFinishedListener, payload); } catch (IabAsyncInProgressException e)
{ complain("Error launching purchase flow. Another async operation in progress. e=" + e.getMessage()); } }
6.购买回调,Sdk回调onIabPurchaseFinished()。
通知Unity购买成功/失败
IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener()
{ public void onIabPurchaseFinished(IabResult result, Purchase purchase)
{ Log.i(TAG, "IAB=== Purchase finished: " + result + ", purchase: " + purchase); // if we were disposed of in the meantime, quit. if (mHelper == null) { UnityPlayer.UnitySendMessage("GameRoot","BuyFail", "mHelper is null"); return; } if (result.isFailure())
{ complain("Error purchasing: " + result); UnityPlayer.UnitySendMessage("GameRoot","BuyFail", result.getMessage()); return; } if (!verifyDeveloperPayload(purchase))
{ complain("Error purchasing. Authenticity verification failed."); UnityPlayer.UnitySendMessage("GameRoot","BuyFail", "Error purchasing. Authenticity verification failed."); return; } Log.i(TAG, "IAB=== Purchase successful. productId = " + purchase.getSku()); InventoryList.add(purchase);
UnityPlayer.UnitySendMessage("GameRoot","ExchangePayment", purchase.getSku() + "#" + purchase.getSku()); } };
7.消耗商品,提供给Unity上层调用的接口。调用consumeAsync()传入Purchase对象
public void consumeProduct(String productId) { if (productId != "") { for (int i = 0; i < InventoryList.size(); i++) { if (productId.equals(InventoryList.elementAt(i).getSku())) { Log.i(TAG, "IAB=== 向google发送消费请求"); try { mHelper.consumeAsync(InventoryList.elementAt(i), mConsumeFinishedListener); } catch (IabAsyncInProgressException e) { complain("Error consuming. Another async operation in progress. e = " + e.getMessage()); } break; } } } }
8.消耗商品的回调,Sdk调用onConsumeFinished()。
IabHelper.OnConsumeFinishedListener mConsumeFinishedListener = new IabHelper.OnConsumeFinishedListener()
{ public void onConsumeFinished(Purchase purchase, IabResult result)
{ Log.i(TAG, "IAB=== Consumption finished. Purchase: " + purchase + ", result: " + result); // if we were disposed of in the meantime, quit. if (mHelper == null) { Log.i(TAG, "mHelper is null"); return; } // We know this is the "gas" sku because it's the only one we consume, // so we don't check which sku was consumed. If you have more than one // sku, you probably should check... if (result.isSuccess())
{ Log.i(TAG, "IAB=== consume success product = " + purchase.getSku()); } else
{ complain("Error while consuming: " + result); } Log.i(TAG, "IAB=== End consumption flow."); // 从订单列表中移除消耗过的订单 for (int i = 0; i < InventoryList.size(); i++) { if (purchase.getSku().equals(InventoryList.elementAt(i).getSku())) { InventoryList.remove(i); Log.i(TAG, "IAB=== 从订单列表中移除消耗过的订单: " + purchase.getSku()); break; } } } };
9.关于测试
1).登录google play console
2)在 设置-->管理测试人员 中加入测试账号,并且在 开发者账号-->账号详情-->许可测试 中加入可用于测试的Gmail账号。
(只有在这里添加了账号,测试时购买页才会提示:Test card, always approves 这是测试订单,我们不会向您收取任何费用,否则都会实际扣费,即使是在aplha测试下)
3)在 所有应用--> <你的应用>-->版本管理-->应用版本 里发布alpha版本,选择测试人员进行封闭式Alpha测试
4)在测试过程中如果需要修改逻辑,可以重新打包,versionCode保持不变,直接拷贝到手机内安装即可,不需要通过网站
5)发布alpha测试后,可以通过发送测试链接给测试人员,测试人员通过点击测试链接输入gmail账号同意加入测试计划,就可以到play商店下载测试版。
要注意查看版本修改信息,确保下载的是最新测试版,一般在发布后,需要在发布前测试报告做完之后才会刷新上去
6)发布前测试报告,google 会将游戏自动安装到10台不同安卓机子上,并开游戏进行测试,如果测试不通过会提供测试视频,奔溃报告等

浙公网安备 33010602011771号