Как реализовать биллинг в приложении в Android-приложении?

кажется, что довольно сложно реализовать биллинг в приложении в приложении для Android. Как я мог это сделать? Пример приложения из SDK имеет только одно действие, что упрощает его для такого приложения, как mine, которое имеет несколько действий.

6 ответов


хорошо, я попытаюсь объяснить, что я испытал. Я не считаю себя экспертом в этом, но я сломал голову несколько дней.

для начала, у меня было очень плохое время, пытаясь понять рабочий процесс примера и приложения. Я подумал, что лучше начать с простого примера, однако его очень сложно разделить код на маленькие кусочки и не знать, если вы что-то нарушаете. Я расскажу вам, что у меня есть и что я изменил из примера, чтобы сделать это работает.

у меня есть один вид деятельности, где все мои покупки пришли. Это называется Pro.

во-первых, вы должны обновить переменную base64EncodedPublicKey в своем классе безопасности с помощью ключа разработчика публичного рынка, или вы увидите хорошее исключение.

Ну, я связываю свою деятельность с моим BillingService так:

      public class Pro extends TrackedActivity implements OnItemClickListener {

            private BillingService mBillingService;
            private BillingPurchaseObserver mBillingPurchaseObserver;
            private Handler mHandler;

            @Override
            protected void onCreate(Bundle savedInstanceState) {    
                super.onCreate(savedInstanceState);     
                setContentView(R.layout.pro);


                //Do my stuff

                mBillingService = new BillingService();
                mBillingService.setContext(getApplicationContext());

                mHandler = new Handler();
                mBillingPurchaseObserver = new BillingPurchaseObserver(mHandler);

            }

        }



    @Override
    protected void onStart() {
       //Register the observer to the service
        super.onStart();
        ResponseHandler.register(mBillingPurchaseObserver);   
    }


    @Override
    protected void onStop() {
        //Unregister the observer since you dont need anymore
        super.onStop();
        ResponseHandler.unregister(mBillingPurchaseObserver);
    }

    @Override
    protected void onDestroy() {
       //Unbind the service
        super.onDestroy();
        mBillingService.unbind();
    }

таким образом, все покупки разговаривают с этой службой, которая затем отправит запросы JSON на рынок. Можно подумать что покупки совершаются в один и тот же момент, но нет. Вы отправляете запрос, и покупка может прийти через несколько минут или часов. Я думаю, что это в основном для перегрузки сервера и одобрения кредитных карт.

затем у меня есть ListView с моими элементами, и я открываю AlertDialog на каждом из них, приглашая их купить элемент. Когда они нажимают на элемент, я делаю это:

  private class BuyButton implements DialogInterface.OnClickListener {

       private BillingItem item = null;
       private String developerPayload;

       public BuyButton(BillingItem item, String developerPayload) {
        this.item = item;
        this.developerPayload = developerPayload;
        }

            @Override
            public void onClick(DialogInterface dialog, int which) {

                if (GeneralHelper.isOnline(getApplicationContext())){
                    //I track the buy here with GA SDK. 

        mBillingService.requestPurchase(this.item.getSku(), this.developerPayload);             
                } else {                
                    Toast.makeText(getApplicationContext(), R.string.msg_not_online, Toast.LENGTH_SHORT).show();
                }

            }

        }

хорошо, вы должны увидеть, что рынок открывается и пользователь завершает или отменяет покупку.

что тогда важно, это мой PurChaseObserver, который обрабатывает все события, которые отправляет рынок. Это урезанная версия, но вы должны получить точку (см. мои комментарии через код):

private class BillingPurchaseObserver extends PurchaseObserver {
        public BillingPurchaseObserver(Handler handler) {
            super(Pro.this, handler);
        }

        @Override
        public void onBillingSupported(boolean supported) {

            if (supported) {
                //Enable buy functions. Not required, but you can do stuff here. The market first checks if billing is supported. Maybe your country is not supported, for example. 
            } else {
                Toast.makeText(getApplicationContext(), R.string.billing_not_supported, Toast.LENGTH_LONG).show();
            }
        }

