A simple implementation of the Android In-App Billing API.

Overview

Google In-App Billing Library v4+

A simple implementation of the Android In-App Billing API.

It supports: in-app purchases (both consumable and non-consumable) and subscriptions.

image preview video example

Getting Started

  • You project should build against Android 4.1.x (minSdkVersion 16).

  • Add the JitPack repository to your project's build.gradle file:

allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}
  • Add the dependency in your app's build.gradle file:
dependencies {
    implementation 'com.github.moisoni97:google-inapp-billing:1.0.2'
}
  • Open the AndroidManifest.xml of your application and add this permission:
  <uses-permission android:name="com.android.vending.BILLING" />

Important Notice

  • For builds that use minSdkVersion lower than 24 it is very important to include the following in your app's build.gradle file:
android {
  compileOptions {
    coreLibraryDesugaringEnabled true
    
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }
}

dependencies {
  coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
}
  • For builds that use minSdkVersion lower than 21 add the above and also this:
android {
    defaultConfig {
        multiDexEnabled true
    }
}

This step is required to enable support for some APIs on lower SDK versions that aren't available natively only starting from minSdkVersion 24.

Usage

  • Create an instance of BillingConnector class. Constructor will take 2 parameters:
    • Context
    • License key from Play Console
billingConnector = new BillingConnector(this, "license_key")
                .setConsumableIds(consumableIds)
                .setNonConsumableIds(nonConsumableIds)
                .setSubscriptionIds(subscriptionIds)
                .autoAcknowledge()
                .autoConsume()
                .enableLogging()
                .connect();
  • Implement the listener to handle event results and errors:
billingConnector.setBillingEventListener(new BillingEventListener() {
            @Override
            public void onProductsFetched(@NonNull List<SkuInfo> skuDetails) {
                /*Provides a list with fetched products*/
            }

            @Override
            public void onPurchasedProductsFetched(@NonNull List<PurchaseInfo> purchases) {
                /*Provides a list with fetched purchased products*/
            }

            @Override
            public void onProductsPurchased(@NonNull List<PurchaseInfo> purchases) {
                /*Callback after a product is purchased*/
            }

            @Override
            public void onPurchaseAcknowledged(@NonNull PurchaseInfo purchase) {
                /*Callback after a purchase is acknowledged*/
                
                /*
                 * Grant user entitlement for NON-CONSUMABLE products and SUBSCRIPTIONS here
                 *
                 * Even though onProductsPurchased is triggered when a purchase is successfully made
                 * there might be a problem along the way with the payment and the purchase won't be acknowledged
                 *
                 * Google will refund users purchases that aren't acknowledged in 3 days
                 *
                 * To ensure that all valid purchases are acknowledged the library will automatically
                 * check and acknowledge all unacknowledged products at the startup
                 * */
            }

            @Override
            public void onPurchaseConsumed(@NonNull PurchaseInfo purchase) {
                /*Callback after a purchase is consumed*/
                
                /*
                 * CONSUMABLE products entitlement can be granted either here or in onProductsPurchased
                 * */
            }

            @Override
            public void onBillingError(@NonNull BillingConnector billingConnector, @NonNull BillingResponse response) {
                /*Callback after an error occurs*/
                
                switch (response.getErrorType()) {
                    case CLIENT_NOT_READY:
                        //TODO - client is not ready
                        break;
                    case CLIENT_DISCONNECTED:
                        //TODO - client has disconnected
                        break;
                    case ITEM_NOT_EXIST:
                        //TODO - item doesn't exist
                        break;
                    case ITEM_ALREADY_OWNED:
                        //TODO - item is already owned
                        break;
                    case ACKNOWLEDGE_ERROR:
                        //TODO - error during acknowledgment
                        break;
                    case ACKNOWLEDGE_WARNING:
                        /*
                         * This will be triggered when a purchase can not be acknowledged because the state is PENDING
                         * A purchase can be acknowledged only when the state is PURCHASED
                         *
                         * PENDING transactions usually occur when users choose cash as their form of payment
                         *
                         * Here users can be informed that it may take a while until the purchase complete
                         * and to come back later to receive their purchase
                         * */
                         
                        //TODO - warning during acknowledgment
                        break;
                    case CONSUME_ERROR:
                        //TODO - error during consumption
                        break;
                    case FETCH_PURCHASED_PRODUCTS_ERROR:
                        //TODO - error occurred while querying purchases
                        break;
                    case BILLING_ERROR:
                        //TODO - error occurred during initialization / querying sku details
                        break;
                }
            }
        });

