2013-05-28 33 views
0

我在Android上實現了關於如何實現In-App Billing(IAB)的示例。下面是我必須添加到我的代碼中才能完成此工作的10個課程之一。我以爲我有它的工作,但當我在手機上測試它,並導航應用程序以下BibleStudy活動,屏幕加載,然後開始「閃爍」或可能重新加載屏幕一遍又一遍,所以它看起來像屏幕一遍又一遍地閃爍。屏幕在應用內結算屏幕/活動期間反覆閃爍(重新加載?)

我不完全理解這個類中的IAB進程(和其他9類),所以我對我的下面的代碼中的錯誤位置有點困惑。

所以我的問題是,它是什麼在我的下面的代碼是讓我的活動不斷閃爍加載時?

public class BibleStudy extends SwarmActivity { 

    static final String SKU_SPREADSHEET = "spreadsheet"; 

    boolean mIsPurchased = false; 

    TextView title, link; 
    Button purchaseBtn; 

    Context c; 

    IabHelper mHelper; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     requestWindowFeature(Window.FEATURE_NO_TITLE); 
     setContentView(R.layout.biblestudy); 

     c = this; 

     String base64EncodedPublicKey = a + b + d + e + f + g + h + i + j + k; 

     // Create the helper, passing it our context and the public key to verify signatures with 
     mHelper = new IabHelper(this, base64EncodedPublicKey); 

