Android in-app billing, how to handle app reinstal

2020-07-13 11:20发布

问题:

I'm very confused on how in-app billing works. I've read the documentation and I must have missed something because I don't understand the final step I need to implement into my application to make this work. The in-app billing works great, however, if a user uninstalls my app and installs it again at a future date, my application doesn't know how to determine if the in-app purchase has previously been made. Here's a snippet from my main class where I attempt to handle all of this:

@Override
public void onCreate(Bundle savedInstanceState)
{
    mContext = this;
    startService(new Intent(mContext, BillingService.class));
    BillingHelper.setCompletedHandler(mTransactionHandler);
}

I am using the example classes from the dungeons example project. What I don't understand is how the below code works at the time of purchase, but re-running it doesn't work to check if something been purchased already. I have been stuck on this part for about a month now and I've been getting very frustrated with it.

public Handler mTransactionHandler = new Handler()
{
    public void handleMessage(android.os.Message msg)
    {
        Log.i(TAG, "Transaction complete");
        Log.i(TAG, "Transaction status: "
            + BillingHelper.latestPurchase.purchaseState);
        Log.i(TAG, "Item purchased is: "
            + BillingHelper.latestPurchase.productId);

        if (BillingHelper.latestPurchase.isPurchased())
        {
            new Message("Thank you!", getApplicationContext());
            PAY_VERSION = true;
            SharedPreferences purchasePreferences = getSharedPreferences(PURCHASE_PREFERENCES, Activity.MODE_PRIVATE);
            Editor purchaseEditor = purchasePreferences.edit();
            purchaseEditor.putBoolean("purchased", PAY_VERSION);
            purchaseEditor.commit();
            Intent intent = getIntent();
            finish();
            startActivity(intent);
        }
    };

What I need is some way to query the server to see if this item has been purchased or not. I understand that there's a PURCHASE_STATE_CHANGED thing there somewhere however I have no idea how to do anything when it determines the state has changed or how to initiate it to check. I'm lost and all I need is a good push in the right direction because so far I'm just completely lost.

EDIT:

I've also heard you need to parse JSON, but I have no idea how to even begin doing that.

EDIT 2:

Am I supposed to call this stuff to check?

BillingHelper.restoreTransactionInformation(BillingSecurity.generateNonce());
BillingHelper.getPurchaseInformation(new String[] {"myItem"});

That code previously had crashed on my sisters phone (SGS3, ICS) but not on mine (GN, ICS, and JB work). I was calling it in onCreate() of my first activity. Not really sure what to do with getPurchaseInformation(...) once it's been called. It has no return value so I'm not sure if I can parse the JSON or whatever I'm supposed to do...

Also, those 2 lines give me this:

08-27 11:54:04.271: E/BillingService(17702): BillingHelper not fully instantiated
08-27 11:54:04.271: E/BillingService(17702): BillingHelper not fully instantiated

回答1:

JSON

An example of a JSON order object that includes a subscription purchase token is shown below.

{ "nonce" : 1836535032137741465,

  "orders" :
    [{ "notificationId" : "android.test.purchased",
       "orderId" : "transactionId.android.test.purchased",
       "packageName" : "com.example.dungeons",
       "productId" : "android.test.purchased",
       "developerPayload" : "bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ",
       "purchaseTime" : 1290114783411,
       "purchaseState" : 0,
       "purchaseToken" : "rojeslcdyyiapnqcynkjyyjh" }]
}

How to parse JSON in Java.

Android supports JSON library

Android Billing

If you have a remote server, we recommend that you store purchase information on your server instead of in a local database on a device. Look here.

Read about Managed per user account, Unmanaged, or Subscription

I use billing like this:

  1. In onCreate

     BillingHelper.setCompletedHandler(handlerTransaction);
    

    You have handler in your code.

  2. Next in onClick or something

     BillingHelper.requestPurchase(this, currentMarketProduct.getMarketId());
    


回答2:

You are on the right track with the second update. The trick is to realise everything is done in async.

The typical flow is as follows:

  1. User installs your app.

  2. On first load of your app, you check if you need to restore purchases.

  3. If you do, send a RESTORE_TRANSACTION synchronous request to Google.

  4. Google will respond with a acknowlegment response to your RESTORE_TRANSACTION request. (This is only an acknowlegement that they received your request.)

  5. At this point, you should mark that you had already sent a restore request to Google and no further restores needs to be sent from the app.

  6. Now asynchronously Google will start sending a 'PURCHASE_STATE_CHANGED' event to your app for each in-app purchase the user has previously purchased. This call is the same as what Google would had sent if the user had made that purchase for the first time.

  7. Since it's the same call, your app would pick up the event and handled it normally as if the user has just purchased the in-app product (thereby "restoring" the purchased feature).

In regard to steps 2 and 5, what I've done for my app is to keep a SharedPreference value called 'APP_INITIALISED' that defaults to false. Everytime my app starts up, if 'APP_INITIALISED' is false, I tell Google to RESTORE_TRANSACTION (step 2) then I set APP_INITIALISED to true (step 5).