15
votes

Google has upgraded to IAB3(In App Billing version 3). First what a issue in example code.. super.onDestroy() is missed.

I implemented v3 with the help of http://developer.android.com/google/play/billing/billing_integrate.html

It is tested on phone, does not work in emulator.It stuck in emulator.

My issue is, I did not see the API for restoring transactions. How can I restore purchases with IAB3? Is it mService.getPurchases(apiVersion, packageName, type, continuationToken). Has anyone tested this?? Does this returns purchased items from locally stored items or does it restore purchased items? Uninstalling application does not have continuationToken. Should it be null?

And What about when the purchase state changes??

Please help!

Thanks in advance.

EDIT :

Google has updated the In app billing library and solved the super.onDestroy() issue. They have also added some additional features.

2
The query purchase that occurs right after set up does this. I am trying for the same but i have an another issue that is after i got result "ITEM is already owned and again i try to call launchPurchaseFlow. It give up an exception "java.lang.IllegalStateException: Can't start async operation (launchPurchaseFlow) because another async operation(launchPurchaseFlow) is in progress. ". I do not know how to go through it.LuminiousAndroid
For testing, should I publish application or Will do with draft??.. My application is not published on play(not a single version).Bhavesh Hirpara
You just require to publish your in-app product not the app.LuminiousAndroid

2 Answers

3
votes

To make item consumable you have to sent a consume request and you have to do that in separate thread.

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == 1111) {
        int responseCode = data.getIntExtra("RESPONSE_CODE", 0);
        String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
        String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");
        Logger.printMessage(TAG, "on activity result reponse"
                + responseCode, Logger.DEBUG);
        if (resultCode == RESULT_OK && responseCode == 0) {
            try {
                JSONObject jo = new JSONObject(purchaseData);
                String sku = jo.getString("productId");
                String title = jo.getString("title");
                addChipsToBalance(sku);
                final String token = jo.getString("purchaseToken");
                Toast.makeText(BuyChipsActivity.this,
                        "You have bought " + title + ". Enjoy the game!",
                        Toast.LENGTH_SHORT).show();

                new Thread(new Runnable() {

                    @Override
                    public void run() {
                        // TODO Auto-generated method stub
                        Logger.printMessage(TAG, "inside run", Logger.DEBUG);
                        try {
                            int response = mService.consumePurchase(3,
                                    getPackageName(), token);
                            Logger.printMessage(TAG, "inside run response"
                                    + response, Logger.DEBUG);
                        } catch (RemoteException e) {
                            // TODO Auto-generated catch block
                            Logger.printMessage(TAG, "exception here 1",
                                    Logger.DEBUG);
                            e.printStackTrace();
                        }
                    }
                }).start();
                // alert("You have bought the " + sku +
                // ". Excellent choice,  adventurer!");
            } catch (JSONException e) {
                // alert("Failed to parse purchase data.");
                e.printStackTrace();
            }
        }
    }

