handleActivityResult:实施inapp billing v3时数据为空
handleActivityResult: data is null when implementing inapp billing v3
我正在使用这个实现:https://github.com/anjlab/android-inapp-billing-v3
列表中的所有内容(Android Studio,干净的项目):
- 添加了对 build.gradle
的依赖
- 向清单添加了
uses-permission android:name="com.android.vending.BILLING"
权限
- 将主要 activity 更改为这样:
_
package com.example.myappnamehere;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import com.anjlab.android.iab.v3.BillingProcessor;
import com.anjlab.android.iab.v3.TransactionDetails;
public class MainActivity extends Activity implements BillingProcessor.IBillingHandler {
BillingProcessor bp;
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.i("MainActivity", "on Create");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bp = new BillingProcessor(this, "[my license key here]", this);
}
@Override
public void onProductPurchased(@NonNull String productId, @Nullable TransactionDetails details) {
Log.i("MainActivity", "Product purchased");
}
@Override
public void onPurchaseHistoryRestored() {
Log.i("MainActivity", "Purchase History Restored");
}
@Override
public void onBillingError(int errorCode, @Nullable Throwable error) {
Log.e("MainActivity", error.getMessage());
}
@Override
public void onBillingInitialized() {
Log.i("MainActivity", "Billing initialized");
bp.purchase(MainActivity.this, "[my inapp product id here]");
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.i("MainActivity", "Activity Result");
if (!bp.handleActivityResult(requestCode, resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data);
}
}
@Override
public void onDestroy() {
Log.i("MainActivity", "Destroy");
if (bp != null) {
Log.i("MainActivity", "bp release");
bp.release();
}
super.onDestroy();
}
}
清单以防万一:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myappnamehere">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="com.android.vending.BILLING" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
我希望它能在启动时向我提供购买或向控制台显示某种错误,而我却得到这个(如果 运行 在设备上):
W/art: Failed execv(/system/bin/dex2oat --runtime-arg -classpath --runtime-arg --instruction-set=arm64 --instruction-set-features=smp,a53 --runtime-arg -Xrelocate --boot-image=/system/framework/boot.art --non-interactive --runtime-arg -Xms64m --runtime-arg -Xmx512m --instruction-set-variant=generic --instruction-set-features=default --dex-file=/data/app/pro.yakninja.usermobi-1/split_lib_slice_9_apk.apk --oat-file=/data/dalvik-cache/arm64/data@app@com.example.myappnamehere-1@split_lib_slice_9_apk.apk@classes.dex) because non-0 exit status
...
W/System: ClassLoader referenced unknown path: /data/app/com.example.myappnamehere-1/lib/arm64
I/InstantRun: starting instant run server: is main process
I/MainActivity: on Create
D/AccessibilityManager: current package=com.example.myappnamehere, accessibility manager mIsFinalEnabled=false, mOptimizeEnabled=false, mIsUiAutomationEnabled=false, mIsInterestedPackage=false
W/System: ClassLoader referenced unknown path: /system/app/MiuiContentCatcher/lib/arm64
D/OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true
I/MainActivity: Billing initialized
I/Adreno: ...
I/OpenGLRenderer: Initialized EGL, version 1.4
I/MainActivity: Activity Result
E/iabv3: handleActivityResult: data is null!
或者这个(如果 运行 在模拟器上):
I/InstantRun: starting instant run server: is main process
I/MainActivity: on Create
D/OpenGLRenderer: HWUI GL Pipeline
D/: HostConnection::get() New Host Connection established 0x9b3e4380, tid 9990
I/OpenGLRenderer: Initialized EGL, version 1.4
D/OpenGLRenderer: Swap behavior 1
W/OpenGLRenderer: Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...
D/OpenGLRenderer: Swap behavior 0
D/EGL_emulation: eglCreateContext: 0x9b685120: maj 3 min 0 rcv 3
D/EGL_emulation: eglMakeCurrent: 0x9b685120: ver 3 0 (tinfo 0x9b683290)
D/EGL_emulation: eglMakeCurrent: 0x9b685120: ver 3 0 (tinfo 0x9b683290)
到目前为止我已经尝试和检查的内容:
- 将应用程序推出到 alpha 版,添加了测试人员。测试员帐户不同于应用程序所有者的帐户。使用测试员帐户访问了选择加入 link。
- 实际上是通过 Play 商店安装的应用程序,在这种情况下我没有看到控制台,而是在应用程序启动后没有任何反应
- APK 已签名,应用密钥正确,inapp 产品 ID 正确。许可证密钥中没有空格
- 也为清单添加了 android.permission.INTERNET 权限
- 检查了 android-inapp-billing-v3 问题跟踪器,该问题未在此处列出,所以我想这并不常见,我犯了一些愚蠢的初学者错误,或者它与我的有关仅限系统
- 我对 Android 开发不是很熟悉,所以如果我遇到某种老依赖问题,我刚刚从我的机器上卸载了 Android Studio 和 SDK,然后从头开始安装
- 尝试不在 onBillingInitialized 中而是在点击按钮时进行购买。在设备上给出相同的结果并在模拟器上崩溃,因为在这种情况下 bp 为 null
- 尝试传递 null 而不是库示例代码中的真实许可证密钥
编辑:根据一些建议,我将 onCreate 更改为:
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.i("MainActivity", "on Create");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bp = BillingProcessor.newBillingProcessor(this, "[license key]", this); // doesn't bind
bp.initialize(); // binds
payButton = (Button)findViewById(R.id.payButton);
payButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.i("MainActivity", "button clicked");
boolean isAvailable = BillingProcessor.isIabServiceAvailable(v.getContext());
if(isAvailable) {
Log.i("MainActivity", "isIabServiceAvailable");
}
else {
Log.e("MainActivity", "isIabService is not Available");
}
boolean isOneTimePurchaseSupported = bp.isOneTimePurchaseSupported();
if(isOneTimePurchaseSupported) {
Log.i("MainActivity", "OneTimePurchase is supported");
bp.purchase(MainActivity.this, "android.test.purchased");
}
else {
Log.e("MainActivity", "OneTimePurchase is not supported");
}
}
});
}
没有任何变化。日志输出是这样的:
I/MainActivity: on Create
I/MainActivity: Billing initialized
I/MainActivity: button clicked
I/MainActivity: isIabServiceAvailable
I/MainActivity: OneTimePurchase is supported
I/MainActivity: Activity Result
E/iabv3: handleActivityResult: data is null!
可能 onBillingInitialized()
在构造函数完成之前被调用。
实例化延迟初始化的 BillingProcessor
基本 new BillingProcessor(...)
实际上绑定到 constructor
内的 Play 服务。这很少会导致竞争条件,即 Play 服务被绑定并且 onBillingInitialized()
在构造函数完成之前被调用,并且可能导致 NPE。为了避免这种情况,我们有以下内容:
bp = BillingProcessor.newBillingProcessor(this, "YOUR LICENSE KEY FROM GOOGLE PLAY CONSOLE HERE", this); // doesn't bind
bp.initialize(); // binds
并且在使用之前,最好检查应用内结算服务的可用性。在某些较旧的设备或中文设备中,可能会出现 Play Market 不可用或已弃用且不支持应用内结算的情况。
只需调用静态方法BillingProcessor.isIabServiceAvailable()
,如果为真则继续。
更多详情请参考此link
问题出在设备上。您无法在模拟器上测试计费,似乎计费在我的设备上出现问题,在其他应用程序中也是如此(每次我尝试付款时他们都会给出某种 "Unknown error")。
显然,Google Play 应用程序或 Google 服务的权限在从 phone 设置中恢复后被撤销 - 权限正常。
我正在使用这个实现:https://github.com/anjlab/android-inapp-billing-v3
列表中的所有内容(Android Studio,干净的项目):
- 添加了对 build.gradle 的依赖
- 向清单添加了
uses-permission android:name="com.android.vending.BILLING"
权限 - 将主要 activity 更改为这样:
_
package com.example.myappnamehere;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import com.anjlab.android.iab.v3.BillingProcessor;
import com.anjlab.android.iab.v3.TransactionDetails;
public class MainActivity extends Activity implements BillingProcessor.IBillingHandler {
BillingProcessor bp;
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.i("MainActivity", "on Create");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bp = new BillingProcessor(this, "[my license key here]", this);
}
@Override
public void onProductPurchased(@NonNull String productId, @Nullable TransactionDetails details) {
Log.i("MainActivity", "Product purchased");
}
@Override
public void onPurchaseHistoryRestored() {
Log.i("MainActivity", "Purchase History Restored");
}
@Override
public void onBillingError(int errorCode, @Nullable Throwable error) {
Log.e("MainActivity", error.getMessage());
}
@Override
public void onBillingInitialized() {
Log.i("MainActivity", "Billing initialized");
bp.purchase(MainActivity.this, "[my inapp product id here]");
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.i("MainActivity", "Activity Result");
if (!bp.handleActivityResult(requestCode, resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data);
}
}
@Override
public void onDestroy() {
Log.i("MainActivity", "Destroy");
if (bp != null) {
Log.i("MainActivity", "bp release");
bp.release();
}
super.onDestroy();
}
}
清单以防万一:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myappnamehere">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="com.android.vending.BILLING" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
我希望它能在启动时向我提供购买或向控制台显示某种错误,而我却得到这个(如果 运行 在设备上):
W/art: Failed execv(/system/bin/dex2oat --runtime-arg -classpath --runtime-arg --instruction-set=arm64 --instruction-set-features=smp,a53 --runtime-arg -Xrelocate --boot-image=/system/framework/boot.art --non-interactive --runtime-arg -Xms64m --runtime-arg -Xmx512m --instruction-set-variant=generic --instruction-set-features=default --dex-file=/data/app/pro.yakninja.usermobi-1/split_lib_slice_9_apk.apk --oat-file=/data/dalvik-cache/arm64/data@app@com.example.myappnamehere-1@split_lib_slice_9_apk.apk@classes.dex) because non-0 exit status
...
W/System: ClassLoader referenced unknown path: /data/app/com.example.myappnamehere-1/lib/arm64
I/InstantRun: starting instant run server: is main process
I/MainActivity: on Create
D/AccessibilityManager: current package=com.example.myappnamehere, accessibility manager mIsFinalEnabled=false, mOptimizeEnabled=false, mIsUiAutomationEnabled=false, mIsInterestedPackage=false
W/System: ClassLoader referenced unknown path: /system/app/MiuiContentCatcher/lib/arm64
D/OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true
I/MainActivity: Billing initialized
I/Adreno: ...
I/OpenGLRenderer: Initialized EGL, version 1.4
I/MainActivity: Activity Result
E/iabv3: handleActivityResult: data is null!
或者这个(如果 运行 在模拟器上):
I/InstantRun: starting instant run server: is main process
I/MainActivity: on Create
D/OpenGLRenderer: HWUI GL Pipeline
D/: HostConnection::get() New Host Connection established 0x9b3e4380, tid 9990
I/OpenGLRenderer: Initialized EGL, version 1.4
D/OpenGLRenderer: Swap behavior 1
W/OpenGLRenderer: Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...
D/OpenGLRenderer: Swap behavior 0
D/EGL_emulation: eglCreateContext: 0x9b685120: maj 3 min 0 rcv 3
D/EGL_emulation: eglMakeCurrent: 0x9b685120: ver 3 0 (tinfo 0x9b683290)
D/EGL_emulation: eglMakeCurrent: 0x9b685120: ver 3 0 (tinfo 0x9b683290)
到目前为止我已经尝试和检查的内容:
- 将应用程序推出到 alpha 版,添加了测试人员。测试员帐户不同于应用程序所有者的帐户。使用测试员帐户访问了选择加入 link。
- 实际上是通过 Play 商店安装的应用程序,在这种情况下我没有看到控制台,而是在应用程序启动后没有任何反应
- APK 已签名,应用密钥正确,inapp 产品 ID 正确。许可证密钥中没有空格
- 也为清单添加了 android.permission.INTERNET 权限
- 检查了 android-inapp-billing-v3 问题跟踪器,该问题未在此处列出,所以我想这并不常见,我犯了一些愚蠢的初学者错误,或者它与我的有关仅限系统
- 我对 Android 开发不是很熟悉,所以如果我遇到某种老依赖问题,我刚刚从我的机器上卸载了 Android Studio 和 SDK,然后从头开始安装
- 尝试不在 onBillingInitialized 中而是在点击按钮时进行购买。在设备上给出相同的结果并在模拟器上崩溃,因为在这种情况下 bp 为 null
- 尝试传递 null 而不是库示例代码中的真实许可证密钥
编辑:根据一些建议,我将 onCreate 更改为:
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.i("MainActivity", "on Create");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bp = BillingProcessor.newBillingProcessor(this, "[license key]", this); // doesn't bind
bp.initialize(); // binds
payButton = (Button)findViewById(R.id.payButton);
payButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.i("MainActivity", "button clicked");
boolean isAvailable = BillingProcessor.isIabServiceAvailable(v.getContext());
if(isAvailable) {
Log.i("MainActivity", "isIabServiceAvailable");
}
else {
Log.e("MainActivity", "isIabService is not Available");
}
boolean isOneTimePurchaseSupported = bp.isOneTimePurchaseSupported();
if(isOneTimePurchaseSupported) {
Log.i("MainActivity", "OneTimePurchase is supported");
bp.purchase(MainActivity.this, "android.test.purchased");
}
else {
Log.e("MainActivity", "OneTimePurchase is not supported");
}
}
});
}
没有任何变化。日志输出是这样的:
I/MainActivity: on Create
I/MainActivity: Billing initialized
I/MainActivity: button clicked
I/MainActivity: isIabServiceAvailable
I/MainActivity: OneTimePurchase is supported
I/MainActivity: Activity Result
E/iabv3: handleActivityResult: data is null!
可能 onBillingInitialized()
在构造函数完成之前被调用。
实例化延迟初始化的 BillingProcessor
基本 new BillingProcessor(...)
实际上绑定到 constructor
内的 Play 服务。这很少会导致竞争条件,即 Play 服务被绑定并且 onBillingInitialized()
在构造函数完成之前被调用,并且可能导致 NPE。为了避免这种情况,我们有以下内容:
bp = BillingProcessor.newBillingProcessor(this, "YOUR LICENSE KEY FROM GOOGLE PLAY CONSOLE HERE", this); // doesn't bind
bp.initialize(); // binds
并且在使用之前,最好检查应用内结算服务的可用性。在某些较旧的设备或中文设备中,可能会出现 Play Market 不可用或已弃用且不支持应用内结算的情况。
只需调用静态方法BillingProcessor.isIabServiceAvailable()
,如果为真则继续。
更多详情请参考此link
问题出在设备上。您无法在模拟器上测试计费,似乎计费在我的设备上出现问题,在其他应用程序中也是如此(每次我尝试付款时他们都会给出某种 "Unknown error")。
显然,Google Play 应用程序或 Google 服务的权限在从 phone 设置中恢复后被撤销 - 权限正常。