Страницы

Поиск по вопросам

суббота, 27 октября 2018 г.

Как реализовать платное отключение рекламы с помощью in-app

Не могу разобраться, как реализовать в приложении платное отключение рекламы с помощью in-app библиотеки AnjLab?
Внизу приведу пример кода:
1) Встраивание рекламы. Здесь все работает, так что если кому нужно можете пользоваться.
Подключение библиотеки build.gradle
compile 'com.google.android.gms:play-services-ads:9.4.0'
В файле AndroidManifest.xml

В текстовый ресурс String.xml вставляю id рекламного баннера adMobe
ca-app-pub-8911529113562577/1565264629
Вставляю баннер в файл app_bar_main.xml
...

Файл для отображение рекламного баннера Ads.java
public class Ads { // создаем метод для создания баннера public static void showBanner(final Activity activity) {
// создаем баннер, находим его по id final AdView banner = (AdView) activity.findViewById(R.id.banner); // строит и загружает баннер // импорт android.gms.ads AdRequest adRequest = new AdRequest.Builder().build(); banner.loadAd(adRequest);
// слушатель загрузки баннера banner.setAdListener(new AdListener() { @Override public void onAdLoaded() { super.onAdLoaded(); setupContentViewPadding(activity, banner.getHeight()); } }); }
// метод подвигает нижний край экрана, на высоте размера баннера public static void setupContentViewPadding(Activity activity, int padding) { View view = activity.findViewById(R.id.coordinator); view.setPadding(view.getPaddingLeft(), view.getPaddingTop(), view.getPaddingRight(), padding); } }
И наконец код для показа рекламного баннера, вставляю в MainActivity.java
// внедряем баннер Ads.showBanner(this);
Все реклама отображается, но как теперь реализовать платное отключение? Нашел пример на этом сайте. Ссылка
2) Отключение рекламы. Я сделал таким образом, в левом меню создал ссылку на отключение рекламы, на файл SettingsFrag.java
Код:
public class SettingsFrag extends Fragment implements BillingProcessor.IBillingHandler {
private boolean adsStatus; // храним текущий статус отображения рекламы private boolean initialize; // храним готовность к покупкам private BillingProcessor bp; // переменная нашего процессора
private PreferencesManager prefManager; // класс, который работает с SharedPreferences. Я для себя решил вынести всю логику отдельно private Resources resources; // для работы с ресурсами. Раз получаем и постоянно обращаемся private ToggleButton tbAdsState; // кнопка
Context mContext; @Override public void onAttach(Context context) { super.onAttach(context); this.mContext = context; // инициализируем `BillingProcessor`. В документации на `GitHub` сказано, что для защиты от липовых покупок через приложения типа // `freedom` необходимо в конструктор `BillingProcessor`'а передать еще и свой `MERCHANT_ID`. Где его взять - внизу текущего ответа опишу шаги bp = new BillingProcessor(context, InAppBillingResources.getRsaKey(), InAppBillingResources.getMerchantId(), this);
prefManager = new PreferencesManager(context); // класс, который работает с `SharedPreferences` adsStatus = prefManager.getAdsStatus(); // получаем из `SharedPreferences` сохраненное состояние рекламы (ВКЛ / ВЫКЛ) resources = context.getResources(); // получаем "доступ" к ресурсам }
public static SettingsFrag newInstance() { Bundle args = new Bundle(); SettingsFrag fragment = new SettingsFrag(); fragment.setArguments(args); return fragment; }
@Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { // создаем `View` экрана настроек View settView = inflater.inflate(R.layout.frag_sett_screen, container, false);
// инициализация других полей tbAdsState = (ToggleButton) settView.findViewById(R.id.tbAdsState); // инициализация других полей
// вешаем слушателя нажатий по кнопке `ToggleButton` tbAdsState.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) {
// `adsStatus` : getAdsStatus из класса `PreferencesManager` // true - enabled (ВКЛ) | false - disabled (ВЫКЛ) if (adsStatus && initialize) { bp.purchase(getActivity(), InAppBillingResources.getSKU_Disable_Ads()); }
if (!adsStatus) { tbAdsState.setChecked(false); Toast.makeText(getActivity(), getActivity().getResources().getString(R.string.txt_ads_is_already_disabled), Toast.LENGTH_LONG).show(); }
} });
return settView; }
@Override public void onResume() { super.onResume(); tbAdsState.setChecked(prefManager.getAdsStatus()); }
// диалог, который скажет пользователю, что после покупки необходимо перезагрузиться private void restartDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setTitle(resources.getString(R.string.msg_notification_Title)); builder.setCancelable(false); builder.setPositiveButton("Ок", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { restartApp(); dialog.cancel(); } } ); AlertDialog resetDialog = builder.create(); resetDialog.show();
}
// перезагружаем приложение private void restartApp() { Intent rIntent = mContext.getPackageManager().getLaunchIntentForPackage(mContext.getPackageName()); if (rIntent != null) { rIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); mContext.startActivity(rIntent); } }
// ... другие методы класса // [START billing part of class]
@Override public void onProductPurchased(@NonNull String productId, TransactionDetails details) { // Called when requested PRODUCT ID was successfully purchased // Вызывается, когда запрашиваемый PRODUCT ID был успешно куплен
if (bp.isPurchased(productId)) { prefManager.setAdsStatus(false); // 1. записываем в `SharedPreferences` состояние рекламы (ВЫКЛ / false) tbAdsState.setChecked(false); // 2. устанавливаем `TogglButton` в соответствующее состояние restartDialog(); // 3. перезагружаем приложение } else { tbAdsState.setChecked(true); // иначе, если не прошла покупка, оставляем состояние (ВКЛ / true) } }
@Override public void onPurchaseHistoryRestored() { //Вызывается, когда история покупки была восстановлена, // и список всех принадлежащих идентификаторы продуктов был загружен из Google Play
// так Вы сможете НУЖНУЮ покупку проверить for (String sku : bp.listOwnedProducts()) { //MyAppLogs.show("Owned Managed Product: " + sku); boolean wasBouhtg = sku.equals(InAppBillingResources.getSKU_Disable_Ads()); if (wasBouhtg) { // true - куплено // пишем в `SharedPreferences`, что отключили рекламу } else { // false - не куплено // пишем в `SharedPreferences`, что нужно показывать рекламу } } }
@Override public void onBillingError(int errorCode, Throwable error) { // Вызывается, когда появляется ошибка. См. константы класса // для получения более подробной информации }
@Override public void onBillingInitialized() { // Вызывается, когда bp был инициализирован и он готов приобрести initialize = true; } // [END billing part of class]
}
Файл PreferencesManager.java
public class PreferencesManager {
private static SharedPreferences mSPref; private SharedPreferences.Editor mSPEditor;
private static final String APP_PREF = "app_pref"; // имя файла настроек Вашего приложения
private static final String APP_ADS_STATUS = "adsStatus"; // статус рекламы
public PreferencesManager(Context context) { mSPref = context.getSharedPreferences(APP_PREF, Context.MODE_PRIVATE); }
public void setAdsStatus(boolean adsStatus) { // true - enabled | false - disabled mSPEditor = mSPref.edit(); mSPEditor.putBoolean(APP_ADS_STATUS, adsStatus); mSPEditor.apply(); }
public boolean getAdsStatus() { return mSPref.getBoolean(APP_ADS_STATUS, true); } }
Файл InAppBillingResources.java
public class InAppBillingResources {
// Ваш `RSA` ключ из `Google Play Developer Console` private static final String RSA_KEY = "MAFD........."; private static final String MERCHANT_ID = "18........."; // Ваш `MERCHANT_ID` из `Google Play Developer Console` private static final String SKU_DISABLE_ADS = "android.test.purchased"; // Ваш `product_id`, создается в `Google Play Developer Console`
public static String getRsaKey() { return RSA_KEY; }
public static String getMerchantId() { return MERCHANT_ID; }
public static String getSKU_Disable_Ads() { return SKU_DISABLE_ADS; } }
Файл frag_sett_screen.xml с переключателем.

tools:layout_editor_absoluteX="87dp" tools:layout_editor_absoluteY="66dp"/>

3) Как теперь этот код совместить с отображением рекламы Ads.showBanner(this);? Что бы если нажать на переключатель или если приложение было уже куплено то скрыть Ads.showBanner(this); и наоборот если не оплатили, то показывать баннер.
Я понимаю может кому-то этот вопрос покажется глупым, но у меня абсолютно уже мозги не работают, не могу никак сообразить.


Ответ

На сколько я понял, Ваше приложение работает по схеме в одной Activity показываем Fragmentы. Хорошо.
Так как у Вас есть метод, который подымает пользовательский контент и показывает под ним рекламу, то мы его и будем пытаться обуздать :-)
Что делаем ?
В классе MainActivity
(или как там у Вас называется главная Activity)
@Override protected void onCreate(Bundle savedInstanceState) { // получаем наши `SharedPreferences` PreferencesManager prefManager = new PreferencesManager(this); super.onCreate(savedInstanceState); setContentView(R.layout.activity_min);
// проверяем нашу запись в файле настроек. Если реклама не отключена, то у нас будет true записано, то есть состояние ВКЛЮЧЕНО // а также проверяем подключение к сети Internet простеньким способом // true - enabled | false - disabled boolean adsState = prefManager.getAdsStatus(); if (adsState && CheckURLConnection.isNetworkAvailable(this)) { Ads.showBanner(this, adsState); } else { Ads.showBanner(this, adsState); }
// далее Вы просто инициализируете все свои `View` в `MainActivity` // добавляете что нужно
}
класс CheckURLConnection
public class CheckURLConnection {
public static boolean isNetworkAvailable(Context context) { ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo(); return activeNetworkInfo != null; }
}
класс Ads
public class Ads { public static void showBanner(final Activity activity, boolean adsState) {
// вместо LinearLayout у Вас будет ВАШ View, который располагается над AdView. В вопросе фигурирует CoordinatorLayout, вот его и нужно будет здесь инициализировать по аналогии с LinearLayout final LinearLayout adsContainer = (LinearLayout) activity.findViewById(R.id.container); final AdView mAdView = (AdView) activity.findViewById(R.id.banner);
if (adsState) { AdRequest adRequest; // DEBUG or RELEASE if (BuildConfig.DEBUG) { adRequest = new AdRequest.Builder() .addTestDevice() .build(); } else { adRequest = new AdRequest.Builder() .build(); } mAdView.loadAd(adRequest);
mAdView.setAdListener(new AdListener() { @Override public void onAdLoaded() { super.onAdLoaded(); setupContentViewPadding(activity, mAdView.getHeight()); } }); } else { adsContainer.removeView(mAdView); } }
public static void setupContentViewPadding(Activity activity, int padding) { View view = activity.findViewById(R.id.container); // рекомендую добавить 8dp отступа над баннером, чтобы была ЧЕТКАЯ граница, которая отделяет его и пользовательские данные (Google просто рекомендует делать границу, иначе могут быть ложные клики и бан AdMob аккаунта) view.setPadding(view.getPaddingLeft(), view.getPaddingTop(), view.getPaddingRight(), padding + 8); } }
<здесь Hash Вашего смартфона или эмулятора> [тип String] - нужно делать для того, чтобы в режиме отладки приложения (DEBUG) Вы сами себе не испортили всё! То есть не стали показывать сами себе настоящую рекламу, проверять клики по ней. Проверка - это нормально! Но не нормально проверять на реальный баннерах, за что Google/AdMob банит аккаунт AdSense. Когда соберете приложение (выпустите его в Google Play Маркет), то будет выполняться блок else условия if (BuildConfig.DEBUG)
В итоге мы получаем: - в MainActivity происходит проверка состояния adsState из наших локальных настроек PreferencesManager, а также проверка доступа в сеть Internet. Если куплено отключение рекламы, то метод getAdsStatus() вернет нам false. И реклама не будет показана. - как производить покупку отключения рекламы я описал здесь (https://ru.stackoverflow.com/a/770241/22239). Там и про ToggleButton есть, и про ее обновление, и диалоги с пользователем.
Пишите в комментарии, если будут вопросы. Успехов! ;-)
// Увы, но весь код приложения за Вас я написать не могу. Ваш вопрос не глупый! По природе вопросов глупых нет, есть люди, которые полностью в чем-то не разобрались/изучили.
// Кстати, Вы мне мой же код в вопросе прислали. Изучите его хорошо. Я постарался все покрыть комментариями, чтобы было понятно каждому, что происходит на той или иной строчке класса

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

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