handleActivityResult:实施inapp结算v3时数据为空

时间:2018-07-10 11:04:50

标签: java android in-app-billing

我正在使用以下实现:https://github.com/anjlab/android-inapp-billing-v3

列表中的所有内容(Android Studio,干净的项目):

  • 将依赖项添加到build.gradle
  • 为清单添加了uses-permission android:name="com.android.vending.BILLING"权限
  • 这样更改了主要活动:

_

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版本,添加了测试人员。测试者帐户与应用所有者的帐户不同。使用测试人员帐户访问了“选择加入”链接。
  • 实际上是通过Play商店安装了该应用程序,在这种情况下,我看不到控制台,但是启动应用程序后什么也没发生
  • APK已签名,应用密钥正确,inapp产品ID正确。许可证密钥中没有空格
  • 还为清单添加了android.permission.INTERNET权限
  • 检查了android-inapp-billing-v3问题跟踪器,该问题未在此处列出,所以我想这并不常见,我犯了一个愚蠢的初学者错误,或者仅与我的系统有关
  • 我对Android开发不是很熟悉,因此,如果我遇到某种旧的依赖性问题,我只是从机器上卸载了Android Studio和SDK,然后从头开始安装了
  • 试图不是在onBillingInitialized中而是通过button-onClick进行购买。在设备上给出相同的结果,并在模拟器上崩溃,因为在这种情况下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!

2 个答案:

答案 0 :(得分:1)

问题出在设备上。您无法在模拟器上测试帐单,而且帐单似乎在我的设备以及其他应用程序中也损坏(每次尝试付款时,它们都会发出某种“未知错误”)。

很明显,从电话设置中恢复Google Play应用或Google服务的权限后,这些权限可以正常工作。

答案 1 :(得分:0)

可能在构造函数完成之前调用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市场不可用或已被弃用且不支持应用内结算的情况。

只需调用静态方法BillingProcessor.isIabServiceAvailable(),如果它为true,则继续。

有关更多详细信息,请参阅此link