Не могу разобраться, как реализовать в приложении платное отключение рекламы с помощью in-app библиотеки AnjLab?
Внизу приведу пример кода:
1) Встраивание рекламы. Здесь все работает, так что если кому нужно можете пользоваться.
Подключение библиотеки build.gradle
compile 'com.google.android.gms:play-services-ads:9.4.0'
В файле AndroidManifest.xml
В текстовый ресурс String.xml вставляю id рекламного баннера adMobe
Вставляю баннер в файл 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 с переключателем.
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 есть, и про ее обновление, и диалоги с пользователем.
Пишите в комментарии, если будут вопросы. Успехов! ;-)
// Увы, но весь код приложения за Вас я написать не могу. Ваш вопрос не глупый! По природе вопросов глупых нет, есть люди, которые полностью в чем-то не разобрались/изучили.
// Кстати, Вы мне мой же код в вопросе прислали. Изучите его хорошо. Я постарался все покрыть комментариями, чтобы было понятно каждому, что происходит на той или иной строчке класса
Комментариев нет:
Отправить комментарий