70

Google のチュートリアルで推奨されているように、ユーティリティ クラスを使用していIabHelperますが、このエラーに悩まされています。複数の非同期IabHelper操作を同時に実行できないようです。在庫の取得がまだ進行中のときに購入を開始しようとして、なんとかヒットしました。

ここonActivityResultで提案されているように、すでにメインクラスに実装しようとしましたが、エラーが発生する前にそのメソッドを呼び出すことすらできません。次に、これを見つけましが、このメソッドがどこにあるかわかりません-クラスにはありません。flagEndAsyncIabHelper

今、私はこれを回避する方法を探しています(シーバン全体を再実装することなく)。私が考えることができる唯一の解決策はasyncActive、非同期タスクが開始される前にチェックされるブール値フィールドを作成し、アクティブな別のタスクがある場合はそれを行わないことです。しかし、これには他にも多くの問題があり、アクティビティ全体では機能しません。また、まったく実行しないのではなく、許可されたらすぐに非同期タスクをキューに入れて実行することをお勧めします。

この問題の解決策はありますか?

4

19 に答える 19

106

単純なトリッキーな解決策

purchaseItemメソッドを呼び出す前に、この行を追加するだけです

  if (billingHelper != null) billingHelper.flagEndAsync();

あなたのコードはこのように見えます

 if (billingHelper != null) billingHelper.flagEndAsync();
 purchaseItem("android.test.purchased");

注:別のパッケージから呼び出す場合は、IabHelper で flagEndAsync() メソッドを public にすることを忘れないでください。

于 2013-05-03T12:35:05.500 に答える
41

これをクラックするのは簡単ではありませんでしたが、必要な回避策を見つけました。最近の Google にはかなりがっかりしています。彼らの Android Web サイトはめちゃくちゃになり (有用な情報を見つけるのが非常に難しくなっています)、サンプル コードも貧弱です。数年前に Android 開発を行っていたとき、すべてがとても簡単になりました。これはそのさらに別の例です...

実際、IabUtil にはバグがあり、独自の非同期タスクを適切に呼び出しません。このことを安定させるために必要な回避策の完全なセット:

1) メソッドをflagEndAsync公開します。目に見えないだけで、そこにあります。

iabHelper.flagEndAsync2)手順が適切に完了としてマークされていることを確認するために、すべてのリスナー呼び出しを行います。すべてのリスナーに必要なようです。

3) 呼び出しを で囲み、発生する可能性try/catchのある をキャッチし、IllegalStateExceptionそのように処理します。

于 2013-03-23T03:12:02.590 に答える
15

金太郎と似たようなことをやってしまいました。ただし、キャッチの最後に mHelper.flagEndAsync() を追加しました。ユーザーは引き続きトーストを受け取りますが、次に購入ボタンを押すまでに、非同期操作は強制終了され、購入ボタンは再び使用できるようになります。

if (mHelper != null) {
    try {
    mHelper.launchPurchaseFlow(this, item, RC_REQUEST, mPurchaseFinishedListener, "");
    }       
    catch(IllegalStateException ex){
        Toast.makeText(this, "Please retry in a few seconds.", Toast.LENGTH_SHORT).show();
        mHelper.flagEndAsync();
    }
}
于 2014-02-02T00:56:59.723 に答える
7

私のためにそれを行った簡単なトリックは、IabHelper でメソッドを作成することでした。

public Boolean getAsyncInProgress() {
    return mAsyncInProgress;
}

次に、コードで次を確認します。

if (!mHelper.getAsyncInProgress())
    //launch purchase
else
    Log.d(TAG, "Async in progress already..)
于 2014-10-04T15:35:10.217 に答える
6

本当に悩ましい問題。これは、コードに関しては完全ではありませんが、ユーザーフレンドリーで、悪い評価やクラッシュを回避する、簡単で汚いソリューションです。

if (mHelper != null) {
        try {
        mHelper.launchPurchaseFlow(this, item, RC_REQUEST, mPurchaseFinishedListener, "");
        }       
        catch(IllegalStateException ex){
            Toast.makeText(this, "Please retry in a few seconds.", Toast.LENGTH_SHORT).show();
        }
    }

このようにして、ユーザーは別の時間 (最悪で 2 回) をタップするだけで、請求ポップアップが表示されます。

それが役に立てば幸い

于 2013-07-23T12:20:59.213 に答える
3

アクティビティの onActivityResult requestCode を確認し、購入時に使用した PURCHASE_REQUEST_CODE と一致する場合は、それをフラグメントに渡します。

FragmentTransaction でフラグメントを追加または置換する場合は、タグを設定するだけです。

fTransaction.replace(R.id.content_fragment, fragment, fragment.getClass().getName());

次に、アクティビティの onActivityResult で

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if(requestCode == PurchaseFragment.PURCHASE_REQUEST_CODE) {
        PurchaseFragment fragment = getSuportFragmentManager().findFragmentByTag(PurchaseFragment.class.getNAme());
        if(fragment != null) {
            fragment.onActivityResult(requestCode, resultCode, data);
        }
    }
}
于 2014-04-02T07:49:29.743 に答える
1