     // Start setup. This is asynchronous and the specified listener will be called once setup completes. 
     mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() { 
      public void onIabSetupFinished(IabResult result) { 

       if (!result.isSuccess()) { 
        // Oh noes, there was a problem. 
        complain("An error has occurred. We apologize for the inconvenience. " + c.getResources().getString(R.string.problem1) + " " + result); 
        return; 
       } 

       // Hooray, IAB is fully set up. Now, let's get an inventory of stuff we own. 
       mHelper.queryInventoryAsync(mGotInventoryListener); 
      } 
     }); 

     if(mIsPurchased == true) { 
      purchaseBtn.setText(c.getResources().getString(R.string.thankyou2)); 
      title.setText(c.getResources().getString(R.string.thankyou)); 
      purchaseBtn.setOnClickListener(new OnClickListener() { 
       public void onClick(View v) { 
        alreadyOwned(); 
       } 
      }); 
     } else { 
      title.setText(c.getResources().getString(R.string.biblestudy)); 
      purchaseBtn.setText(c.getResources().getString(R.string.purchaseBtn)); 
      purchaseBtn.setOnClickListener(new OnClickListener() { 
       // User clicked the "Download NOW!" button. 
       public void onClick(View v) { 
        String payload = ""; 
        test(payload); 
       } 
      }); 
     } 
    } 

    public void alreadyOwned() { 

     final Dialog dialog = new Dialog(c); 
     dialog.setContentView(R.layout.alreadyowned); 

     TextView tv = (TextView)dialog.findViewById(R.id.tv); 

     tv.setText(c.getResources().getString(R.string.alreadyowned)); 

     dialog.show(); 
    } 

    public void test(String payload) { 
     mHelper.launchPurchaseFlow(this, SKU_SPREADSHEET, 10001, mPurchaseFinishedListener, payload); 
    } 

    // Listener that's called when we finish querying the items and subscriptions we own. 
    IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() { 
     public void onQueryInventoryFinished(IabResult result, Inventory inventory) { 
      if (result.isFailure()) { 
       complain("An error has occurred. We apologize for the inconvenience. " + c.getResources().getString(R.string.failedtoquery) + " " + result); 
       return; 
      } 

      /* 
      * Check for items we own. Notice that for each purchase, we check 
      * the developer payload to see if it's correct! See 
      * verifyDeveloperPayload(). 
      */ 

      Purchase spreadsheetPurchase = inventory.getPurchase(SKU_SPREADSHEET); 

      mIsPurchased = (spreadsheetPurchase != null && verifyDeveloperPayload(spreadsheetPurchase)); 

      updateUi(); 
     } 
    }; 

    @Override 
    protected void onActivityResult(int requestCode, int resultCode, Intent data) { 

     // Pass on the activity result to the helper for handling 
     if(!mHelper.handleActivityResult(requestCode, resultCode, data)) { 
      // not handled, so handle it ourselves (here's where you'd 
      // perform any handling of activity results not related to in-app 
      // billing... 
      super.onActivityResult(requestCode, resultCode, data); 
     } 
    } 

    /** Verifies the developer payload of a purchase. */ 
    boolean verifyDeveloperPayload(Purchase p) { 
     String payload = p.getDeveloperPayload(); 

     /* 
     * TODO: verify that the developer payload of the purchase is correct. It will be 
     * the same one that you sent when initiating the purchase. 
     * 
     * WARNING: Locally generating a random string when starting a purchase and 
     * verifying it here might seem like a good approach, but this will fail in the 
     * case where the user purchases an item on one device and then uses your app on 
     * a different device, because on the other device you will not have access to the 
     * random string you originally generated. 
     * 
     * So a good developer payload has these characteristics: 
     * 
     * 1. If two different users purchase an item, the payload is different between them, 
     * so that one user's purchase can't be replayed to another user. 
     * 
     * 2. The payload must be such that you can verify it even when the app wasn't the 
     * one who initiated the purchase flow (so that items purchased by the user on 
     * one device work on other devices owned by the user). 
     * 
     * Using your own server to store and verify developer payloads across app 
     * installations is recommended. 
     */ 

     return true; 
    } 

    // Callback for when a purchase is finished 
    IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() { 
     public void onIabPurchaseFinished(IabResult result, Purchase purchase) { 
      if(result.isFailure()) { 
       complain("An error has occurred. We apologize for the inconvenience. " + result); 
       return; 
      } 

      if(!verifyDeveloperPayload(purchase)) { 
       complain("An error has occurred. We apologize for the inconvenience. " + c.getResources().getString(R.string.error2)); 
       return; 
      } 

      else if(purchase.getSku().equals(SKU_SPREADSHEET)) { 
       // this appears to the user immediately after purchasing. 
       alert(c.getResources().getString(R.string.purchased)); 
       mIsPurchased = true; 
       updateUi(); 
      } 
     } 
    }; 

    // updates UI to reflect model 
    public void updateUi() { 

     if(mIsPurchased == true) { 
      link.setClickable(true); 
      link.setMovementMethod(LinkMovementMethod.getInstance()); 
      String a = "<a href='https://docs.google.com/spreadsheet/ccc?key=0At8avx-xtho6dHhkVzRUNkpJWFBNeGc4S3U1X0k0RFE&usp=sharing'>here</a>"; 
      String b = c.getResources().getString(R.string.link1) + " "; 
      String e = " " + c.getResources().getString(R.string.link3); 
      String d = b + a + e; 
      link.setText(Html.fromHtml(d)); 

      Intent intent = new Intent(BibleStudy.this, BibleStudy.class); 
      startActivity(intent); 
     } 
    } 

    void complain(String message) { 
     alert("Error: " + message); 
    } 

    void alert(String message) { 
     AlertDialog.Builder bld = new AlertDialog.Builder(this); 
     bld.setMessage(message); 
     bld.setNeutralButton("OK", null); 
     bld.create().show(); 
    } 

    @Override 
    public void onDestroy() { 
     super.onDestroy(); 
     if(mHelper != null) mHelper.dispose(); 
     mHelper = null; 
    } 
} 

回答

0

確保您在google開發人員控制檯中使用了正確的base64EncodedPublicKey。

我已經看到你的代碼,並有一些代碼可能會解決你的錯誤。 您尚未將此代碼放入您的活動中,請嘗試將此代碼添加到您的活動中。但是,如果萬一它不起作用,請不要移除它,它不會影響您的代碼,但它對於應用程序是必需的-billing。

//你可以用這個替換BibleActivity java文件。 BibleActivity.java:

public class BibleStudy extends SwarmActivity { 

    static final String SKU_SPREADSHEET = "spreadsheet"; 

    boolean mIsPurchased = false; 

    TextView title, link; 
    Button purchaseBtn; 

    Context c; 

    IabHelper mHelper; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     requestWindowFeature(Window.FEATURE_NO_TITLE); 
     setContentView(R.layout.biblestudy); 

     c = this; 

     String base64EncodedPublicKey = a + b + d + e + f + g + h + i + j + k; 