Initiate a purchase

  • Purchase a non-consumable / consumable product:
billingConnector.purchase(this, "sku_id");
  • Purchase a subscription:
billingConnector.subscribe(this, "sku_id");
  • Cancel a subscription:
billingConnector.unsubscribe(this, "sku_id");

Sample App

Go through the sample app to see a more advanced integration of the library.

It also shows how to implement some useful public methods.

Comments
  • Cannot Initiate Purchase or Subscription

    Cannot Initiate Purchase or Subscription

    I came across your library the other day because I need to update my billing library and yours seemed to be straight forward. I'm able to receive callbacks with product info ie. pricing and product ids, but when I initiate billingConnector.purchase or .subscribe neither go anywhere. Checked all cases as well, even copied your logic to a T & the only thing I can seem to get working is getting the info.

    Hope to get some help, thank you.

    invalid 
    opened by DNAMobileApplications 33
  • Please build release lastest code

    Please build release lastest code

    Thanks for your work

    I see your commit lastest a2e27e53c80edbd8fe18cd7d5899d6f435d876e8 but still does not release in jitpack

    Could you please build lastest jitpack ?

    onNoPurchasedProductsFetched listener is great listener, I want using this callback to trigger data

    Please build jitpack help me.

    enhancement 
    opened by huongtran 10
  • Upgraded to Google Billing v5.0

    Upgraded to Google Billing v5.0

    • The deprecated methods have been replaced with the ones that came with Billing v5.
    • With the offer options, the purchase is included.
    • Upgraded compileSdkVersion to API 33
    • Upgraded dependencies.
    opened by mert-karadeniz 9
  • Error in classes_proguard.jar

    Error in classes_proguard.jar

    I recently updated the lib to version 1.0.6 and I am getting an error building with proguard, the error is as follows: Compilation failed to complete, origin: /storage/emulated/0/.sketchware/mysc/601/bin/classes_proguard.jar

    In version 1.0.5, proguard worked normally.

    What could be happening?

    opened by franciscowilton 8
  • Correct purchase flow to handle Cash payments for consumables?

    Correct purchase flow to handle Cash payments for consumables?

    Thanks for creating this wrapper, it looks very useful. One question I have, is how can I use this library to correctly handle those new Cash payments that are now happening in Indonesia, Malaysia, etc? In those cases the user makes the purchase, then later goes to a convenience store to make the actual payment. Google recommends using the PurchaseToken to store information about a consumable on our own servers, which can then be granted later when the cash payment is made. It would be super helpful if you could add some sample code that correctly handles this type of situation. Thanks!

    enhancement 
    opened by rknoesel 7
  • Granting title to the product to the user before the purchase is confirmed.

    Granting title to the product to the user before the purchase is confirmed.

    First of all, I'm new to the subject of programming, I managed to implement in-app-purchase almost successfully, but I'm facing some problems:

    I have a problem that when I make a test purchase that will be denied after a few minutes, it already calls the OnProductPurchase event and gives the user the title of the product. How to solve? I would like to verify that the user has actually purchased by validating the purchase information before granting entitlement.

    https://user-images.githubusercontent.com/60080154/129499718-cf5149e3-a6d4-40d1-a15d-78c0f9729924.mp4

    Also would you like to implement queryPurchasesAsync() is the library compatible? I didn't find any information in the README

    Oh, one more thing, Lucky Patcher makes the purchase easily with just one click, does anyone have an efficient system against that?

    Thank you very much in advance.

    question 
    opened by franciscowilton 7
  • How to check subscription state in Android billing?

    How to check subscription state in Android billing?

    I have some app, which have subscription. User can buy subs, but how I can check is subs currently active.

    Android App :- https://play.google.com/store/apps/details?id=com.shiv.shambhu

    question 
    opened by Mahadev-code 7
  • This purchase is not restored.

    This purchase is not restored.

    I'm testing the library 1.06 with an app installed on a device where the user has a non-consumable purchase already made in the past. This purchase is not restored. Restored purchase 1 out of 50 attempts

    opened by horhomun 6
  • call onPurchasedProductsFetched if no have purchased products

    call onPurchasedProductsFetched if no have purchased products

    Hello. Thanks for your work! I ask you to call the onPurchasedProductsFetched event with an empty list if the user hasn't bought anything or the subscription has ended. This will greatly simplify the work, as well as reduce the amount of code, as it will make it possible to check the purchase correctly.

    @Override
    public void onPurchasedProductsFetched(@NonNull List<PurchaseInfo> purchases) {
        //   not called if there are no purchases
        boolean subscribedPremium = purchases.stream().anyMatch(a -> a.getSku().equals(InAppConstants.SKU_SUBSCRIBE_PREMIUM_ONE_YEAR));
    }
    

    The current implementation results in a double check.

    @Override
    public void onProductsFetched(@NonNull List<SkuInfo> skuDetails) {
        for(SkuInfo skuInfo : skuDetails) {
            if (skuInfo.getSku().equals(InAppConstants.SKU_SUBSCRIBE_PREMIUM_ONE_YEAR)) {
                // mBillingConnector.isPurchased(skuInfo) return PURCHASED_PRODUCTS_NOT_FETCHED_YET 
                // because purchases have not been synced yet
                // We cannot know for sure whether a purchase was made, 
                // so the subscribedPremium value will be false regardless of whether something was purchased or not.
                // If not, then everything is fine, but if yes, then we will disable the user's purchase 
                // and will wait for the onPurchasedProductsFetched event
                boolean subscribedPremium = mBillingConnector.isPurchased(skuInfo) == PurchasedResult.YES;
    
                // subscribedPremium == false
                // We cannot assign a value other than false, 
                // because we are not sure that the onPurchasedProductsFetched event will fire
            }
        }
    }
    @Override
    public void onPurchasedProductsFetched(@NonNull List<PurchaseInfo> purchases) {
        // Reassigning a value to the subscribedPremium variable
        boolean subscribedPremium = purchases.stream().anyMatch(a -> a.getSku().equals(InAppConstants.SKU_SUBSCRIBE_PREMIUM_ONE_YEAR));
    }
    

    Is it possible to do this?

    bug 
    opened by vitalii-vov 5
  • ImmutableList Error

    ImmutableList Error

    The error below keeps occurring I've searched online for a solution but nothing is working.

    java.lang.NoClassDefFoundError: Failed resolution of: Lcom/google/common/collect/ImmutableList; at games.moisoni.google_iab.BillingConnector.purchase(BillingConnector.java:653)

    opened by DNAMobileApplications 4
  • Billing V5.0 increases apk size by 8MB compared to V4

    Billing V5.0 increases apk size by 8MB compared to V4

    Hey thanks for the update to billing V5, it works perfectly!

    Just a small issue i noticed that when i use billing V5 compared to the previous V4 the size of the compiled apk is increased by approx 8mb

    is anyone else having the same effect? Thanks

    opened by newGenMobile 4
  • Billing API version is not supported for the type requested

    Billing API version is not supported for the type requested

    Hello, I recently tried using this library and am having some issues using it. I have one in-app purchase that I want to use your library with. The in-app is a remove ads non-consumable that would only ever be purchased once by the user (If bought in the past then I'd want the purchase to be verified and handled instead of purchased again).

    Whenever I try to make a purchase I see this:

    Screenshot_20221113-194441_Google Play Store

    I filtered Android Studio to show me only BillingConnector:

    ? D/BillingConnector: Billing service: connecting...
    ? D/BillingConnector: Billing service: connected
    ? D/BillingConnector: Query Product Details: data found
    ? D/BillingConnector: Subscriptions support check: success
    ? D/BillingConnector: Query SUBS Purchases: the list is empty
    ? D/BillingConnector: Query IN-APP Purchases: the list is empty
    ? D/BillingConnector: Billing API version is not supported for the type requested. Response code: 3 <-- after billingConnector.purchase
    

    I followed the instruction in the readme for setting everything up.

    implementation 'com.android.billingclient:billing:5.0.0'
    implementation 'com.github.moisoni97:google-inapp-billing:1.1.1'
    coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
    
    billingConnector = new BillingConnector(activity, LICENSE)
    					.setNonConsumableIds(Collections.singletonList(SKU))
    					.autoAcknowledge()
    					.autoConsume()
    					.enableLogging()
    					.connect();
    ...
    
    billingConnector.setBillingEventListener(new BillingEventListener() {
    			@Override public void onProductsFetched(@NonNull List<ProductInfo> productDetails) {
    				for (ProductInfo pinfo : productDetails)
    				{
    					Logd("Fetched product " + pinfo.getProductDetails().getProductId());
    
    					...
    				}
    			}
    			@Override public void onPurchasedProductsFetched(@NonNull ProductType productType, @NonNull List<PurchaseInfo> purchases) {
    				for (PurchaseInfo pinfo : purchases)
    				{
    					Logd("Fetched purchased product " + pinfo.getPurchase().toString());
    
    					...
    				}
    			}
    			@Override public void onPurchaseConsumed(@NonNull PurchaseInfo purchase) {}
    
    			@Override
    			public void onProductsPurchased(@NonNull List<PurchaseInfo> purchases) {
    				for (PurchaseInfo pinfo : purchases)
    				{
    					verifyPayload(pinfo.getPurchase(), new Runnable() {
    						@Override
    						public void run() {
    							Logd("Handling purchase payload");
    							
    							...
    						}
    					});
    				}
    			}
    
    			@Override
    			public void onPurchaseAcknowledged(@NonNull PurchaseInfo purchase) {
    				/*Callback after a purchase is acknowledged*/
    
    				verifyPayload(purchase.getPurchase(), new Runnable() {
    					@Override
    					public void run() {
    						Logd("Acknowledge purchase payload");
    	
    						...
    					}
    				});
    			}
    
    			@Override
    			public void onBillingError(@NonNull BillingConnector billingConnector, @NonNull BillingResponse response) {
    
    				Logd(response.toString());
    			}
    		});
    
    ...
    
    billingConnector.purchase(activity, SKU); // I have this elsewhere in my code
    

    I also tried updating to com.android.billingclient:billing:5.1.0 and that didn't change anything.

    Do you have any ideas why this issue is happening?

    Edit: My minSdkVersion is 23 if that helps

    opened by jbro129 2
  • onPurchasedProductsFetched is always called twice

    onPurchasedProductsFetched is always called twice

    onPurchasedProductsFetched is called twice on connect(). One time with purchases empty and once with purchases as expected (in case the user purchased). The worst thing is that there's a race condition so you can't even write a logic based on skipping the first time as sometimes this is the correct data, followed by the false data.

    It doesn't help to connect before setting the listener or after.

    opened by lioriluz 1
  • Subscriptions Not Loading

    Subscriptions Not Loading

    So I've successfully loaded all other items but when I activate & load a Subscription it doesn't load. When I try to subscribe it also says it doesn't exist. Do apps that have Subscriptions need to be on the PlayStore to work I've followed all the steps & nothing.

    opened by DNAMobileApplications 4
  • purchase cancelled because it was not acknowledged

    purchase cancelled because it was not acknowledged

    First time using this library, I try to implement it as it says in README. but when I purchase onProductsPurchased was called with empty purchases, this is the only callback I got back.

    I setup the billingConnector like this.

    billingConnector = BillingConnector(this, base64Key)
                .setConsumableIds(listOf(id1))
                .autoAcknowledge()
                .autoConsume()
                .enableLogging()
                .connect()
    

    what am I missing here?

    opened by whoisjeeva 1
Releases(1.1.1)
  • 1.1.1(Sep 12, 2022)

    Improvement

    • Fixed issue with the price showing the description instead of the actual price

    Breaking changes

    • Removed old getPrice()
    • Added getOneTimePurchaseOfferPrice and getSubscriptionOfferPrice(int selectedOfferIndex, int selectedPricingPhaseIndex)
    Source code(tar.gz)
    Source code(zip)
  • 1.1.0(Sep 8, 2022)

  • 1.0.9(Sep 6, 2022)

    Updated to Google Billing v5+

    • Migration thanks to @mert-karadeniz
    • Other small improvements/changes

    Breaking changes

    • Refactoring to match with the new Google Billing documentation ("sku" has been replaced with "product")
    • ErrorType.SKU_NOT_EXIST replaced with ErrorType.PRODUCT_NOT_EXIST
    • ProductType.NONE replaced with ProductType.COMBINED
    Source code(tar.gz)
    Source code(zip)
  • 1.0.8(Dec 10, 2021)

  • 1.0.7(Dec 9, 2021)

  • 1.0.6(Oct 27, 2021)

    Improvements

    • Added SkuType and isEmpty parameter for onPurchasedProductsFetched listener
    • Added new enum CONSUME_WARNING for ErrorType
    • Updated onPurchasedProductsFetched() listener to be called on an empty list

    Breaking changes

    • Enum SkuType as parameter for onPurchasedProductsFetched
    • Boolean parameter isEmpty for onPurchasedProductsFetched
    Source code(tar.gz)
    Source code(zip)
  • 1.0.5(Jul 28, 2021)

  • 1.0.4(Jul 20, 2021)

    Improvements

    • Added all response codes provided by Google Billing API
    • Added toString() method to BillingResponse
    • Improved error handling throughout the library

    Breaking change

    • Enum ITEM_NOT_EXIST changed to SKU_NOT_EXIST
    Source code(tar.gz)
    Source code(zip)
  • 1.0.3(Jul 13, 2021)

    Improvements

    • Added all wrappers around Google Billing API
    • Added Kotlin example

    Breaking change

    • Replaced getSkuId() with getSku() to match Google docs
    Source code(tar.gz)
    Source code(zip)
  • 1.0.2(Jul 8, 2021)

    New features and improvements

    • Added subscribe method to initiate a subscription
    • Added unsubscribe method to cancel a subscription
    • Now the library check for unacknowledged valid purchases at the startup to avoid Google refunds after 3 days
    • Added new ErrorType: ACKNOWLEDGE_WARNING
    • Downgraded minSdkVersion to 16 to support more devices
    • Better documentation
    Source code(tar.gz)
    Source code(zip)
  • 1.0.1(Jun 14, 2021)

  • 1.0.0(Jun 13, 2021)

Android Resource Manager application to manage and analysis your app resources with many features like image resize, Color, Dimens and code Analysis

AndroidResourceManager Cross-Platform tools to manage your resources as an Android Developer, AndroidResourceManager - ARM provide five main services

Amr Hesham 26 Nov 16, 2022
an android app to browse urls before open

link eye - kuesji koesnu - 8/8/2021 an android app to browse urls before open try to open a link, select link eye and choose always to start using

kuesji koesnu 25 Dec 31, 2022
Flash cards app using JavaFX, Scene Builder and persistence using Serialization with JAVA IO API

Flashcards - JavaFX , Scene Builder, Serialized Persistence JAVA IO API Main Scene that will show all the Decks in Flash Card App Add or Edit Cards in

Ali Raja 3 Nov 28, 2022
TMU is very simple app for posting your digital manga as article into Telegraph for further reading using any browser or in Telegram with Instant View.

TMU is very simple app for posting your digital manga as article into Telegraph for further reading using any browser or in Telegram with Instant View. App may be very helpful for content translators that searching easy way to share their work.

null 5 Oct 6, 2022
🌄 Image editor using native modules for iOS and Android. Inherit from 2 available libraries, Brightroom (iOS) and PhotoEditor (Android)

React Native Photo Editor (RNPE) ?? Image editor using native modules for iOS and Android. Inherit from 2 available libraries, Brightroom (iOS) and Ph

Baron Ha. 243 Jan 4, 2023
Simple, maintained and highly customizable colorpicker library for Android.

Colorpicker Library for Android Simple, maintained and highly customizable color picker library for Android. It is packed with ColorPicker Popup, Colo

Mrudul Tora 31 Oct 3, 2022
A simple Android Tag EditText

TagEditText A simple Android Tag EditText. Setup The easiest way to add the TagEditText library to your project is by adding it as a dependency to you

HearSilent 15 May 5, 2022
Tray Icon implementation for JavaFX applications. Say goodbye to using AWT's SystemTray icon, instead use a JavaFX Tray Icon.

FXTrayIcon Library intended for use in JavaFX applications that makes adding a System Tray icon easier. The FXTrayIcon class handles all the messy AWT

Dustin Redmond 248 Dec 30, 2022
Java implementation of BSP based CSG (Constructive Solid Geometry)

JCSG Java implementation of BSP based CSG (Constructive Solid Geometry). It is the only simple and free Java implementation I am aware of. This implem

Michael Hoffer 154 Sep 25, 2022
FlexBoxFX is a JavaFX implementation of CSS3 flexbox.

FlexBoxFX is a JavaFX implementation of CSS3 flexbox layout manager

null 5 Nov 4, 2021
A sub module of EdgeGallery MECM which responsible for the app package management.

mecm-apm Description Application package manager responsible for application package management including Onboarding, distributing package to edge etc

EdgeGallery 21 Jan 10, 2022
A sub module of EdgeGallery MECM which responsible for the app orchestration.

mecm-appo Description Application orchestrator is the core module responsible for orchestrating life cycle maintenance operation of application. Compi

EdgeGallery 25 Dec 25, 2021
HUAWEI 3D Modeling Kit project contains a sample app. Guided by this demo, you will be able to implement full 3D Modeling Kit capabilities, including 3D object reconstruction and material generation.

HUAWEI 3D Modeling Kit Sample English | 中文 Introduction This project includes apps developed based on HUAWEI 3D Modeling Kit. The project directory is

HMS 59 Jan 1, 2023
An Appointment app preview.

BOOKME APP This Application is an Example of Appointment System in which you can book your appointment at Hospitals,Hotels,Saloons,Cinemas,etc. This A

null 5 Nov 29, 2022
This app displays the perceived strength of a single earthquake event based on the DYFI indicator.

This app displays the perceived strength of a single earthquake event based on the DYFI indicator. Used in a Udacity course in the Android Basics Nanodegree.

Ezaz Ahammad 1 Jan 23, 2022
Pomodoro app made for myself in Java.

Pomodoro app This is a Pomodoro-type app made in Java using Swift UI. How to use Click on "Start timer" and input how many minutes you want to focus.

null 4 Oct 19, 2022
Checkers game. Server and Client. Client's app handled in JavaFX. Play with radom player or against AI.

Checkers-JavaFX-and-Sockets Checkers game. Server and Client. Client's app handled in JavaFX. Play with radom player or against AI. If you want to pla

Jakub Bednarski 1 Mar 30, 2022
A prayer times (Adhan) app for Windows and GNU/Linux written in JavaFX.

Salawat Salawat - سالوات A prayer times and Adhan application for Windows, macOS and GNU/Linux written in Java Download » View Demo · Report Bug · Req

DarkBlackChocolate 8 Nov 17, 2022
CSS-style shadows for Android

Fifty Shades: CSS-style shadows for Android What? In CSS, shadows are specified by (dx, dy, blurRadius, colour) (I call it ShadowSpec). This library i

Mike 73 Dec 19, 2022