我正在尝试为我的应用实施应用内结算 我正在关注谷歌的TriviaDrive示例应用程序中使用的实现,以及开发人员网站上的相关文档 我的代码按预期工作,但是当我尝试"Query Items Available for Purchase"时,生成的Inventory对象包含0个对象,即使我已经创建了一个产品。
我使用Google Play开发者控制台创建了一个ID为paid_version
的托管产品,如下图所示:
文档指出“要检索产品详细信息,请在IabHelper实例上调用queryInventoryAsync(boolean, List, QueryInventoryFinishedListener)
。”
在我自己的代码中,我称之为
mHelper.queryInventoryAsync(true, iabItemSkus, mQueryFinishedListener)
其中:
mHelper
是我的IabHelper实例
iabItemSkus
是一个包含值为“paid_version”的单个项目的列表
mQueryFinishedListener
是我的听众定义如下。
IabHelper.QueryInventoryFinishedListener mQueryFinishedListener = new IabHelper.QueryInventoryFinishedListener() {
@Override
public void onQueryInventoryFinished(IabResult result, Inventory inv) {
if (result.isFailure()) {
Log.d(TAG, "Querying Inventory Failed: " + result);
return;
}
Log.d(TAG, "Title: " + inv.getSkuDetails(SKU_PAID).getTitle());
Log.d(TAG, "Description: " + inv.getSkuDetails(SKU_PAID).getDescription());
Log.d(TAG, "Price = " + inv.getSkuDetails(SKU_PAID).getPrice());
}
};
但是在调试时我可以看到Inventory
中传回的QueryInventoryFinishedListener
对象包含0项,因此inv.getSkuDetails(SKU_PAID).getTitle()
之类的调用会给出空指针异常。
我无法解决我出错的地方。我希望Inventory
对象包含我的paid_version
应用内商品的详细信息。
以下是我的代码部分和我认为与此问题相关的LogCat(试图避免给你代码重载!),但是如果代码的其他部分的更多细节会有所帮助,请告诉我。
来自我的活动:
...
private static final String SKU_PAID = "paid_version";
private static final String TAG = "MyActivity";
private IabHelper mHelper;
...
IabHelper.QueryInventoryFinishedListener mQueryFinishedListener = new IabHelper.QueryInventoryFinishedListener() {
@Override
public void onQueryInventoryFinished(IabResult result, Inventory inv) {
if (result.isFailure()) {
Log.d(TAG, "Querying Inventory Failed: " + result);
return;
}
Log.d(TAG, "Title: " + inv.getSkuDetails(SKU_PAID).getTitle()); // <-- Line 266 of MyActivity.java
Log.d(TAG, "Description: " + inv.getSkuDetails(SKU_PAID).getDescription());
Log.d(TAG, "Price = " + inv.getSkuDetails(SKU_PAID).getPrice());
}
};
...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
final List<String> iabItemSkus = new ArrayList<String>();
iabItemSkus.add(SKU_PAID);
// In App Billing
String base64EncodedPublicKey = "... My Public Key ...";
mHelper = new IabHelper(this, base64EncodedPublicKey);
mHelper.enableDebugLogging(true);
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
@Override
public void onIabSetupFinished(IabResult result) {
if (!result.isSuccess()) {
Log.d(TAG, "Problem setting up In-app Billing: " + result);
}
// Have we been disposed of in the meantime? If so, quit.
if (mHelper == null) return;
// IAB is fully set up. Now, let's get list of available items
Log.d(TAG, "Setup successful. Querying inventory.");
mHelper.queryInventoryAsync(true, iabItemSkus, mQueryFinishedListener);
}
});
...
}
来自我的LogCat:
...
05-13 19:46:59.609 22390-22390/xxx.xxxxxx.xxxxxx D/IabHelper﹕ Starting in-app billing setup.
05-13 19:46:59.629 22390-22390/xxx.xxxxxx.xxxxxx D/IabHelper﹕ Billing service connected.
05-13 19:46:59.629 22390-22390/xxx.xxxxxx.xxxxxx D/IabHelper﹕ Checking for in-app billing 3 support.
05-13 19:46:59.629 22390-22390/xxx.xxxxxx.xxxxxx D/IabHelper﹕ In-app billing version 3 supported for xxx.xxxxxx.xxxxxx
05-13 19:46:59.639 22390-22390/xxx.xxxxxx.xxxxxx D/IabHelper﹕ Subscriptions AVAILABLE.
05-13 19:46:59.639 22390-22390/xxx.xxxxxx.xxxxxx D/MyActivity﹕ Setup successful. Querying inventory.
05-13 19:46:59.639 22390-22390/xxx.xxxxxx.xxxxxx D/IabHelper﹕ Starting async operation: refresh inventory
05-13 19:46:59.649 22390-22596/xxx.xxxxxx.xxxxxx D/IabHelper﹕ Querying owned items, item type: inapp
05-13 19:46:59.649 22390-22596/xxx.xxxxxx.xxxxxx D/IabHelper﹕ Package name: xxx.xxxxxx.xxxxxx
05-13 19:46:59.649 22390-22596/xxx.xxxxxx.xxxxxx D/IabHelper﹕ Calling getPurchases with continuation token: null
05-13 19:46:59.659 22390-22596/xxx.xxxxxx.xxxxxx D/IabHelper﹕ Owned items response: 0
05-13 19:46:59.659 22390-22596/xxx.xxxxxx.xxxxxx D/IabHelper﹕ Continuation token: null
05-13 19:46:59.659 22390-22596/xxx.xxxxxx.xxxxxx D/IabHelper﹕ Querying SKU details.
05-13 19:46:59.689 22390-22596/xxx.xxxxxx.xxxxxx D/IabHelper﹕ Querying owned items, item type: subs
05-13 19:46:59.689 22390-22596/xxx.xxxxxx.xxxxxx D/IabHelper﹕ Package name: xxx.xxxxxx.xxxxxx
05-13 19:46:59.689 22390-22596/xxx.xxxxxx.xxxxxx D/IabHelper﹕ Calling getPurchases with continuation token: null
05-13 19:46:59.699 22390-22596/xxx.xxxxxx.xxxxxx D/IabHelper﹕ Owned items response: 0
05-13 19:46:59.699 22390-22596/xxx.xxxxxx.xxxxxx D/IabHelper﹕ Continuation token: null
05-13 19:46:59.699 22390-22596/xxx.xxxxxx.xxxxxx D/IabHelper﹕ Querying SKU details.
05-13 19:46:59.829 22390-22596/xxx.xxxxxx.xxxxxx D/IabHelper﹕ Ending async operation: refresh inventory
05-13 19:46:59.829 22390-22390/xxx.xxxxxx.xxxxxx D/AndroidRuntime﹕ Shutting down VM
05-13 19:46:59.829 22390-22390/xxx.xxxxxx.xxxxxx W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0x41b31ba8)
05-13 19:46:59.839 22390-22390/xxx.xxxxxx.xxxxxx E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: xxx.xxxxxx.xxxxxx, PID: 22390
java.lang.NullPointerException
at xxx.xxxxxx.xxxxxx.MyActivity$1.onQueryInventoryFinished(MyActivity.java:266)
at xxx.xxxxxx.xxxxxx.util.IabHelper$2$1.run(IabHelper.java:630)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5017)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
at dalvik.system.NativeStart.main(Native Method)
...
PS:我刚刚更新了我的代码,以突出显示第266行。
附加
我在上传APK后12小时遇到此问题,正如您在LogCat中看到的那样,它表示我的应用为"In-app billing version 3 supported"
。
无论我是否将IN-APP PRODUCT的状态设置为活动或非活动状态,问题仍然存在。
现在24小时后它神奇地决定正常工作。
由此我只能确定这是Google Play的问题,而不是我的代码。
答案 0 :(得分:2)
我在同一条船上。我等着看看会发生什么。
在Google文档http://developer.android.com/training/in-app-billing/test-iab-app.html
中有一个警告,也许这就是问题所在:
警告:上传APK for Google Play后可能需要2-3小时才能识别您更新的APK版本。如果您在Google Play识别上传的APK之前尝试测试您的应用程序,您的应用程序将收到“已取消购买”的回复,并显示错误消息“此版本的应用程序未启用应用内结算。”
答案 1 :(得分:1)
我遇到了同样的问题。如果你看看IabHelper代码,我认为问题是:
在queryInventory中:
if (querySkuDetails) {
r = querySkuDetails(ITEM_TYPE_INAPP, inv, moreItemSkus);
if (r != BILLING_RESPONSE_RESULT_OK) {
throw new IabException(r, "Error refreshing inventory (querying prices of items).");
}
}
但是后面的几行querySkuDetails:
int querySkuDetails(String itemType, Inventory inv, List<String> moreSkus)
throws RemoteException, JSONException {
logDebug("Querying SKU details.");
ArrayList<String> skuList = new ArrayList<String>();
skuList.addAll(inv.getAllOwnedSkus(itemType));
注意最后一行用所有拥有的 skus填充skuList。并非所有可用的。
所以答案是IabHelper并不真正支持查询可用的购买。
答案 2 :(得分:1)
要获取包含价格的可用购买列表,您需要使用参数调用queryInventoryAsync - 购物标识符列表:
ArrayList<String> skuList = new ArrayList<String> ();
skuList.add("purchase1");
ArrayList<String> subsList = new ArrayList<String> ();
subsList.add("subscribe1");
mHelper.queryInventoryAsync(true, skuList, subsList, mGotInventoryListener);
答案 3 :(得分:1)
我已经尝试过上述解决方案,但是它对我不起作用,我从另一个代码中获得了解决方案,所以我只想分享一下,以便其他人可以得到帮助。有关Google应用内代码,请检查此google github project
区别在于调用queryInventoryAsync()
时需要传递更多参数,并确保在onIabSetupFinished()
成功初始化后在IabHelper
内部调用以下方法。
runOnUiThread(new Runnable() {
@Override
public void run() {
refreshItemList();
}
});
准备skurequest
private void refreshItemList() {
List<String> itemSku = new ArrayList<>();
List<String> subSku = new ArrayList<>();
subSku.add(AppConstant.InApp.SKU_ONE_ID);
mHelper.queryInventoryAsync(true, itemSku, subSku, mQotInventoryListener);
}
下面是您收到SkuDetails
的听众
IabHelper.QueryInventoryFinishedListener mQotInventoryListener = new IabHelper.QueryInventoryFinishedListener() {
@Override
public void onQueryInventoryFinished(IabResult result, Inventory inv) {
try {
Log.d(TAG, "mQotInventoryListener 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()) {
Log.e(TAG, "mQotInventoryListener Failed to query inventory: " + result);
return;
}
Log.d(TAG, "mQotInventoryListener Query inventory was successful.");
try {
//Here you just pass SKU_ID that you want its detail
SkuDetails skuDetails = inv.getSkuDetails(AppConstant.InApp.SKU_ONE_ID);
if (skuDetails != null) {
Log.d(TAG, "skuDetails are received");
} else {
Log.e(TAG, "skuDetails are null");
}
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
};
答案 4 :(得分:0)
要使应用内结算工作,请按以下步骤操作:
<uses-permission android:name="com.android.vending.BILLING" />
权限添加到 AndroidManifest.xml 。答案 5 :(得分:0)
迟到回答,我也遇到了同样的问题。在阅读了整整3天的文档后,我终于找到了罪魁祸首。
不再支持草稿应用程序。
以前,您可以发布&#34;草案&#34;你的应用版本 测试。不再支持此功能。相反,有 您可以通过两种方式测试预发布应用在Google上的运作方式 Play商店:
您可以将应用发布到Alpha或Beta分发渠道。 这使得该应用在Google Play商店中可用,但仅适用于 测试人员你戴上了&#34;白名单&#34;。在少数情况下,您可以测试Google 使用未发布的应用程序播放功能。例如,您可以测试 通过使用静态响应,未发布应用的应用内结算支持, 始终返回特定结果的特殊保留产品ID (例如&#34;购买&#34;或&#34;退款&#34;)。
Google应该简化此过程。