【问题标题】:Android In-App Billing: Ads are not removing when In-App is madeAndroid 应用内计费:制作应用内时不会删除广告
【发布时间】:2016-09-11 09:56:45
【问题描述】:

我已在我的 Activity 中实施应用内结算

这是我的onIabPurchaseFinished() 方法:

@Override
public void onIabPurchaseFinished(IabResult result, Purchase info) {

    if (!verifyDeveloperPayload(info)) {
        Toast.makeText(this, R.string.error_purchasing, Toast.LENGTH_LONG).show();
    }

    Toast.makeText(this, R.string.premium_bought, Toast.LENGTH_LONG).show();

    if (info.getSku().equals("chords_premium")) {

        /** salva isPremium tra SharedPreferences */
        SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
        SharedPreferences.Editor editor = sharedPref.edit();
        editor.putString("status", "purchased");
        editor.apply();
    }
}

如您所见,我将字符串 "status" 保存到 SharedPreferences 以便我可以从任何地方访问它,并且即使在应用程序关闭后也可以保存它。

然后在我实施广告的其他活动中,我这样写:

final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
    final String status = prefs.getString("status", "free");


    /** gestisce le pubblicita */
    if (status.equals("free")) {
        MobileAds.initialize(getApplicationContext(), "ca-app-pub-6723047396589178/2654753246");

        AdView listBanner = (AdView) findViewById(R.id.chords_list_banner);
        AdRequest adRequest = new AdRequest.Builder().build();
        listBanner.loadAd(adRequest);

        /** carica Ad a tutto schermo */
        chordsListAd = new InterstitialAd(this);
        chordsListAd.setAdUnitId("ca-app-pub-6723047396589178/7447672046");
        requestNewInterstitial();


        chordsListAd.setAdListener(new AdListener() {
            @Override
            public void onAdClosed() {
                requestNewInterstitial();
            }
        });
    }

正如您在此处看到的,广告被if statement 包围,用于检查"status"String 是否设置为空闲。

问题是当我购买高级版时,广告仍然显示。我该如何解决?

