In-App Billing
(IAB)の実装方法について、Android の例を実装しました。以下は、これを機能させるためにコードに追加しなければならなかった 10 個のクラスの 1 つです。私はそれが機能していると思っていましたが、電話でテストしてアプリを以下のBibleStudy
アクティビティに移動すると、画面がロードされてから「ちらつき」を開始するか、画面が何度も何度もリロードされる可能性があるため、画面がただのように見えます何度も点滅。
このクラス (およびその他の 9 つのクラス) の IAB プロセスを完全には理解していないため、以下のコードのどこにエラーがあるのか少し混乱しています。
私の質問は、以下のコードで、ロード時にアクティビティが継続的にちらつく原因は何ですか?
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;
}
}