...

суббота, 23 ноября 2013 г.

[recovery mode] Android In-app purchasing: платное отключение рекламы в своём приложении

Много раз уже просили написать статью о том, как в приложении реализовать платное отключение рекламы. По In-app уже былистатьи на хабре. Правда, они старую версию API рассматривали. В принципе, новая версия не особо то и отличается от старой. Была похожая статья, но там больше именно про отображение рекламы рассказывалось, а второй части статьи мы так и не увидели. Как оказалось, многим до сих пор интересен этот вопрос, решил написать как это реализовать в своём приложении.



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 будет выглядеть примерно так:


Обёртка для 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 минут после покупки. Так что, не беспокойтесь. Вот только у вас не получится протестировать приложение, если ваш аккаунт на устройстве и аккаунт издателя один и тот же =/


Полностью рабочий пример можете посмотреть на гитхабе.


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at fivefilters.org/content-only/faq.php#publishers.


Комментариев нет:

Отправить комментарий