【问题讨论】:

    标签: java android in-app-billing ads


    【解决方案1】:

    这是因为您将数据保存在 Base Context 中,并尝试使用 (this) 在当前 Activity 上下文 中找到它。

    final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
    

    final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
    

    此外,更推荐的查询应用内购买项目的方法是查询应用内库存,而不是存储在 sharedprefs 中。

    如 Google 文档中所述

    查询购买的商品

    成功购买后,用户的购买数据会通过 Google Play 的应用内结算服务缓存在本地。最好经常查询应用内结算服务以了解用户的购买情况,例如每当应用启动或恢复时,以便用户当前的应用内产品所有权信息始终反映在您的应用中。

    要从您的应用中检索用户的购买,请在您的 IabHelper 实例上调用 queryInventoryAsync(QueryInventoryFinishedListener)。 QueryInventoryFinishedListener 参数指定一个侦听器,当查询操作完成并处理查询响应时通知该侦听器。从您的主线程进行此调用是安全的。

    mHelper.queryInventoryAsync(mGotInventoryListener); //mHelper is IabHelper instance
    

    如果查询成功,查询结果将存储在一个 Inventory 对象中,该对象会传回给侦听器。 In-app Billing 服务仅返回当前登录到设备的用户帐户进行的购买。

    IabHelper.QueryInventoryFinishedListener mGotInventoryListener
       = new IabHelper.QueryInventoryFinishedListener() {
       public void onQueryInventoryFinished(IabResult result,
          Inventory inventory) {
    
          if (result.isFailure()) {
            // handle error here
          }
          else {
            // does the user have the premium upgrade?
            mIsPremium = inventory.hasPurchase(SKU_PREMIUM);
            // update UI accordingly
          }
       }
    };
    

    【讨论】:

    • 非常感谢您的出色回答!我会考虑使用查询而不是 SharedPreferences。使用 sharedPreferences 有什么实际的缺点吗?
    • 如果应用程序数据由于某些原因被自动或手动擦除。存储在共享首选项中的数据也将丢失。
    【解决方案2】:

    检查是否进行了应用内购买:

    //*************************************checking in app purchase has been made********************************// 
        void testInApp()
        {
            if (!blnBind) return;
            if (mService == null) return;
    
            int result;
            try {
                result = mService.isBillingSupported(3, getPackageName(), "inapp");
    
                //Toast.makeText(context, "isBillingSupported() - success : return " + String.valueOf(result), Toast.LENGTH_SHORT).show();
                Log.i(tag, "isBillingSupported() - success : return " + String.valueOf(result));
            } catch (RemoteException e) {
                e.printStackTrace();
    
                //Toast.makeText(context, "isBillingSupported() - fail!", Toast.LENGTH_SHORT).show();
                Log.w(tag, "isBillingSupported() - fail!");
                return;
            } 
        }
    
        void checkInApp()
        {
    
            if (!blnBind) return;
            if (mService == null) return;
    
            Bundle ownedItems;
            try {
                ownedItems = mService.getPurchases(3, getPackageName(), "inapp", null);
    
                //Toast.makeText(context, "getPurchases() - success return Bundle", Toast.LENGTH_SHORT).show();
                Log.i(tag, "getPurchases() - success return Bundle");
            } catch (RemoteException e) {
                e.printStackTrace();
    
                //Toast.makeText(context, "getPurchases - fail!", Toast.LENGTH_SHORT).show();
                Log.w(tag, "getPurchases() - fail!");
                return;
            }
    
            int response = ownedItems.getInt("RESPONSE_CODE");
            //Toast.makeText(context, "getPurchases() - \"RESPONSE_CODE\" return " + String.valueOf(response), Toast.LENGTH_SHORT).show();
            Log.i(tag, "getPurchases() - \"RESPONSE_CODE\" return " + String.valueOf(response));
    
            if (response != 0) return;
    
            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");
    
            Log.i(tag, "getPurchases() - \"INAPP_PURCHASE_ITEM_LIST\" return " + ownedSkus.toString());
            Log.i(tag, "getPurchases() - \"INAPP_PURCHASE_DATA_LIST\" return " + purchaseDataList.toString());
            Log.i(tag, "getPurchases() - \"INAPP_DATA_SIGNATURE\" return " + (signatureList != null ? signatureList.toString() : "null"));
            Log.i(tag, "getPurchases() - \"INAPP_CONTINUATION_TOKEN\" return " + (continuationToken != null ? continuationToken : "null"));
    
            // TODO: management owned purchase  
    
    
            try {
    
    
                if(purchaseDataList.size()>0){
                    jinapp=new JSONArray(purchaseDataList.toString());
                    JSONObject c =  jinapp.getJSONObject(0);
    
                    String productid=c.getString("productId");
    
                    if(productid!=null){
                        SharedPreferences.Editor editor = prefpurchase.edit();
                        editor.putBoolean(Constants.APP_IS_PURCHASED,true);
                        editor.commit();
                    }
                }   
            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    
            // TODO: management owned purchase  
    
        }
    

    在您的 SplashScreen 中编写代码

    现在在您展示广告的活动/片段中,编写以下代码:

    //*******************to check purchase has been made.If yes disable ads and no then show ads******************//
            prefpurchase = this.getSharedPreferences(Constants.GET_IN_APP_STATE, Context.MODE_PRIVATE);
    
            //Toast.makeText(context, "bindService - return " + String.valueOf(blnBind), Toast.LENGTH_SHORT).show();
    
            //In App Purchase
    
            ispurchased=prefpurchase.getBoolean(Constants.APP_IS_PURCHASED,false);
            System.out.println("ispurchased-->"+ispurchased);
            if(ispurchased)
            {
                setContentView(R.layout.activity_home_noads);
    
            }else{
                System.out.println("Getting ad");
                setContentView(R.layout.activity_home);
                //Locate the Banner Ad in activity_main.xml
                AdView adView = (AdView) this.findViewById(R.id.adView);
                AdRequest adRequest = new AdRequest.Builder()
                // Add a test device to show Test Ads
                //.addTestDevice(AdRequest.DEVICE_ID_EMULATOR)
                //.addTestDevice("B2D63***************************")
                .build();
    
    
                // Load ads into Banner Ads
                adView.loadAd(adRequest);
            }
        //*******************************************************************************************************//
    

    逻辑很简单,您正在创建两个版本的布局,一个有广告,另一个没有广告。

    根据 sharedpreference 的值加载正确的布局。

    移动服务:

    在 onCreate() 之前的初始屏幕中全局编写此代码:

    private IInAppBillingService mService;
        private ServiceConnection mServiceConn = new ServiceConnection() {
            @Override
            public void onServiceDisconnected(ComponentName name) {
                mService = null;
            }
    
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                mService = IInAppBillingService.Stub.asInterface(service);
            }
        };
    

    blnBind

    全局声明 blnBind:

    boolean blnBind;
    

    在 SplashActivity 的 onCreate() 中写入:

    // Bind Service
            blnBind = bindService(new Intent(
                    "com.android.vending.billing.InAppBillingService.BIND"),
                    mServiceConn, Context.BIND_AUTO_CREATE);
    
            //Toast.makeText(context, "bindService - return " + String.valueOf(blnBind), Toast.LENGTH_SHORT).show();
            Log.i(tag, "bindService - return " + String.valueOf(blnBind)); 
            //In App Purchase
    

    GET_IN_APP_STATE 或 APP_IS_PURCHASED 是为共享首选项创建的,它们充当首选项值的键。

    //Preferences to check in app purchase
        final static public String GET_IN_APP_STATE = "prefinapp";
        public static final String APP_IS_PURCHASED ="AppIsPurchased";
    

    每次购买时,不要忘记将共享偏好值设置为 true。

    【讨论】:

    • 感谢您的回答。一个问题。 blnBind 和 mService 是什么?我在哪里得到它?
    • 我应该在哪里写绑定服务器?在启动画面或 adActivity 的 oncreate() 中?
    • 最重要的是,什么是“constants.IN_APP_PURCHASED”?它在哪里声明,应该设置在哪里?
    猜你喜欢
    • 1970-01-01
    • 2020-08-05
    • 2018-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多