Много раз уже просили написать статью о том, как в приложении реализовать платное отключение рекламы. Вообще, реализовать рекламу легко, по In-app так же есть куча информации в официальной документации. Ну, если кому-то всё же статья пригодится, то хорошо.
In-App Purchase представляет собой сервис покупки виртуальных товаров внутри приложения (например игровой валюты, новых уровней и т.д.). Применяется он в основном в играх, в тех случаях, когда встает вопрос о необходимости заработка на своем творении.
В данной статье рассмотрю как можно использовать In-App Purchase для отключения рекламы в своём приложении.
Реклама в приложении
В принципе, можно взять любую площадку. Возьмём, к примеру AdMob. Я для удобства обычно подобные вещи в обёртки запихиваю, чтобы при смене площадки, если потребуется, почти ничего не пришлось менять. Обёртки для рекламной площадки должны реализовывать интерфейс:
public interface AdsControllerBase { public void createView( RelativeLayout layout); public void show(boolean show); public void onStart(); public void onDestroy(); public void onResume(); public void onStop(); }
Тогда обёртка для AdMob будет выглядеть примерно так:
public class AdMobController implements AdsControllerBase, AdListener { private static final String ADMOB_ID = "ваш_идентификатор_из_AdMob"; private static final int REQUEST_TIMEOUT = 30000; private AdView adView; private Context c; private long last; public AdMobController(Context activity, RelativeLayout layout) { this.c = activity; createView(layout); last = System.currentTimeMillis() - REQUEST_TIMEOUT; } public void createView(RelativeLayout layout) { if(PreferencesHelper.isAdsDisabled()) return; adView = new AdView((Activity) c, AdSize.BANNER, ADMOB_ID); RelativeLayout.LayoutParams adParams = new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); adParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); adParams.addRule(RelativeLayout.CENTER_HORIZONTAL); adView.setAdListener(this); layout.addView(adView, adParams); adView.loadAd(new AdRequest()); } // обновляем рекламу не чаще, чем раз в 30 секунд public void show(boolean show) { if(adView == null) return; adView.setVisibility((show) ? View.VISIBLE : View.GONE); if (show && (System.currentTimeMillis() - last > REQUEST_TIMEOUT)) { last = System.currentTimeMillis(); adView.loadAd(new AdRequest()); } } @Override public void onReceiveAd(Ad ad) {} @Override public void onFailedToReceiveAd(Ad ad, AdRequest.ErrorCode error) {} @Override public void onPresentScreen(Ad ad) {} @Override public void onDismissScreen(Ad ad) {} @Override public void onLeaveApplication(Ad ad) {} @Override public void onStart() {} @Override public void onDestroy() {} @Override public void onResume() {} @Override public void onStop() {} }
Тогда инициализация рекламы будет такой:
AdsControllerBase ads = new AdMobController(this, layout);
При такой реализации в случае смены площадки, мы просто создадим инстанс другого класса. Для работы вам нужен лишь ID_приложения. который получите после создания в приложения в админке Admob.
In-app purchasing или внутренние платежи в приложениях
Для того, чтобы работать с системой покупок необходим файл IMarketBillingService.aidl. Лежит он в /user/android-sdk-linux/extras/google/play_billing директории с SDK. Положить файлик надо в com.android.vending.billing пакет вашего приложения.
О типах покупок можно почитать тут. Нас интересую восстанавливаемые покупки, то есть те, что привязываются к аккаунту и повторно их уже не купить. Если вы удалите приложение и постановите заново, то покупка будет восстановлена. В нашем случае, после покупки отключения рекламы, реклама больше не будет беспокоить пользователя. Это касается и других устройств: если пользователь залогиниться на другом устройство под своим аккаунтом, то в приложение будет восстановлена покупка и реклама будет отключена.
Для работы необходимо добавить разрешение в AndroidManifest.xml:
<uses-permission android:name="com.android.vending.BILLING"/>
.
Очень помогает официальная документация и пример из SDK.
Необходимо определить ключик в приложении — PublicKey, полученный при регистрации аккаунта на Android Market
Определяем IabHelper и инициализируем. Если удачно, то пытаемся восстановить покупки.
// id вашей покупки из админки в Google Play static final String SKU_ADS_DISABLE = "com.ads.disable"; IabHelper mHelper; private void billingInit() { mHelper = new IabHelper(this, BASE64_PUBLIC_KEY); // включаем дебагинг (в релизной версии ОБЯЗАТЕЛЬНО выставьте в false) mHelper.enableDebugLogging(true); // инициализируем; запрос асинхронен // будет вызван, когда инициализация завершится mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() { public void onIabSetupFinished(IabResult result) { if (!result.isSuccess()) { return; } // чекаем уже купленное mHelper. queryInventoryAsync(mGotInventoryListener); } }); }
mGotInventoryListener
— слушатель для восстановления покупок.
// Слушатель для востановителя покупок. IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() { private static final String TAG = "QueryInventoryFinishedListener"; public void onQueryInventoryFinished(IabResult result, Inventory inventory) { LOG.d(TAG, "Query inventory finished."); if (result.isFailure()) { LOG.d(TAG, "Failed to query inventory: " + result); return; } LOG.d(TAG, "Query inventory was successful."); /* * Проверяются покупки. * Обратите внимание, что надо проверить каждую покупку, чтобы убедиться, что всё норм! * см. verifyDeveloperPayload(). */ Purchase purchase = inventory.getPurchase(SKU_ADS_DISABLE); PreferencesHelper.savePurchase( context, PreferencesHelper.Purchase.DISABLE_ADS, purchase != null && verifyDeveloperPayload(purchase)); ads.show(!PreferencesHelper.isAdsDisabled()); } };
Теперь надо, собственно, саму покупку реализовать:
private void buy(){ if(!PreferencesHelper.isAdsDisabled()){ /* для безопасности сгенерьте payload для верификации. В данном примере просто пустая строка юзается. * Но в реальном приложение подходить к этому шагу с умом. */ String payload = ""; mHelper.launchPurchaseFlow(this, SKU_ADS_DISABLE, RC_REQUEST, mPurchaseFinishedListener, payload); } }
SKU_ADS_DISABLE — идентификатор товара, который вы создали в адмике Google Play. mPurchaseFinishedListener
— слушатель:
// слушатель завершения покупки IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() { public void onIabPurchaseFinished(IabResult result, Purchase purchase) { if (result.isFailure()) { return; } if (!verifyDeveloperPayload(purchase)) { return; } if (purchase.getSku().equals(SKU_ADS_DISABLE)) { Toast.makeText(getApplicationContext(), "Purchase for disabling ads done.", Toast.LENGTH_SHORT); // сохраняем в настройках, что отключили рекламу PreferencesHelper.savePurchase( context, PreferencesHelper.Purchase.DISABLE_ADS, true); // отключаем рекламу ads.show(!PreferencesHelper.isAdsDisabled()); } } };
Стоит отдельно поговорить о методе по верификации:
boolean verifyDeveloperPayload(Purchase p) { String payload = p.getDeveloperPayload(); /* * TODO: здесь необходимо свою верификацию реализовать * Хорошо бы ещё с использованием собственного стороннего сервера. */ return true; }
Сейчас нет никакой проверки покупок, но в реальном приложении вы должны сверять полученные данные с той сгенерированой строкой, что вы отправили в запросе на покупку. Проверять это надо на своём стороннем сервере. Для обычно приложения или офф-лайн игры это может и не критично, но для он-лайн игры это очень важно.
В принципе всё, теперь при запуске приложения просиходит проверка настроек (куда мы сохранили, что отключили рекламу):
PreferencesHelper.loadSettings(this);
После чего реклама уже не будет показываться.
Тестирование покупок
Сейчас довольно удобно тестировать своё приложение. Можно залить .apk как альфа/бета версию и опубликовать. При этом можно назначить группу в Google+, которая будет иметь возможность к тестированию. Если вы публикуете альфа или бета версию приложения, то в маркете она не появится, иметь доступ будет только эта группа.
Тестеры смогут осуществлять покупки. Деньги будут списываться без комиссии и будут возвращены после 15 минут после покупки. Так что, не беспокойтесь. Вот только у вас не получится протестировать приложение, если ваш аккаунт на устройстве и аккаунт издателя один и тот же =/
Полностью рабочий пример можете форкнуть с гитхаба.