        @Override
        public void onPurchaseStateChange(PurchaseState purchaseState, String itemId,
                int quantity, long purchaseTime, String developerPayload) {

//This is the method that is called when the buy is completed or refunded I believe. 
// Here you can do something with the developerPayload. Its basically a Tag you can use to follow your transactions. i dont use it. 

        BillingItem item = BillingItem.getBySku(getApplicationContext(), itemId);

        if (purchaseState == PurchaseState.PURCHASED) {
            if (item != null){
//This is my own implementation that sets the item purchased in my database. BillingHelper is a class with methods I use to check if the user bought an option and update the UI. You should also check for refunded. You can see the Consts class to find what you need to check for. 

                    boolean resu = item.makePurchased(getApplicationContext());
                    if (resu){                      
                        Toast.makeText(getApplicationContext(), R.string.billing_item_purchased, Toast.LENGTH_LONG).show();
                    }
                }
            }
        }

        private void trackPurchase(BillingItem item, long purchaseTime) {           
            //My code to track the purchase in GA
        }

        @Override
        public void onRequestPurchaseResponse(RequestPurchase request,
                ResponseCode responseCode) {

               //This is the callback that happens when you sent the request. It doesnt mean you bought something. Just that the Market received it. 

            if (responseCode == ResponseCode.RESULT_OK) {               

                Toast.makeText(getApplicationContext(), R.string.billing_item_request_sent, Toast.LENGTH_SHORT).show();

            } else if (responseCode == ResponseCode.RESULT_USER_CANCELED) {
                //The user canceled the item. 
            } else {
            //If it got here, the Market had an unexpected problem. 
            }
        }

        @Override
        public void onRestoreTransactionsResponse(RestoreTransactions request,
                ResponseCode responseCode) {
            if (responseCode == ResponseCode.RESULT_OK) {
//Restore transactions should only be run once in the lifecycle of your application unless you reinstalled the app or wipe the data. 

                SharedPreferences.Editor edit = PreferencesHelper.getInstance().getDefaultSettings(getApplicationContext()).edit();
                edit.putBoolean(Consts.DB_INITIALIZED, true);
                edit.commit();

            } else {
    //Something went wrong
            }
        }
    }

и я считаю,что вам не нужно ничего редактировать. Остальная часть кода "работает". Вы можете попробовать использовать образец SKU сначала в собственных элементах " android.тест.приобретенный." До сих пор я тестировал это, и это работает, однако мне все еще нужно охватить все, как возвращенное состояние. В этом случае я позволяю пользователю сохранить функции, но я хочу убедиться, что он работает идеально, прежде чем его модифицировать.

Я надеюсь, это поможет вам и другим.


V3: вот учебник для быстрого запуска.. Он использует вспомогательные классы из примера google (Trivial Drive)... Хорошо, как первый "привет Биллинг"..

http://www.techotopia.com/index.php/Integrating_Google_Play_In-app_Billing_into_an_Android_Application_%E2%80%93_A_Tutorial


для биллинга в приложении v3, я нашел это действительно helpful.
http://blog.blundellapps.com/simple-inapp-billing-payment-v3/


Если вы хотите использовать простую библиотеку для публикации в Google Play и Amazon Appstore, вы можете пойти с RoboBillingLibrary. Он абстрагирует детали обоих в одну простую в использовании библиотеку. Подробные инструкции приведены на странице Github.


существует полный пример Android в приложении Биллинг v3 шаг за шагом с скриншотом. Пожалуйста, проверьте учебник: Android в приложении Биллинг v3 с помощью класса ServiceConnection

надеюсь, это поможет.

дополнительные пояснения, пройти через этот урок: реализация биллинга в приложении в версии 3 API

шаги для интеграции в приложение Биллинг библиотеки в нашем проекте

обновление ваш AndroidManifest.XML-файл.

создайте ServiceConnection и привязать его к IInAppBillingService.

отправить в приложении платежные запросы из вашего приложения в IInAppBillingService.

обрабатывать в приложении биллинга ответы из Google Play.

Обновление AndroidManifest.в XML

<uses-permission android:name="com.android.vending.BILLING" />

добавить разрешения в Манифесте.xml-файл

добавление файла AIDL в проект

