#android #in_app_purchases
Реализовал в своем приложении отключение рекламы на базе библиотеки с GitHub: "anjlab/android-inapp-billing-v3".
public class HelpActivity extends Activity implements BillingProcessor.IBillingHandler{
ScrollView scrollView;
TextView mTextView;
BillingProcessor bp;
static final String Off_ADVERTISING = "off_advertising";
String fileName = "data";
boolean m_off_advertising = false;
SharedPreferences sPref;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_help);
// Убираем панель уведомлений
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
scrollView = (ScrollView)findViewById(R.id.scrollView);
try {
readFileXML();
} catch (IOException e) {
e.printStackTrace();
}
mTextView = (TextView)findViewById(R.id.textView11);
// String licenseKey = getResources().getString(R.string.license_key);
// bp = new BillingProcessor(this, licenseKey, this);
bp = new BillingProcessor(this, null, this);
mTextView.setOnClickListener(new View.OnClickListener() {
@SuppressLint("ShowToast")
@Override
public void onClick(View v) {
// bp.purchase(HelpActivity.this, "off_advertising");
bp.purchase(HelpActivity.this, "android.test.purch");
}
});
if(m_off_advertising){
//показываем рекламу
mTextView.setText("не показываем рекламу");
}
}
@Override
public void onProductPurchased(@NonNull String productId, @Nullable TransactionDetails
details) {
mTextView.setText("Реклама убрана");
m_off_advertising = true;
saveData();
}
@Override
public void onPurchaseHistoryRestored() {
// mTextView.setText("Реклама восстановлена");
// m_off_advertising = true;
// saveData();
}
@Override
public void onBillingError(int errorCode, @Nullable Throwable error) {
}
@Override
public void onBillingInitialized() {
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (!bp.handleActivityResult(requestCode, resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data);
}
}
@Override
protected void onPause() {
saveData();
super.onPause();
}
@Override
protected void onResume() {
try {
readFileXML();
} catch (IOException e) {
e.printStackTrace();
}
super.onResume();
}
@Override
public void onDestroy() {
saveData();
if (bp != null) {
bp.release();
}
super.onDestroy();
}
void readFileXML() throws IOException {
this.sPref = getSharedPreferences(this.fileName, 0);
this.m_off_advertising = this.sPref.getBoolean(Off_ADVERTISING, false);
}
void saveData() {
//Log.d(TAG, "m_off_advertising save " + this.m_off_advertising);
this.sPref = getSharedPreferences(this.fileName, 0);
SharedPreferences.Editor ed = this.sPref.edit();
ed.putBoolean(Off_ADVERTISING, this.m_off_advertising);
ed.commit();
}
}
Но есть 2 но:
Первое:
После покупки, нужно ещё раз нажать на текст купить, чтобы покупка отобразилась.
Второе:
Метод восстановления срабатывает всегда, и выполняет всё что в нём написано, не проверяя
id продукта
@Override
public void onPurchaseHistoryRestored() {
// mTextView.setText("Реклама восстановлена");
// m_off_advertising = true;
// saveData();
}
Как можно сделать проверку при включении и восстановлении для определённого продукта?
Ответы
Ответ 1
Как я у себя реализовал отключение рекламы в приложении с применением библиотеки
Android In-App-Billing-v3 от AnjLab?
файл build.gradle модуля /app
dependencies {
// Ваши всевозможные библиотеки
// ...
compile 'com.anjlab.android.iab.v3:library:1.0.44'
// ...
// Ваши всевозможные библиотеки
compile fileTree(include: ['*.jar'], dir: 'libs')
testCompile 'junit:junit:4.12'
}
следите за последней release версией библиотеки, если нет возможности заходить на
GitHub страничку и выписывать номер версии оттуда, то можно сделать следующее:
compile 'com.anjlab.android.iab.v3:library:+'
данная строчка будет выделена Android Studio, ставим курсор слева от +
Жмем Alt + Enter, выбираем Replace with specific version
Идем дальше ...
класс SettingsFrag
Мое приложение работает по принципу "В одной Activity отображаю все Fragment'ы."
package com.my_best_of_the_best_application_name.ui.fragment;
// список **import**'ов ...
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; // кнопка
@Override
public void onAttach(Context context) {
super.onAttach(context);
this.mContext = context;
bp = new BillingProcessor(context,
InAppBillingResources.getRsaKey(), InAppBillingResources.getMerchantId(),
this); // инициализируем `BillingProcessor`. В документации на `GitHub` сказано, что
для защиты от липовых покупок через приложения типа `freedom` необходимо в конструктор
`BillingProcessor`'а передать еще и свой `MERCHANT_ID`. Где его взять - внизу текущего
ответа опишу шаги
prefManager = new PreferencesManager(context); // класс, который работает
с `SharedPreferences`
adsStatus = prefManager.getAdsStatus(); // получаем из `SharedPreferences`
сохраненное состояние рекламы (ВКЛ / ВЫКЛ)
resources = context.getResources(); // получаем "доступ" к ресурсам
}
@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;
View alertLayout = View.inflate(mContext, R.layout.dialog_restart, null);
builder = new AlertDialog.Builder(mContext, R.style.AppThemeDialogStyleDark);
builder.setTitle(resources.getString(R.string.msg_notification_Title));
builder.setView(alertLayout);
builder.setCancelable(false);
builder.setPositiveButton(resources.getString(R.string.ans_restart),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
restartApp();
}
});
builder.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
// случай #2 (см. ниже)
}
@Override
public void onBillingError(int errorCode, Throwable error) {
// Вызывается, когда появляется ошибка. См. константы класса
// для получения более подробной информации
}
@Override
public void onBillingInitialized() {
// Вызывается, когда bp был инициализирован и он готов приобрести
initialize = true;
}
// [END billing part of class]
}
класс InAppBillingResources
public class InAppBillingResources {
private static final String RSA_KEY = "GFGFD156GF1SDF1.... FDS156DS"; // Ваш
`RSA` ключ из `Google Play Developer Console`
private static final String MERCHANT_ID = "16..1511.5..82"; // Ваш
`MERCHANT_ID` из `Google Play Developer Console`
private static final String SKU_DISABLE_ADS = "disable_ads"; // Ваш
`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;
}
}
класс PreferencesManager
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);
}
}
Дополнительная полезная информация
Где взять в Google Play Developer Console свой RSA ключ - Читать Google Справку
Где взять в Google Play Developer Console свой MERCHANT_ID - Читать Google Справку
Метод восстановления. Вы можете реализовать восстановление покупок на стартовом activity
приложения. Код инициализации BillingProcessor такой же. Метод onPurchaseHistoryRestored ниже
@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`, что нужно показывать рекламу
}
}
}
// Если где-то я что-то упустил, сообщите, пожалуйста, в комментарии к моему ответу