私は時々この問題を抱えていましたが、私の場合、基盤となるサービスが切断されて再接続された場合 (たとえば、断続的なネットワーク接続が原因で)、IabHelper の onServiceConnected メソッドが複数回呼び出される可能性があるという事実まで追跡しました。

私の場合の特定の操作は、「別の非同期操作(launchPurchaseFlow)が進行中のため、非同期操作(インベントリの更新)を開始できません」でした。

私のアプリの作成方法では、queryInventory が完了するまで launchPurchaseFlow を呼び出すことができず、onIabSetupFinished ハンドラー関数からのみ queryInventory を呼び出します。

IabHelper コードは、その onServiceConnected が呼び出されるたびにこのハンドラ関数を呼び出します。これは複数回発生する可能性があります。

onServiceDisconnectedのAndroid ドキュメントには次のように書かれています。

サービスへの接続が失われたときに呼び出されます。これは通常、サービスをホストしているプロセスがクラッシュまたは強制終了された場合に発生します。これは ServiceConnection 自体を削除しません。このサービスへのバインディングはアクティブなままであり、サービスが次に実行されるときに onServiceConnected(ComponentName, IBinder) への呼び出しを受け取ります。

問題を説明します。

おそらく、IabHelper は onIabSetupFinished リスナー関数を 2 回以上呼び出すべきではありませんが、一方で、既に実行して結果を取得している場合、この関数内から queryInventory を呼び出さないことでアプリの問題を修正するのは簡単なことでした。 .

于 2014-06-19T11:18:15.560 に答える
1

または、 https ://code.google.com/p/marketbilling/source/browse/ から最新の IabHelper.java ファイルを入手できます。

3月15日のバージョンでこれが修正されました。(変更のない他のファイルは 15 日にコミットされたことに注意してください)

「android.test.canceled」が送信された SKU である場合、null インテント エクストラが原因でテスト中に発生した 1 つのクラッシュを修正する必要がありました。私が変更され:

int getResponseCodeFromIntent(Intent i) {
    Object o = i.getExtras().get(RESPONSE_CODE);

に:

int getResponseCodeFromIntent(Intent i) {
    Object o = i.getExtras() != null ? i.getExtras().get(RESPONSE_CODE) : null;
于 2013-07-11T21:37:10.590 に答える
1

IabHelpr クラスのもう 1 つの主要な問題は、複数のメソッドで RuntimeExcptions (IllegalStateException) をスローするという不適切な選択です。独自のコードから RuntimeExeptions をスローすることは、ほとんどの場合、未チェックの例外であるため望ましくありません。これは、独自のアプリケーションを妨害するようなものです。キャッチされないと、これらの例外が発生してアプリがクラッシュします。

これに対する解決策は、独自のチェック済み例外を実装し、IllegalStateException の代わりにそれをスローするように IabHelper クラスを変更することです。これにより、コンパイル時にコード内でスローされる可能性のあるすべての場所で、この例外を処理する必要があります。

ここに私のカスタム例外があります:

public class MyIllegalStateException extends Exception {

    private static final long serialVersionUID = 1L;

    //Parameterless Constructor
    public MyIllegalStateException() {}

    //Constructor that accepts a message
    public MyIllegalStateException(String message)
    {
       super(message);
    }
}

IabHelper クラスに変更を加えたら、クラス メソッドを呼び出すコードでチェック済み例外を処理できます。例えば:

try {
   setUpBilling(targetActivityInstance.allData.getAll());
} catch (MyIllegalStateException ex) {
    ex.printStackTrace();
}
于 2014-11-02T01:02:15.050 に答える
0

私は同じ問題を抱えていましたが、問題はメソッド onActivityResult を実装していなかったことです。

@Override
protected void onActivityResult(int requestCode,
            int resultCode,
            Intent data)
{
    try
    {
        if (billingHelper == null)
        {
            return;
        } else if (!billingHelper.handleActivityResult(requestCode, resultCode, data))
        {
            super.onActivityResult(requestCode, resultCode, data);
        }
    } catch (Exception exception)
    {
        super.onActivityResult(requestCode, resultCode, data);
    }
}
于 2014-03-22T17:13:55.743 に答える
0

はい、私もこの問題に直面していますが、これを解決しましたが、使用して解決しました

IabHelper mHelpermHelper = new IabHelper(inappActivity, base64EncodedPublicKey);
  mHelper.flagEndAsync();

上記のメソッドは、すべてのフラグを停止します。私にとってのその仕事はチェックしなければなりません

于 2014-04-03T20:00:16.927 に答える
-2

私は同じ問題を抱えていますが、解決しました!UI スレッドで「launchPurchaseFlow」を実行してはいけないと思います。UI スレッドで launchPurchaseFlow を実行してみてください。問題なく動作します。

mActivity.runOnUiThread(new Runnable(){
            public void run(){
                mHelper.launchPurchaseFlow(mActivity, item, 10001, mPurchaseFinishedListener,username);
            }
        });
于 2014-03-15T02:49:52.520 に答える