создать приложение. Вы должны увидеть сгенерированный файл с именем IInAppBillingService.java в каталоге /gen вашего проекта.

обновить зависимости в сборке.файл gradle

apply plugin: 'com.android.application'
android {
    compileSdkVersion 24
    buildToolsVersion "24.0.0"
    defaultConfig {
        applicationId "com.inducesmile.androidinapppurchase"
        minSdkVersion 14
        targetSdkVersion 24
        versionCode 2
        versionName "1.1"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:24.1.1'
    compile 'com.intuit.sdp:sdp-android:1.0.3'
    compile 'com.android.support:support-annotations:24.1.1'
    compile 'org.jetbrains:annotations-java5:15.0'
}

InAppPurchaseActivity.java и activity_in_app_purchase.в XML

Это где предложит нашим пользователям приложения возможность сделать покупку в приложении. В файле макета, мы будем дайте пользователю возможность совершать покупки в различных номиналах.

InAppPurchaseActivity.java

Примечание: getAllUserPurchase() и itempurchaseavailability() методы должны вызываться в не поток пользовательского интерфейса, чтобы избежать сбоя приложения.

public class InAppPurchaseActivity extends AppCompatActivity {
    private static final String TAG = InAppPurchaseActivity.class.getSimpleName();
    private IInAppBillingService mService;
    private CustomSharedPreference customSharedPreference;
    String[] productIds = new String[]{Helper.ITEM_ONE_ID, Helper.ITEM_TWO_ID, Helper.ITEM_THREE_ID};
    private ImageView buyOneButton, buyTwoButton, buyThreeButton;
    private static final char[] symbols = new char[36];
    static {
        for (int idx = 0; idx < 10; ++idx)
            symbols[idx] = (char) ('0' + idx);
        for (int idx = 10; idx < 36; ++idx)
            symbols[idx] = (char) ('a' + idx - 10);
    }
    private String appPackageName;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_in_app_purchase);
        appPackageName = this.getPackageName();
        Intent serviceIntent = new Intent("com.android.vending.billing.InAppBillingService.BIND");
        serviceIntent.setPackage("com.android.vending");
        bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE);
        customSharedPreference = new CustomSharedPreference(InAppPurchaseActivity.this);
        buyOneButton = (ImageView)findViewById(R.id.buy_one);
        buyOneButton.setVisibility(View.GONE);
        assert buyOneButton != null;
        buyOneButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(!isBillingSupported()){
                    Helper.displayMessage(InAppPurchaseActivity.this, getString(R.string.in_app_support));
                    return;
                }
                purchaseItem(Helper.ITEM_ONE_ID);
            }
        });
        buyTwoButton = (ImageView)findViewById(R.id.buy_two);
        buyTwoButton.setVisibility(View.GONE);
        assert buyTwoButton != null;
        buyTwoButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(!isBillingSupported()){
                    Helper.displayMessage(InAppPurchaseActivity.this, getString(R.string.in_app_support));
                    return;
                }
                purchaseItem(Helper.ITEM_TWO_ID);
            }
        });
        buyThreeButton = (ImageView)findViewById(R.id.buy_three);
        buyThreeButton.setVisibility(View.GONE);
        assert buyThreeButton != null;
        buyThreeButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(!isBillingSupported()){
                    Helper.displayMessage(InAppPurchaseActivity.this, getString(R.string.in_app_support));
                    return;
                }
                purchaseItem(Helper.ITEM_THREE_ID);
            }
        });
    }
    ServiceConnection mServiceConn = new ServiceConnection() {
        @Override
        public void onServiceDisconnected(ComponentName name) {
            mService = null;
        }
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mService = IInAppBillingService.Stub.asInterface(service);
            AvailablePurchaseAsyncTask mAsyncTask = new AvailablePurchaseAsyncTask(appPackageName);
            mAsyncTask.execute();
        }
    };
    private void purchaseItem(String sku){
        String generatedPayload = getPayLoad();
        customSharedPreference.setDeveloperPayLoad(generatedPayload);
        try {
            Bundle buyIntentBundle = mService.getBuyIntent(3, getPackageName(), sku, "inapp", generatedPayload);
            PendingIntent pendingIntent = buyIntentBundle.getParcelable("BUY_INTENT");
            try {
                startIntentSenderForResult(pendingIntent.getIntentSender(), Helper.RESPONSE_CODE, new Intent(), Integer.valueOf(0), Integer.valueOf(0), Integer.valueOf(0));
            } catch (IntentSender.SendIntentException e) {
                e.printStackTrace();
            }
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == Helper.RESPONSE_CODE) {
            int responseCode = data.getIntExtra("RESPONSE_CODE", 0);
            String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
            String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");
            if (resultCode == RESULT_OK) {
                try {
                    JSONObject purchaseJsonObject = new JSONObject(purchaseData);
                    String sku = purchaseJsonObject.getString("productId");
                    String developerPayload = purchaseJsonObject.getString("developerPayload");
                    String purchaseToken = purchaseJsonObject.getString("purchaseToken");
                    //the developerPayload value is better stored in remote database but in this tutorial
                    //we will use a shared preference
                    for(int i = 0; i < productIds.length; i++){
                        if(productIds[i].equals(sku) && developerPayload.equals(customSharedPreference.getDeveloperPayload())){
                            customSharedPreference.setPurchaseToken(purchaseToken);
                            //access to private content
                            Intent contentIntent = new Intent(InAppPurchaseActivity.this, PrivateContentActivity.class);
                            startActivity(contentIntent);
                        }
                    }
                }
                catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    private String getPayLoad(){
        RandomString randomString = new RandomString(36);
        String payload = randomString.nextString();
        return payload;
    }
    public class RandomString {
        private final Random random = new Random();
        private final char[] buf;
        public RandomString(int length) {
            if (length < 1)
                throw new IllegalArgumentException("length < 1: " + length);
            buf = new char[length];
        }
        public String nextString() {
            for (int idx = 0; idx < buf.length; ++idx)
                buf[idx] = symbols[random.nextInt(symbols.length)];
            return new String(buf);
        }
    }
    public final class SessionIdentifierGenerator {
        private SecureRandom random = new SecureRandom();
        public String nextSessionId() {
            return new BigInteger(130, random).toString(32);
        }
    }
    private class AvailablePurchaseAsyncTask extends AsyncTask<Void, Void, Bundle> {
        String packageName;
        public AvailablePurchaseAsyncTask(String packageName){
            this.packageName = packageName;
        }
        @Override
        protected Bundle doInBackground(Void... voids) {
            ArrayList<String> skuList = new ArrayList<String>();
            skuList.add(Helper.ITEM_ONE_ID);
            skuList.add(Helper.ITEM_TWO_ID);
            skuList.add(Helper.ITEM_THREE_ID);
            Bundle query = new Bundle();
            query.putStringArrayList(Helper.ITEM_ID_LIST, skuList);
            Bundle skuDetails = null;
            try {
                skuDetails = mService.getSkuDetails(3, packageName, "inapp", query);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
            return skuDetails;
        }
        @Override
        protected void onPostExecute(Bundle skuDetails) {
            List<AvailablePurchase> canPurchase = new ArrayList<AvailablePurchase>();
            int response = skuDetails.getInt("RESPONSE_CODE");
            if (response == 0) {
                ArrayList<String> responseList = skuDetails.getStringArrayList("DETAILS_LIST");
                if(responseList != null){
                    for (String thisResponse : responseList) {
                        JSONObject object = null;
                        try {
                            object = new JSONObject(thisResponse);
                            String sku = object.getString("productId");
                            String price = object.getString("price");
                            canPurchase.add(new AvailablePurchase(sku, price));
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
            if(checkIfPurchaseIsAvailable(canPurchase, productIds[0])){
                buyOneButton.setVisibility(View.VISIBLE);
            }else{
                buyOneButton.setVisibility(View.GONE);
            }
            if(checkIfPurchaseIsAvailable(canPurchase, productIds[1])){
                buyTwoButton.setVisibility(View.VISIBLE);
            }else{
                buyTwoButton.setVisibility(View.GONE);
            }
            if(checkIfPurchaseIsAvailable(canPurchase, productIds[2])){
                buyThreeButton.setVisibility(View.VISIBLE);
            }else{
                buyThreeButton.setVisibility(View.GONE);
            }
        }
    }
    @org.jetbrains.annotations.Contract("null, _ -> false")
    private boolean checkIfPurchaseIsAvailable(List<AvailablePurchase> all, String productId){
        if(all == null){ return false;}
        for(int i = 0; i < all.size(); i++){
            if(all.get(i).getSku().equals(productId)){
                return true;
            }
        }
        return false;
    }
    public boolean isBillingSupported(){
        int response = 1;
        try {
            response = mService.isBillingSupported(3, getPackageName(), "inapp");
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        if(response > 0){
            return false;
        }
        return true;
    }
    public void consumePurchaseItem(String purchaseToken){
        try {
            int response = mService.consumePurchase(3, getPackageName(), purchaseToken);
            if(response != 0){
                return;
            }
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
    public Bundle getAllUserPurchase(){
        Bundle ownedItems = null;
        try {
            ownedItems = mService.getPurchases(3, getPackageName(), "inapp", null);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        return ownedItems;
    }
    public List<UserPurchaseItems> extractAllUserPurchase(Bundle ownedItems){
        List<UserPurchaseItems> mUserItems = new ArrayList<UserPurchaseItems>();
        int response = ownedItems.getInt("RESPONSE_CODE");
        if (response == 0) {
            ArrayList<String> ownedSkus = ownedItems.getStringArrayList("INAPP_PURCHASE_ITEM_LIST");
            ArrayList<String>  purchaseDataList = ownedItems.getStringArrayList("INAPP_PURCHASE_DATA_LIST");
            ArrayList<String>  signatureList = ownedItems.getStringArrayList("INAPP_DATA_SIGNATURE_LIST");
            String continuationToken = ownedItems.getString("INAPP_CONTINUATION_TOKEN");
            if(purchaseDataList != null){
                for (int i = 0; i < purchaseDataList.size(); ++i) {
                    String purchaseData = purchaseDataList.get(i);
                    assert signatureList != null;
                    String signature = signatureList.get(i);
                    assert ownedSkus != null;
                    String sku = ownedSkus.get(i);
                    UserPurchaseItems allItems = new UserPurchaseItems(sku, purchaseData, signature);
                    mUserItems.add(allItems);
                }
            }
        }
        return mUserItems;
    }
    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mService != null) {
            unbindService(mServiceConn);
        }
    }
}

Создать Каталог Вспомогательных Пакетов

создайте новую папку пакета и назовите ее помощниками. Внутри пакета создайте новый файл java Помощник.Ява.

помощником.java

public class Helper {
    public static final String ITEM_ID_LIST = "ITEM_ID_LIST";
    public static final String ITEM_ONE_ID = "productone";
    public static final String ITEM_TWO_ID = "producttwo";
    public static final String ITEM_THREE_ID = "productthree";
    public static final int RESPONSE_CODE = 1001;
    public static final String SHARED_PREF = "shared_pref";
    public static final String DEVELOPER_PAYLOAD = "developer_payload";
    public static final String PURCHASE_TOKEN = "purchase_token";
    public static void displayMessage(Context context, String message){
        Toast.makeText(context.getApplicationContext(), message, Toast.LENGTH_LONG).show();
    }
}

Тестирование Покупки Биллинга В Приложении

  1. создайте учетную запись Google+ (не используйте учетную запись main)
  2. добавьте пользователей, которые будут тестировать приложение в вашей группе или сообществе.

ошибки, которые могут возникнуть во время тестирования покупки в приложении

элемент, который вы запросили, недоступен для покупки

решение согласно AndreiBogdan в Сайте StackOverflow,

все Inducesmile за его учебник

Android Developer Blog также рекомендует учебный класс по продаже продуктов в приложении. Чтобы увидеть полную реализацию и узнать, как протестировать приложение, пожалуйста, проверьте этот учебник: продажа продуктов в приложении


ладно, это одна из тех вещей, которые не очень много документации, доступной в интернете, поэтому я собираюсь сделать все возможное, чтобы объяснить все шаг за шагом. Взято из моего сообщения в блоге, которое является более подробной версией этого (со скриншотами), здесь на Миллибите. Без лишних слов,

Шаг Первый: разрешения Это самый простой шаг. Перейдите к манифесту.XML-файл и добавьте следующую строку в ваш тег:

<uses-permission android:name="com.android.vending.BILLING" />

это даст вашему приложению разрешения на доступ к биллингу в приложении. Если вы нацеливаете версии выше API 22, Вам нужно будет убедиться, что это разрешение предоставлено во время выполнения.

Шаг Второй: Консоли Играть Теперь вам нужно загрузить приложение на консоль Google Play. Мы еще не публикуем наше приложение для общественности (не волнуйтесь), мы просто загружаем его в раздел бета-версии, который позволит нам тестировать покупки в приложении. Причина, по которой нам нужно это сделать, заключается в том, что Google должна иметь некоторую версию вашего APK, загруженную для процессов выставления счетов.

  1. перейти к https://play.google.com/apps/publish/

  2. создать приложение

  3. следуйте инструкциям, чтобы настроить приложение

  4. перейти к выпускам приложений

  5. перейдите к Бета

  6. создайте APK своего приложения в Android studio и загрузите его в бета-версию в игровой консоли

(перед выпуском убедитесь ,что вы уже заполнили список магазина, рейтинг контента и цены и распределение)

  1. нажмите волшебную кнопку (Опубликовать!)

Шаг Третий: Проект Установки Хорошо это часть, где вы должны скопировать и вставить куча файлов.

во-первых, захватите этой файл, загрузите его и поместите под src/mainон должен встроиться в папку Далее, хватай все это папку util и вставить его в src/java folder. затем перестроить проект для устранения ошибок. Папка Util Содержит Следующие Классы:

  • IabBroadcastReceiver
  • IabException
  • IabHelper
  • IabResult
  • инвентаризации
  • купить
  • безопасность
  • SkuDetails

Шаг Четвертый: Создать Продукты

  1. Создать Управляемый Продукт

  2. нажмите Сохранить и сделать "шаблон ценообразования"

здесь, вы выберете цену этого продукта. Вы можете выбрать цену для разных стран или настроить ее автоматически, если вы просто выберете все страны по вашей цене:

  1. убедитесь, что продукт в приложении активирован и связан с правильным приложением в консоли в последний раз.

наконец, обратите внимание на ID вашего продукта. Мы будем использовать этот ID в следующих нескольких шагах.

  1. получите ваш Base64EncodedString

перейдите к "Services & APIs" и возьмите Base64EncodedString. Скопируйте и вставьте это в блокнот где-нибудь, чтобы у вас был доступ к нему. Не делитесь этим ни с кем, они смогут делать с ним злые вещи.

Шаг Пятый: наконец-то! Мы можем начать кодирование: Сначала мы свяжемся с библиотекой биллинга в приложении и запросим, что пользователь купил/не купил. Затем мы купим продукт, который мы создали ранее.

во-первых, импортировать все, что мы создали ранее:

import util.*;

теперь мы будем использовать объект IabHelper под названием mHelper, и мы будем делать все с этот.

base64EncodedPublicKey = ""; //PUT YOUR BASE64KEY HERE

mHelper = new IabHelper(this, base64EncodedPublicKey);
mHelper.enableDebugLogging(false); //set to false in real app


mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
    public void onIabSetupFinished(IabResult result) {
        if (!result.isSuccess()) {
            // Oh no, there was a problem.

            if (result.getResponse() == 3) {
                new AlertDialog.Builder(MainActivity.this)
                        .setTitle("In app billing")
                        .setMessage("This device is not compatible with In App Billing, so" +
                                " you may not be able to buy the premium version on your phone. ")
                        .setPositiveButton("Okay", null)
                        .show();
            }

            Log.v(TAG, "Problem setting up In-app Billing: " + result);
        } else {
            Log.v(TAG, "YAY, in app billing set up! " + result);
            try {
                mHelper.queryInventoryAsync(mGotInventoryListener); //Getting inventory of purchases and assigning listener
            } catch (IabHelper.IabAsyncInProgressException e) {
                e.printStackTrace();
            }
        }
    }
});