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

Overview

Google In-App Billing Library v4+ API JitCI JitPack

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.6'
}
  • 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_11
    targetCompatibility JavaVersion.VERSION_11
  }
}

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 SkuType skuType, @NonNull List<PurchaseInfo> purchases, boolean isEmpty) {
                /*Provides a list with fetched purchased products*/
                
                /*
                 * This will be called even when no purchased products are returned by the API
                 * */
                
                switch (skuType) {
                    case INAPP:
                        //TODO - non-consumable/consumable products
                        break;
                    case SUBS:
                        //TODO - subscription products
                        break;
                }
            }

            @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*/
                
                /*
                 * Grant user entitlement for CONSUMABLE products 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 user will be able consume the product
                 * without actually paying
                 * */
            }

            @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 yet
                        break;
                    case CLIENT_DISCONNECTED:
                        //TODO - client has disconnected
                        break;
                    case SKU_NOT_EXIST:
                        //TODO - sku does not exist
                        break;
                    case CONSUME_ERROR:
                        //TODO - error during consumption
                        break;
                    case CONSUME_WARNING:
                        /*
                         * This will be triggered when a consumable purchase has a PENDING state
                         * User entitlement must be granted 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 consumption
                        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 FETCH_PURCHASED_PRODUCTS_ERROR:
                        //TODO - error occurred while querying purchased products
                        break;
                    case BILLING_ERROR:
                        //TODO - error occurred during initialization / querying sku details
                        break;
                    case USER_CANCELED:
                        //TODO - user pressed back or canceled a dialog
                        break;
                    case SERVICE_UNAVAILABLE:
                        //TODO - network connection is down
                        break;
                    case BILLING_UNAVAILABLE:
                        //TODO - billing API version is not supported for the type requested
                        break;
                    case ITEM_UNAVAILABLE:
                        //TODO - requested product is not available for purchase
                        break;
                    case DEVELOPER_ERROR:
                        //TODO - invalid arguments provided to the API
                        break;
                    case ERROR:
                        //TODO - fatal error during the API action
                        break;
                    case ITEM_ALREADY_OWNED:
                        //TODO - failure to purchase since item is already owned
                        break;
                    case ITEM_NOT_OWNED:
                        //TODO - failure to consume since item is not owned
                        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");

Kotlin

Kotlin is interoperable with Java and vice versa. This library works without any issues in Kotlin projects.

The sample app provides an example for Kotlin users.

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)

Implementation of the application using the latest Android Tech Stack and the GitHub REST API.

GitHub Viewer Implementation of the application using the latest Android Tech Stack and the GitHub REST API. <!-- Github login. You can change the use

Vitaliy Zarubin 53 Jan 3, 2023
Simple Mvp Implementation

Froggy Simple Mvp Implementation Download Gragle: compile 'ru.bullyboo.mvp:froggy:1.0.2' Maven: <dependency> <groupId>ru.bullyboo.mvp</groupId>

Rostislav Sharafutdinov 15 Mar 17, 2019
Android App to test API requests against the GitHub API.

Reproducing an issue with GitHub's IP allowlist feature GitHub provides a feature for Enterprise orgs to define an IP allowlist. Requests to the GitHu

Tom Hombergs 2 Aug 7, 2022
This is a Movie API app in which data is fetched online from the TMDB site using API authentication.

Movie-API This is a Movie API app in which data is fetched online from the TMDB site using API authentication. MVVM model is used for Database Managme

Atishay Jain 1 Dec 4, 2021
Gender Checker app built using Kotlin, MVVM, Genderize.io API. Take this as a reference for MVVM and Genderize.io API 🚀

Gender-Checker ?? Gender Checker app built using Kotlin, MVVM, Genderize.io API Enter a name and the app will guess the gender ?? ✨ Highligts: API : G

Jai Keerthick 0 Jan 5, 2022
OpenWeatherMap-API-Demo - Demo Android Application for OpenWeatherMap API

WeatherForecast Demo Android Application for OpenWeatherMap API Table of Content

Rashid Hussain 0 Jul 10, 2022
Android News App built in kotlin with implementation of MVVM architecture, android navigation components and retrofit. Displays news to users allowing them to share and save news.

News-App Android news app built in kotlin that fetches news data from news api with Retrofit and displays news to users. This App follow MVVM architec

Raj Manjrekar 16 Dec 29, 2022
Github-Api-Pagination-Example - Pagination 3 Example using Github Api

Github-Api-Pagination Pagination 3 Example using Github Api Tech Stack 100% Kotl

Anggoro Beno Lukito 2 Aug 22, 2022
CoroutinesFlow and ViewModel Retrofit API - Practice with CoroutinesFlow, ViewModel and Retrofit API

Practice with Coroutines Flow, ViewModel and get data with Retrofit from two API

Komiljon Zokirov 3 Feb 6, 2022
Wandroid project based on Kotlin + JetPack + concurrent implementation of MVVM architecture for playing Android App

Wandroid project based on Kotlin + JetPack + concurrent implementation of MVVM architecture for playing Android App

null 32 Feb 13, 2022
An simple image gallery app utilizing Unsplash API to showcase modern Android development architecture (MVVM + Kotlin + Retrofit2 + Hilt + Coroutines + Kotlin Flow + mockK + Espresso + Junit)

Imagine App An simple image gallery app utilizing Unsplash API. Built with ❤︎ by Wajahat Karim and contributors Features Popular photos with paginatio

Wajahat Karim 313 Jan 4, 2023
A simple android app written in Kotlin to get defination of word entered from Free Dictionary API.

FlashCard A simple android app written in Kotlin to get defination of word entered from Free Dictionary API. Problem Statement Many of students don't

RITEK ROUNAK 3 Jan 20, 2022
My CS 4th semester homework: simple Android app for looking up cocktails using an open API

CocktailApp My CS 4th semester homework: simple Android app for looking up cocktails using an open API A simple Android app that uses the free api of

null 2 May 18, 2022
A simple material design app intro with cool animations and a fluent API.

material-intro A simple material design app intro with cool animations and a fluent API. Very inspired by Google's app intros. Demo: A demo app is ava

Jan Heinrich Reimer 1.7k Jan 7, 2023
A Simple Movie App Built With Kotlin and Themoviedb API

Movie api https://www.themoviedb.org/documentation/api main fragment detail frag

Alex92w 1 Apr 26, 2022
inderjeet yadav 2 May 5, 2022
A simple Pokedex App getting API with Retrofit, maintaining data using LiveData, and Material Design based on MVVM architecture

PokedexApp Pokedex A simple Pokedex App getting API with Retrofit, maintaining data using LiveData, and Material Design based on MVVM architecture. Te

Steven Adriano 0 Apr 12, 2022
Simple-todo-app - Simple Memo App using SQLite

Judul Aplikasi Aplikasi Memo Sederhana menggunakan SQLite. Fitur Aplikasi Memo y

Ananda Muhamad Lukman 0 Jan 3, 2022
📒 NotyKT is a complete 💎Kotlin-stack (Backend + Android) 📱 application built to demonstrate the use of Modern development tools with best practices implementation🦸.

NotyKT ??️ NotyKT is the complete Kotlin-stack note taking ??️ application ?? built to demonstrate a use of Kotlin programming language in server-side

Shreyas Patil 1.4k Jan 8, 2023