Java 在应用内计费屏幕/活动期间,屏幕重复闪烁(重新加载?)
我在Android上实现了关于如何实现应用内计费(IAB)的示例。下面是我必须向代码中添加的10个类中的一个,以实现这一点。我原以为它可以工作,但当我在手机上测试它并将应用导航到下面的Java 在应用内计费屏幕/活动期间,屏幕重复闪烁(重新加载?),java,android,in-app-purchase,in-app-billing,Java,Android,In App Purchase,In App Billing,我在Android上实现了关于如何实现应用内计费(IAB)的示例。下面是我必须向代码中添加的10个类中的一个,以实现这一点。我原以为它可以工作,但当我在手机上测试它并将应用导航到下面的BibleStumby活动时,屏幕会加载,然后开始“闪烁”,或者可能会一遍又一遍地重新加载屏幕,所以看起来屏幕只是在一遍又一遍地闪烁 我不完全理解这个类(以及其他9个类)中的IAB过程,所以我对下面代码中的错误位置有点困惑 所以我的问题是,在我下面的代码中,是什么让我的活动在加载时不断闪烁 public class
BibleStumby
活动时,屏幕会加载,然后开始“闪烁”,或者可能会一遍又一遍地重新加载屏幕,所以看起来屏幕只是在一遍又一遍地闪烁
我不完全理解这个类(以及其他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;
}
}
公共类圣经研究扩展了Swarmacity{
静态最终字符串SKU_电子表格=“电子表格”;
布尔误购=假;
文本视图标题,链接;
按钮购买;
上下文c;
艾伯曼帮助者;
@凌驾
创建时的公共void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
requestWindowFeature(窗口。功能\u无\u标题);
setContentView(R.layout.biblestudy);
c=这个;
字符串base64EncodedPublicKey=a+b+d+e+f+g+h+i+j+k;
//创建助手,将上下文和公钥传递给它以验证签名
mHelper=新的IABHeloper(此,base64EncodedPublicey);
//启动安装程序。这是异步的,安装程序完成后将调用指定的侦听器。
mHelper.startSetup(新的IabHelper.OnIabSetupFinishedListener(){
已完成公共void ONIBS设置(IAB结果){
如果(!result.issucess()){
//哦,不,有个问题。
投诉(“出现错误。我们为给您带来的不便深表歉意。”+c.getResources().getString(R.string.problem1)+“+result);
回来
}
//万岁,IAB已经准备好了。现在,让我们来盘点一下我们拥有的东西。
mHelper.queryInventoryAsync(mGotInventoryListener);
}
});
如果(误购==真){
purchaseBtn.setText(c.getResources().getString(R.string.thankyou2));
title.setText(c.getResources().getString(R.string.thankyou));
purchaseBtn.setOnClickListener(新的OnClickListener(){
公共void onClick(视图v){
已经拥有();
}
});
}否则{
title.setText(c.getResources().getString(R.string.biblestudy));
setText(c.getResources().getString(R.string.purchaseBtn));
purchaseBtn.setOnClickListener(新的OnClickListener(){
//用户单击“立即下载!”按钮。
公共void onClick(视图v){
字符串有效载荷=”;
测试(有效载荷);
}
});
}
}
已公开作废(){
最终对话框=新对话框(c);
setContentView(R.layout.alreadyowned);
TextView tv=(TextView)dialog.findviewbyd(R.id.tv);
tv.setText(c.getResources().getString(R.string.alreadyowned));
dialog.show();
}
公共无效测试(字符串有效载荷){
mHelper.launchPurchaseFlow(此,SKU电子表格,10001,MPURCCHASEFinishedListener,有效负载);
}
//当我们完成查询我们拥有的项目和订阅时调用的侦听器。
IabHelper.QueryInventoryFinishedListener mGotInventoryListener=新IabHelper.QueryInventoryFinishedListener(){
QueryInventoryFinished上的公共无效(IABREACT结果,库存){
if(result.isFailure()){
投诉(“出现错误。我们为给您带来的不便表示歉意。”+c.getResources().getString(R.string.failedtoquery)+“+result);
回来
}
/*
*检查我们拥有的物品。注意,对于每次购买,我们都会检查
*查看开发人员负载是否正确!请参阅
*验证developerPayLoad()。
*/
采购电子表格采购=存货.getPurchase(SKU\U电子表格);
Misspurchased=(电子表格采购!=null&&verifyDeveloperPayload(电子表格采购));
updateUi();
}
};
@凌驾
受保护的void onActivityResult(int请求代码、int结果代码、意图数据){
//将活动结果传递给助手进行处理
if(!mHelper.handleActivityResult(请求代码、结果代码、数据)){
//没有处理,所以自己处理(这里是你想要的
//执行任何与应用内活动无关的活动结果处理
//帐单。。。
super.onActivityResult(请求代码、结果代码、数据);
}
}
/**验证购买的开发人员有效负载*/
布尔验证developerPayLoad(购买p){
字符串有效负载=p.getDeveloperPayload();
/*
*TODO:验证购买的开发人员有效负载是否正确。它将是
*与您在开始购买时发送的相同。
*
*警告:开始购买时在本地生成随机字符串,然后
*在这里验证它似乎是一个很好的方法,但在将来会失败
*用户在一台设备上购买商品,然后在另一台设备上使用您的应用程序的情况
*另一个设备,因为在另一个设备上,您将无法访问
*最初生成的随机字符串。
*
*因此,好的开发人员负载具有以下特征:
*
*1.如果两个不同的用户购买了一个物品,那么他们之间的有效载荷是不同的,
*因此,一个用户的购买
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;
}
}