大佬教程收集整理的这篇文章主要介绍了android – 应用内结算:库存不正确;让用户再次购买,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我试图弄清楚为什么应用程序没有正确库存,我从TrivialDrive中取出它并试图使它成为我自己的.我相信我删除了所有的消费,我只有一件商品可以购买;高级升级.这应该只买一次,从不收取两次.当我在平板电脑上编译并运行应用程序时,我通过购买流程确定并且一切顺利,直到我使用任务管理器关闭应用程序并重新打开它.一旦重新打开,它就会要求再次购买溢价,而不是通过它并执行高级功能.
这是代码:
public class myClass extends SherlockActivity { private DrawerLayout mDrawerLayout; private ListView mDrawerList; private ActionBarDrawerToggle mDrawerToggle; private CharSequence mDrawerTitle; private CharSequence mTitle; private String[] mPlanetTitles; public static final int DIALOG_DOWNLOAD_PROGRESS = 0; ProgressBar pd = null; private ProgressDialog mProgressDialog; Spinner spLoadFrom; WebView wv; private LinearLayout container; private Button nextButton,closeButton; private EditText findBox; private static final String TAG = "Web"; IabHelper mHelper; static boolean mIsPremium = false; boolean mIsUserPremium = false; boolean searchAllowed = false; static final String PREM_SKU = "prem"; private ArrayAdapter<CharSequence> spinnerArrayAdapter; String name_free[] = { }; String displayName_free[] = { }; String name_premium[] = { }; String displayName_premium[] = {}; /** Called when the activity is first created. */ @SuppressLint("NewApi") @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.mylayout); mTitle = mDrawerTitle = getTitle(); mPlanetTitles = getResources().getStringArray( R.array.fMenu); mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); mDrawerList = (ListView) findViewById(R.id.left_drawer); // set a custom shadow that overlays the main content when the drawer // opens mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow,GravityCompat.START); // set up the drawer's list view with items and click listener mDrawerList.setAdapter(new ArrayAdapter<String>(this,R.layout.drawer_list_item,mPlanetTitles)); mDrawerList.setOnItemClickListener(new DrawerItemClickListener()); // enable ActionBar app icon to behave as action to toggle nav drawer getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setHomeButtonEnabled(true); // ActionBarDrawerToggle ties together the the proper interactions // between the sliding drawer and the action bar app icon mDrawerToggle = new ActionBarDrawerToggle(this,/* host Activity */ mDrawerLayout,/* DrawerLayout object */ R.drawable.ic_drawer,/* nav drawer image to replace 'Up' caret */ R.string.drawer_open,/* "open drawer" description for accessibility */ R.string.drawer_close /* "close drawer" description for accessibility */ ) { public void onDrawerClosed(View view) { getSupportActionBar().setTitle(mTitle); supportInvalidateOptionsMenu(); // creates call to // onPrepareOptionsMenu() } public void onDrawerOpened(View drawerView) { getSupportActionBar().setTitle(mDrawerTitle); supportInvalidateOptionsMenu(); // creates call to // onPrepareOptionsMenu() } }; mDrawerLayout.setDrawerListener(mDrawerToggle); if (savedInstanceState == null) { selectItem(0); } mProgressDialog = new ProgressDialog(this); mProgressDialog.setIndeterminate(false); mProgressDialog.setMax(100); mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); wv = (WebView) findViewById(R.id.webview); pd = (ProgressBar) findViewById(R.id.pBar); spLoadFrom = (Spinner) findViewById(R.id.Spinner02); if (mIsPremium == true) { spinnerArrayAdapter = new ArrayAdapter<CharSequence>(this,android.R.layout.simple_spinner_item,displayName_premium); } else { spinnerArrayAdapter = new ArrayAdapter<CharSequence>(this,displayName_free); } spinnerArrayAdapter .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spLoadFrom.setAdapter(spinnerArrayAdapter); SpinnerListener spListener = new SpinnerListener(); spLoadFrom.setOnItemSelectedListener(spListener); String base64EncodedPublicKey = "hidden"; mHelper = new IabHelper(this,base64EncodedPublicKey); Log.d(TAG,"Starting setup."); mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() { @Override public void onIabSetupFinished(IabResult result) { Log.d(TAG,"Setup finished."); if (!result.isSuccess()) { // Oh noes,there was a problem. complain("Problem setting up in-app billing: " + result); return; } // Hooray,IAB is fully set up. Now,let's get an inventory of // stuff we own. Log.d(TAG,"Setup successful. Querying inventory."); mHelper.queryInventoryAsync(mGotInventoryListener); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { getSupportMenuInflater().inflate(R.menu.menu3,menu); return super.onCreateOptionsMenu(menu); } /* Called whenever we call invalidateOptionsMenu() */ @Override public boolean onPrepareOptionsMenu(Menu menu) { // If the nav drawer is open,hide action items related to the content // view boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList); return super.onPrepareOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(final MenuItem item) { if (mDrawerToggle.onOptionsItemSelected(getMenuItem(item))) { return true; } int itemId = item.getItemId(); if (itemId == R.id.search) { if (searchAllowed == false) { } else if (itemId == R.id.contact) { emailme(); } else if (itemId == R.id.rate) { Uri uri = Uri.parse("market://details?id=" + getPackageName()); Intent myAppLinkToMarket = new Intent(Intent.ACTION_VIEW,uri); try { startActivity(myAppLinkToMarket); } catch (ActivityNotFoundException e) { Toast.makeText(this,"Unable to find Play Market",Toast.LENGTH_SHORT).show(); } } return super.onOptionsItemSelected(item); } public void buyPrem() { Log.d(TAG,"Upgrade button clicked; launching purchase flow for upgrade."); /* * TODO: for security,generate your payload here for verification. See * the comments on verifyDeveloperPayload() for more info. Since this is * a SAMPLE,we just use an empty string,but on a production app you * should carefully generate this. */ String payload = ""; mHelper.launchPurchaseFlow(this,PREM_SKU,10001,mPurchaseFinishedListener,payload); } @Override protected void onActivityResult(int requestCode,int resultCode,Intent data) { Log.d(TAG,"onActivityResult(" + requestCode + "," + resultCode + "," + 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,data); } else { Log.d(TAG,"onActivityResult handled by IABUtil."); } } IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() { @Override public void onIabPurchaseFinished(IabResult result,Purchase purchase) { Log.d(TAG,"Purchase finished: " + result + ",purchase: " + purchase); if (result.isFailure()) { complain("Error purchasing: " + result); // Handle error return; } if (!verifyDeveloperPayload(purchase)) { complain("Error purchasing. Authenticity verification Failed."); return; } Log.d(TAG,"Purchase successful."); if (purchase.getSku().equals(PREM_SKU)) { // bought the premium upgrade! Log.d(TAG,"Purchase is premium upgrade. Congratulating user."); alert("Thank you for upgrading to premium!"); mIsPremium = true; mIsUserPremium = true; searchAllowed = true; } } }; IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() { @Override public void onQueryInventoryFinished(IabResult result,Inventory inventory) { Log.d(TAG,"Query inventory finished."); if (result.isFailure()) { complain("Failed to query inventory: " + result); return; } /*if (inventory.hasPurchase(PREM_SKU)) { mHelper.consumeAsync(inventory.getPurchase(PREM_SKU),null); }*/ Log.d(TAG,"Query inventory was successful."); Purchase premiumPurchase = inventory.getPurchase(PREM_SKU); mIsPremium = (premiumPurchase != null && verifyDeveloperPayload(premiumPurchase)); Log.d(TAG,"User is " + (mIsPremium ? "PREMIUM" : "NOT PREMIUM")); if (mIsPremium) { searchAllowed = true; mIsUserPremium = true; Log.d(TAG,"Should be premium by Now..."); } Log.d(TAG,"Initial inventory query finished; enabling main UI."); } }; 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; } /*public void consumeItem() { mHelper.queryInventoryAsync(mReceivedInventoryListener); }*/ IabHelper.QueryInventoryFinishedListener mReceivedInventoryListener = new IabHelper.QueryInventoryFinishedListener() { @Override public void onQueryInventoryFinished(IabResult result,Inventory inventory) { if (result.isFailure()) { // Handle failure } else { searchAllowed = false; //mHelper.consumeAsync(inventory.getPurchase(PREM_SKU),// mConsumeFinishedListener); } } }; IabHelper.OnConsumeFinishedListener mConsumeFinishedListener = new IabHelper.OnConsumeFinishedListener() { @Override public void onConsumeFinished(Purchase purchase,IabResult result) { if (result.isSuccess()) { } else { // handle error } } }; @Override public void onDestroy() { super.onDestroy(); if (mHelper != null) mHelper.dispose(); mHelper = null; } void complain(String message) { Log.e(TAG,"**** TrivialDrive Error: " + message); alert("Error: " + message); } void alert(String message) { AlertDialog.Builder bld = new AlertDialog.Builder(this); bld.setMessage(message); bld.setNeutralButton("OK",null); Log.d(TAG,"Showing alert dialog: " + message); bld.create().show(); } private android.view.MenuItem getMenuItem(final MenuItem item) { return new android.view.MenuItem() { @Override public int getItemId() { return item.getItemId(); } public boolean isEnabled() { return true; } @Override public boolean collapseActionView() { // TODO Auto-generated method stub return false; } @Override public boolean expandActionView() { // TODO Auto-generated method stub return false; } @Override public ActionProvider getActionProvider() { // TODO Auto-generated method stub return null; } @Override public View getActionView() { // TODO Auto-generated method stub return null; } @Override public char getAlphabeticShortcut() { // TODO Auto-generated method stub return 0; } @Override public int getGroupId() { // TODO Auto-generated method stub return 0; } @Override public Drawable getIcon() { // TODO Auto-generated method stub return null; } @Override public Intent getIntent() { // TODO Auto-generated method stub return null; } @Override public ContextMenuInfo getMenuInfo() { // TODO Auto-generated method stub return null; } @Override public char getNumericShortcut() { // TODO Auto-generated method stub return 0; } @Override public int getOrder() { // TODO Auto-generated method stub return 0; } @Override public SubMenu getSubMenu() { // TODO Auto-generated method stub return null; } @Override public CharSequence getTitle() { // TODO Auto-generated method stub return null; } @Override public CharSequence getTitleCondensed() { // TODO Auto-generated method stub return null; } @Override public boolean hasSubMenu() { // TODO Auto-generated method stub return false; } @Override public boolean isActionViewExpanded() { // TODO Auto-generated method stub return false; } @Override public boolean isCheckable() { // TODO Auto-generated method stub return false; } @Override public boolean isChecked() { // TODO Auto-generated method stub return false; } @Override public boolean isVisible() { // TODO Auto-generated method stub return false; } @Override public android.view.MenuItem setActionProvider( ActionProvider actionProvider) { // TODO Auto-generated method stub return null; } @Override public android.view.MenuItem setActionView(View view) { // TODO Auto-generated method stub return null; } @Override public android.view.MenuItem setActionView(int resId) { // TODO Auto-generated method stub return null; } @Override public android.view.MenuItem setAlphabeticShortcut(char alphaChar) { // TODO Auto-generated method stub return null; } @Override public android.view.MenuItem setCheckable(boolean checkable) { // TODO Auto-generated method stub return null; } @Override public android.view.MenuItem setChecked(boolean checked) { // TODO Auto-generated method stub return null; } @Override public android.view.MenuItem setEnabled(boolean enabled) { // TODO Auto-generated method stub return null; } @Override public android.view.MenuItem setIcon(Drawable icon) { // TODO Auto-generated method stub return null; } @Override public android.view.MenuItem setIcon(int iconRes) { // TODO Auto-generated method stub return null; } @Override public android.view.MenuItem setIntent(Intent intent) { // TODO Auto-generated method stub return null; } @Override public android.view.MenuItem setNumericShortcut(char numericChar) { // TODO Auto-generated method stub return null; } @Override public android.view.MenuItem setOnActionExpandListener( OnActionExpandListener listener) { // TODO Auto-generated method stub return null; } @Override public android.view.MenuItem setOnMenuItemClickListener( OnMenuItemClickListener menuItemClickListener) { // TODO Auto-generated method stub return null; } @Override public android.view.MenuItem setShortcut(char numericChar,char alphaChar) { // TODO Auto-generated method stub return null; } @Override public void setShowAsAction(int actionEnum) { // TODO Auto-generated method stub } @Override public android.view.MenuItem setShowAsActionFlags(int actionEnum) { // TODO Auto-generated method stub return null; } @Override public android.view.MenuItem setTitle(CharSequence title) { // TODO Auto-generated method stub return null; } @Override public android.view.MenuItem setTitle(int title) { // TODO Auto-generated method stub return null; } @Override public android.view.MenuItem setTitleCondensed(CharSequence title) { // TODO Auto-generated method stub return null; } @Override public android.view.MenuItem setVisible(boolean visible) { // TODO Auto-generated method stub return null; } }; } private class DrawerItemClickListener implements ListView.OnItemClickListener { public void onItemClick(AdapterView<?> parent,View view,int position,long id) { switch (position) { case 0: mDrawerLayout.closeDrawer(mDrawerList); break; case 1: Intent c1 = new Intent(getBaseContext(),1.class); startActivity(c1); break; case 2: Intent c2 = new Intent(getBaseContext(),5.class); startActivity(c2); break; case 3: Intent c3 = new Intent(getBaseContext(),3.class); startActivity(c3); break; case 4: Intent c4 = new Intent(getBaseContext(),4.class); startActivity(c4); break; default: } } } public void selectItem(int position) { switch (position) { case 0: break; case 1: setContentView(R.layout.1); break; case 2: setContentView(R.layout.2); break; case 3: setContentView(R.layout.3); break; case 4: setContentView(R.layout.4); break; default: } } @Override public void setTitle(CharSequence title) { mTitle = title; getSupportActionBar().setTitle(mTitle); } /** * When using the ActionBarDrawerToggle,you must call it during * onPostCreate() and onConfigurationChanged()... */ @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); // Sync the toggle state after onRestoreInstanceState has occurred. mDrawerToggle.syncState(); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); // Pass any configuration change to the drawer toggls mDrawerToggle.onConfigurationChanged(newConfig); } }
因此,您需要在某处保存mIsPremium的值,并在再次打开应用程序时加载它.
我建议你使用SharedPreferences来完成这项任务.
这就是你如何做到这一点:
在IabHelper.OnIabPurchaseFinishedListener中,您需要保存您的偏好:
if (purchase.getSku().equals(PREM_SKU)) { // bought the premium upgrade! Log.d(TAG,"Purchase is premium upgrade. Congratulating user."); alert("Thank you for upgrading to premium!"); mIsPremium = true; mIsUserPremium = true; searchAllowed = true; SharedPreferences prefs = this.getBaseContext().getSharedPreferences( "com.example.yourapp",0); prefs.edit().putBoolean("premium",true).apply; }
在用户成功购买保费后,您可以将保费状态“true”保存到共享偏好“premium”.
在onCreate()方法中,您需要加载首选项:
SharedPreferences prefs = this.getBaseContext().getSharedPreferences( "com.example.yourapp",0); mIsPremium = prefs.getBoolean("premium",false);
以上是大佬教程为你收集整理的android – 应用内结算:库存不正确;让用户再次购买全部内容,希望文章能够帮你解决android – 应用内结算:库存不正确;让用户再次购买所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。