But sometimes consume request is not completed on google end so you may want to query the purchased item list and consume it with the purchase token. I did like this

   private void showPreviousPurchases() {
    Logger.printMessage(TAG, "previous purchases", Logger.DEBUG);
    if (mService == null) {
        Toast.makeText(this, "Something Went Wrong. Try later",
                Toast.LENGTH_LONG).show();
        return;
    }
    Bundle ownedItems = null;
    ;
    try {
        ownedItems = mService.getPurchases(3, getPackageName(), "inapp",
                null);
    } catch (RemoteException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    if (ownedItems == null) {
        Logger.printMessage(TAG, "criical error ", Logger.DEBUG);
        return;
    }
    int response = ownedItems.getInt("RESPONSE_CODE");
    if (response == 0) {
        ArrayList<String> ownedSkus = ownedItems
                .getStringArrayList("INAPP_PURCHASE_ITEM_LIST");
        ArrayList<String> purchaseDataList = ownedItems
                .getStringArrayList("INAPP_PURCHASE_DATA_LIST");
    /*  ArrayList<String> signatureList = ownedItems
                .getStringArrayList("INAPP_DATA_SIGNATURE");
        String continuationToken = ownedItems
                .getString("INAPP_CONTINUATION_TOKEN");*/

        for (int i = 0; i < purchaseDataList.size(); ++i) {
            String purchaseData = purchaseDataList.get(i);
            Logger.printMessage(TAG, "json  = " + purchaseData,
                    Logger.DEBUG);
            // String signature = signatureList.get(i);
            String sku = ownedSkus.get(i);

            addChipsAndMakeItConsumable(purchaseData);
            // do something with this purchase information
            // e.g. display the updated list of products owned by user
        }

        // if continuationToken != null, call getPurchases again
        // and pass in the token to retrieve more items
    }

}

private void addChipsAndMakeItConsumable(String purchaseData) {

    try {
        JSONObject jo = new JSONObject(purchaseData);
        String sku = jo.getString("productId");
        // String title = jo.getString("title");
        addChipsToBalance(sku);
        final String token = jo.getString("purchaseToken");
        Logger.printMessage(TAG, "id  = " + sku, Logger.DEBUG);

        Logger.printMessage(TAG, "inside run", Logger.DEBUG);
        try {
            int response = mService.consumePurchase(3, getPackageName(),
                    token);
            Logger.printMessage(TAG, "inside run response" + response,
                    Logger.DEBUG);
        } catch (RemoteException e) {
            // TODO Auto-generated catch block
            Logger.printMessage(TAG, "exception here 1", Logger.DEBUG);
            e.printStackTrace();
        }

        // alert("You have bought the " + sku +
        // ". Excellent choice,  adventurer!");
    } catch (JSONException e) {
        // alert("Failed to parse purchase data.");
        e.printStackTrace();
    }
}
0
votes

In your IabHelper.java which is an example in your /android-sdk/extras/google/play_billing/samples/ put this code to get all the item that has been purchased by the user. This will return an JSON array of purchased data. You can also used Purchase.java to parse with, which is available also in the samples folder.

     public ArrayList<String> getAllPurchases() throws RemoteException{
     Bundle ownedItems = mService.getPurchases(3, mContext.getPackageName(),"inapp", null);

     int response = getResponseCodeFromBundle(ownedItems);
     logDebug("Owned items response: " + String.valueOf(response));
     if (response != BILLING_RESPONSE_RESULT_OK) {
         logDebug("getPurchases() failed: " + getResponseDesc(response));

     }
     if (!ownedItems.containsKey(RESPONSE_INAPP_ITEM_LIST)
             || !ownedItems.containsKey(RESPONSE_INAPP_PURCHASE_DATA_LIST)
             || !ownedItems.containsKey(RESPONSE_INAPP_SIGNATURE_LIST)) {
         logError("Bundle returned from getPurchases() doesn't contain required fields.");
     }

     ArrayList<String> purchaseDataList = ownedItems.getStringArrayList(RESPONSE_INAPP_PURCHASE_DATA_LIST);
     return purchaseDataList;
}

And into your Main activity

 public class MainActivity extends Activity{
  private IabHelper mHelper;
      private String arrayString;
      public void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);

    mHelper = new IabHelper(this,"YOUR PUBLIC KEY" );
      mHelper.enableDebugLogging(true);
      mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {

        public void onIabSetupFinished(IabResult result) {

        if (!result.isSuccess()) { // Oh noes, there was a problem.
            Toast.makeText(this,"Problem setting up in-app billing: " + result,Toast.LENGTH_LONG).show();
              return;
          }

        arrayString=mHelper.getAllPurchases().toString();

        Log.d("Purchases: ",""+arrayString);


        array = new JSONArray(arrayString);

        for (int i = 0; i < array.length(); i++) {
            JSONObject row = array.getJSONObject(i);    
            productId=row.getString("productId");  //this will get the product id's that has been purchased.

            Log.e("To be restored:", " PRODUCT ID's "+productId);
        }

      });         
    }
}

I hope this will help you. ^_^ Thanks.