Ale*_*tru 6 android in-app-purchase in-app-billing firebase
我在 Google Play 商店发布了一个 Android 应用程序,上周我发布了一个新的更新,只是为了解决一些小问题。从我在 Play 商店添加更新版本的那天开始,我可以在 Firebase Crashlytics 上看到有人尝试购买应用功能时出现问题。
在我发布生产中的更新版本之前,我在 Alpha 测试中添加了该应用程序,以便我可以确保 InAppPurchase 工作,并且确实如此。
当其他人尝试购买应用程序功能时,我可以看到抛出了此致命异常:
Fatal Exception: java.lang.IllegalArgumentException: SKU cannot be null.
at com.android.billingclient.api.BillingFlowParams$Builder.build(com.android.billingclient:billing@@3.0.0:23)
Run Code Online (Sandbox Code Playgroud)
SKU 在我的“托管产品”列表中仍然有效。
这是我用来初始化计费客户端的代码(在一个片段中):
billingClient = BillingClient.newBuilder(getActivity())
.enablePendingPurchases()
.setListener(purchasesUpdatedListener)
.build();
Run Code Online (Sandbox Code Playgroud)
这是我用来启动连接的代码:
billingClient.startConnection(new BillingClientStateListener() {
@Override
public void onBillingSetupFinished(@NonNull BillingResult billingResult) {
Log.d(TAG, "Connection finished");
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
// The BillingClient is ready. You can query purchases here.
List<String> skuList = new ArrayList<>();
skuList.add("unlock_keyboard");
SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
params.setSkusList(skuList).setType(BillingClient.SkuType.INAPP);
billingClient.querySkuDetailsAsync(params.build(),
new SkuDetailsResponseListener() {
@Override
public void onSkuDetailsResponse(@NonNull BillingResult billingResult,
List<SkuDetails> skuDetailsList) {
// Process the result.
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && skuDetailsList != null) {
for (Object skuDetailsObject : skuDetailsList) {
skuDetails = (SkuDetails) skuDetailsObject;
sku = skuDetails.getSku();
}
Log.d(TAG, "i got response");
Log.d(TAG, String.valueOf(billingResult.getResponseCode()));
Log.d(TAG, billingResult.getDebugMessage());
}
}
});
}
}
Run Code Online (Sandbox Code Playgroud)
这是我用来处理购买的代码:
PurchasesUpdatedListener purchasesUpdatedListener = new PurchasesUpdatedListener() {
@Override
public void onPurchasesUpdated(@NonNull BillingResult billingResult, @Nullable List<Purchase> list) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && list != null) {
for (Purchase purchase : list) {
handlePurchase(purchase);
Log.d(TAG, "Purchase completed" + billingResult.getResponseCode());
}
} else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.USER_CANCELED) {
Log.d(TAG, "User Canceled" + billingResult.getResponseCode());
} else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED) {
if ("unlock_keyboard".equals(sku)) {
KeyboardAlreadyPurchasedConfirmation();
}
Log.d(TAG, "Item Already owned" + billingResult.getResponseCode());
}
}
};
Run Code Online (Sandbox Code Playgroud)
为了启动计费流程,用户必须单击对话框中的按钮。这是代码:
builder.setPositiveButton(
getString(R.string.purchase_keyboard),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
sku = "unlock_keyboard";
BillingFlowParams flowParams = BillingFlowParams.newBuilder()
.setSkuDetails(skuDetails)
.build();
billingClient.launchBillingFlow(Objects.requireNonNull(getActivity()), flowParams);
}
});
Run Code Online (Sandbox Code Playgroud)
在我的应用程序的以前版本中,这种情况从未发生过,它只是在新更新后才开始。我只需要知道是什么导致了这个问题,是我的代码有问题还是只是 Google Play 服务的问题?我必须指出这是在不同 Android 版本的不同设备上发生的。
非常感谢。
我还没有解决这个问题,但我找到了一种方法来减少此库升级产生的错误数量。
我所做的是将 Google Billing Library 从版本3.0.1降级到版本2.1.0,尽管我在 Firebase 中仍然遇到一些错误(SKU 为 null),但大多数用户现在可以购买这些产品。
另外,我实现了一个方法,每当首次打开 Activity 时无法启动 Google Billing 库连接时就会调用该方法,因此更准确地说,这是重新启动计费连接方法。
如果您遇到同样的问题,我建议您至少现在尝试相同的操作,因为 Google Billing 库似乎仍然存在一些需要修复的问题。
1. 在 build.gradle(app) 中添加以下行:
implementation 'com.android.billingclient:billing:2.1.0'
Run Code Online (Sandbox Code Playgroud)
2 . 在 AndroidManifest.xml 文件中添加 BILLING 权限,因为该库的旧版本仍然需要它:
<uses-permission android:name="com.android.vending.BILLING" />
Run Code Online (Sandbox Code Playgroud)
3 . 创建重启计费连接方法:
public void restartBillingConnection() {
billingClient = BillingClient.newBuilder(Objects.requireNonNull(getActivity())).enablePendingPurchases().setListener(ChooseOptionsFragment.this).build();
billingClient.startConnection(new BillingClientStateListener() {@Override
public void onBillingSetupFinished(@NonNull BillingResult billingResult) {
Log.d(TAG, "Connection finished");
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
// The BillingClient is ready. You can query purchases here.
List < String > skuList = new ArrayList < >();
skuList.add(ITEM_SKU_AD_REMOVAL);
SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
params.setSkusList(skuList).setType(BillingClient.SkuType.INAPP);
billingClient.querySkuDetailsAsync(params.build(), new SkuDetailsResponseListener() {@Override
public void onSkuDetailsResponse(@NonNull BillingResult billingResult, List < SkuDetails > skuDetailsList) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && skuDetailsList != null) {
for (Object skuDetailsObject: skuDetailsList) {
skuDetails = (SkuDetails) skuDetailsObject;
sku = skuDetails.getSku();
String price = skuDetails.getPrice();
if (ITEM_SKU_AD_REMOVAL.equals(sku)) {
skuPrice = price;
BillingFlowParams flowParams = BillingFlowParams.newBuilder().setSkuDetails(skuDetails).build();
billingClient.launchBillingFlow(Objects.requireNonNull(Objects.requireNonNull(getActivity())), flowParams);
}
else {
Log.d(TAG, "Sku is null");
}
}
Log.d(TAG, "i got response");
Log.d(TAG, String.valueOf(billingResult.getResponseCode()));
Log.d(TAG, billingResult.getDebugMessage());
}
else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.ERROR) {
Toast.makeText(getActivity(), "Error in completing the purchase!", Toast.LENGTH_SHORT).show();
}
}
});
}
else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.SERVICE_TIMEOUT) {
Toast.makeText(getActivity(), "Service timeout!", Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(getActivity(), "Failed to connect to the billing client!", Toast.LENGTH_SHORT).show();
}
}@Override
public void onBillingServiceDisconnected() {
restartBillingConnection();
}
});
}
Run Code Online (Sandbox Code Playgroud)
4. 确保在 Google Billing 服务断开连接时调用此方法:
@Override
public void onBillingServiceDisconnected() {
restartBillingConnection();
}
Run Code Online (Sandbox Code Playgroud)
希望这个解决方案能够帮助您解决目前的问题。如果您有其他方法可以完全修复它,请在这篇文章中留下答案。
| 归档时间: |
|
| 查看次数: |
1386 次 |
| 最近记录: |