     // Some sanity checks to see if the developer (that's you!) really 
    // followed the 
    // instructions to run this sample (don't put these checks on your app!) 
    if (base64EncodedPublicKey.contains("CONSTRUCT_YOUR")) { 
     throw new RuntimeException(
       "Please put your app's public key in MainActivity.java. See README."); 
    } 
      // add your packageName here 
    if (getPackageName().startsWith("add_your_package_name_here")) { 
     // throw new 
     // RuntimeException("Please change the sample's package name! See README."); 
    } 

     // Create the helper, passing it our context and the public key to verify signatures with 
     mHelper = new IabHelper(this, base64EncodedPublicKey); 

     // Start setup. This is asynchronous and the specified listener will be called once setup completes. 
     mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() { 
      public void onIabSetupFinished(IabResult result) { 

       if (!result.isSuccess()) { 
        // Oh noes, there was a problem. 
        complain("An error has occurred. We apologize for the inconvenience. " + c.getResources().getString(R.string.problem1) + " " + result); 
        return; 
       } 

       // Hooray, IAB is fully set up. Now, let's get an inventory of stuff we own. 
       mHelper.queryInventoryAsync(mGotInventoryListener); 
      } 
     }); 

     if(mIsPurchased == true) { 
      purchaseBtn.setText(c.getResources().getString(R.string.thankyou2)); 
      title.setText(c.getResources().getString(R.string.thankyou)); 
      purchaseBtn.setOnClickListener(new OnClickListener() { 
       public void onClick(View v) { 
        alreadyOwned(); 
       } 
      }); 
     } else { 
      title.setText(c.getResources().getString(R.string.biblestudy)); 
      purchaseBtn.setText(c.getResources().getString(R.string.purchaseBtn)); 
      purchaseBtn.setOnClickListener(new OnClickListener() { 
       // User clicked the "Download NOW!" button. 
       public void onClick(View v) { 
        String payload = ""; 
        test(payload); 
       } 
      }); 
     } 
    } 

    public void alreadyOwned() { 

     final Dialog dialog = new Dialog(c); 
     dialog.setContentView(R.layout.alreadyowned); 

     TextView tv = (TextView)dialog.findViewById(R.id.tv); 

     tv.setText(c.getResources().getString(R.string.alreadyowned)); 

     dialog.show(); 
    } 

    public void test(String payload) { 
     // if device is not supported 
     if (!mHelper.subscriptionsSupported()) { 
      complain("Subscriptions not supported on your device yet. Sorry!"); 
     return; 
     } 

     mHelper.launchPurchaseFlow(this, SKU_SPREADSHEET, 10001, mPurchaseFinishedListener, payload); 
    } 

    // Listener that's called when we finish querying the items and subscriptions we own. 
    IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() { 
     public void onQueryInventoryFinished(IabResult result, Inventory inventory) { 
      if (result.isFailure()) { 
       complain("An error has occurred. We apologize for the inconvenience. " + c.getResources().getString(R.string.failedtoquery) + " " + result); 
       return; 
      } 

      /* 
      * Check for items we own. Notice that for each purchase, we check 
      * the developer payload to see if it's correct! See 
      * verifyDeveloperPayload(). 
      */ 

      Purchase spreadsheetPurchase = inventory.getPurchase(SKU_SPREADSHEET); 

      mIsPurchased = (spreadsheetPurchase != null && verifyDeveloperPayload(spreadsheetPurchase)); 

      updateUi(); 
     } 
    }; 

    // replace your onActivityResult() with this one. 

    @Override 
protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
    Log.d(TAG, "onActivityResult(" + requestCode + "," + resultCode + "," 
      + data); 

    if (mHelper == null) 
     return; 

    // Pass on the activity result to the helper for handling 
    if (!mHelper.handleActivityResult(requestCode, resultCode, data)) { 
     // not handled, so handle it ourselves (here's where you'd 
     // perform any handling of activity results not related to in-app 
     // billing... 
     super.onActivityResult(requestCode, resultCode, data); 
    } else { 
     Log.d(TAG, "onActivityResult handled by IABUtil."); 
    } 
} 

    /** Verifies the developer payload of a purchase. */ 
    boolean verifyDeveloperPayload(Purchase p) { 
     String payload = p.getDeveloperPayload(); 

     /* 
     * TODO: verify that the developer payload of the purchase is correct. It will be 
     * the same one that you sent when initiating the purchase. 
     * 
     * WARNING: Locally generating a random string when starting a purchase and 
     * verifying it here might seem like a good approach, but this will fail in the 
     * case where the user purchases an item on one device and then uses your app on 
     * a different device, because on the other device you will not have access to the 
     * random string you originally generated. 
     * 
     * So a good developer payload has these characteristics: 
     * 
     * 1. If two different users purchase an item, the payload is different between them, 
     * so that one user's purchase can't be replayed to another user. 
     * 
     * 2. The payload must be such that you can verify it even when the app wasn't the 
     * one who initiated the purchase flow (so that items purchased by the user on 
     * one device work on other devices owned by the user). 
     * 
     * Using your own server to store and verify developer payloads across app 
     * installations is recommended. 
     */ 

     return true; 
    } 

    // Callback for when a purchase is finished 
    IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() { 
     public void onIabPurchaseFinished(IabResult result, Purchase purchase) { 
      if(result.isFailure()) { 
       complain("An error has occurred. We apologize for the inconvenience. " + result); 
       return; 
      } 

      if(!verifyDeveloperPayload(purchase)) { 
       complain("An error has occurred. We apologize for the inconvenience. " + c.getResources().getString(R.string.error2)); 
       return; 
      } 

      if(purchase.getSku().equals(SKU_SPREADSHEET)) { 
       // this appears to the user immediately after purchasing. 
       alert(c.getResources().getString(R.string.purchased)); 
       Log.d(TAG, "Purchase is gas. Starting gas consumption."); 
      mHelper.consumeAsync(purchase, mConsumeFinishedListener); 
       mIsPurchased = true; 
       updateUi(); 
      } 
     } 
    }; 

// Called when consumption is complete it is required for the console to verify transaction consume is completed. 
IabHelper.OnConsumeFinishedListener mConsumeFinishedListener = new IabHelper.OnConsumeFinishedListener() { 
    public void onConsumeFinished(Purchase purchase, IabResult result) { 
     Log.d(TAG, "Consumption finished. Purchase: " + purchase 
       + ", result: " + result); 

     // We know this is the "gas" sku because it's the only one we 
     // consume, 
     // so we don't check which sku was consumed. If you have more than 
     // one 
     // sku, you probably should check... 
     if (result.isSuccess()) { 
      // successfully consumed, so we apply the effects of the item in 
      // our 
      // game world's logic, which in our case means filling the gas 
      // tank a bit 
      Log.d(TAG, "Consumption successful. Provisioning."); 
      mTank = mTank == TANK_MAX ? TANK_MAX : mTank + 1; 
      // saveData(); 
      alert("You filled 1/4 tank. Your tank is now " 
        + String.valueOf(mTank) + "/4 full!"); 
     } else { 
      complain("Error while consuming: " + result); 
     } 
     // updateUi(); 
     // setWaitScreen(false); 
     Log.d(TAG, "End consumption flow."); 
    } 
}; 


    // updates UI to reflect model 
    public void updateUi() { 

     if(mIsPurchased == true) { 
      link.setClickable(true); 
      link.setMovementMethod(LinkMovementMethod.getInstance()); 
      String a = "<a href='https://docs.google.com/spreadsheet/ccc?key=0At8avx-xtho6dHhkVzRUNkpJWFBNeGc4S3U1X0k0RFE&usp=sharing'>here</a>"; 
      String b = c.getResources().getString(R.string.link1) + " "; 
      String e = " " + c.getResources().getString(R.string.link3); 
      String d = b + a + e; 
      link.setText(Html.fromHtml(d)); 

      Intent intent = new Intent(BibleStudy.this, BibleStudy.class); 
      startActivity(intent); 
     } 
    } 

    void complain(String message) { 
     alert("Error: " + message); 
    } 

    void alert(String message) { 
     AlertDialog.Builder bld = new AlertDialog.Builder(this); 
     bld.setMessage(message); 
     bld.setNeutralButton("OK", null); 
     bld.create().show(); 
    } 

    @Override 
    public void onDestroy() { 
     super.onDestroy(); 
     if(mHelper != null) mHelper.dispose(); 
     mHelper = null; 
    } 
} 

希望它能幫助你。