Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Reactive In-App Billing on Android

Edward Dale
November 27, 2015

Reactive In-App Billing on Android

Presented at DevFest Greece 2015

Edward Dale

November 27, 2015
Tweet

More Decks by Edward Dale

Other Decks in Technology

Transcript

  1. View Slide

  2. Reactive In-App Billing
    An In-App Billing API with RxJava
    Edward Dale
    Freeletics GmbH

    View Slide

  3. Motivation
    • Our app uses RxJava for async operations
    • Except In-app billing
    • Crashes in IAB code

    View Slide

  4. Agenda
    • In-App Billing
    • IabHelper
    • RxJava
    • Going Reactive

    View Slide

  5. In-App Billing
    • Google Play service that lets you sell digital
    content from inside your applications
    • Google Play handles all checkout details
    • Any application that you publish through
    Google Play can implement In-app Billing
    • Other stores (Amazon, etc) have similar APIs
    http://developer.android.com/google/play/billing/index.html

    View Slide

  6. In-App Billing
    Your
    App
    Google
    Play
    App
    Google
    Play
    Server
    IPC
    Binder
    Magic

    View Slide

  7. package com.android.vending.billing;
    interface IInAppBillingService {
    int isBillingSupported(int apiVersion,
    String packageName,
    String type);
    .
    .
    AIDL

    View Slide

  8. package com.android.vending.billing;
    interface IInAppBillingService {
    .
    .
    Bundle getSkuDetails(int apiVersion,
    String packageName,
    String type,
    in Bundle skusBundle);
    .
    .
    AIDL

    View Slide

  9. package com.android.vending.billing;
    interface IInAppBillingService {
    .
    .
    Bundle getBuyIntent(int apiVersion,
    String packageName,
    String sku,
    String type,
    String developerPayload);
    .
    AIDL

    View Slide

  10. package com.android.vending.billing;
    interface IInAppBillingService {
    .
    .
    Bundle getPurchases(int apiVersion,
    String packageName,
    String type,
    String continuationToken);
    .
    .
    AIDL

    View Slide

  11. package com.android.vending.billing;
    interface IInAppBillingService {
    .
    .
    int consumePurchase(int apiVersion,
    String packageName,
    String purchaseToken);
    }
    AIDL

    View Slide

  12. Interprocess Communication
    • Supports primitives, Parcelables, and some
    Collection classes
    • Parcelables must be available to both
    processes
    • Synchronous
    • Multithreading must be dealt with
    • Exceptions aren’t propogated
    http://developer.android.com/guide/components/aidl.html

    View Slide

  13. But who really wants
    to write IPC code?

    View Slide

  14. How some people do it
    Your
    App
    Google
    Play
    App
    Google
    Play
    Server
    IPC Magic
    IabHelper
    Java

    View Slide

  15. IabHelper
    • “Sample” code from Google
    • Not versioned or part of a library
    • ~1,000 lines of code
    • Big API
    • 20 public methods
    • 5 interfaces
    • Buggy

    View Slide

  16. public Inventory queryInventory(boolean querySkuDetails,
    List moreSkus) throws IabException
    public Inventory queryInventory(boolean querySkuDetails,
    List moreItemSkus, List moreSubsSkus)
    throws IabException
    public void queryInventoryAsync(boolean querySkuDetails,
    List moreSkus, 

    QueryInventoryFinishedListener listener)
    public void
    queryInventoryAsync(QueryInventoryFinishedListener
    listener)
    public void queryInventoryAsync(boolean querySkuDetails,

    QueryInventoryFinishedListener listener)
    Query

    View Slide

  17. public Inventory queryInventory(

    boolean querySkuDetails, 

    List moreItemSkus, 

    List moreSubsSkus

    ) throws IabException
    Query

    View Slide

  18. public void launchPurchaseFlow(Activity act, String sku,
    int requestCode, OnIabPurchaseFinishedListener listener)
    public void launchPurchaseFlow(Activity act, String sku,
    int requestCode, OnIabPurchaseFinishedListener listener,
    String extraData)
    public void launchSubscriptionPurchaseFlow(Activity act,
    String sku, int requestCode, 

    OnIabPurchaseFinishedListener listener)
    public void launchSubscriptionPurchaseFlow(Activity act,
    String sku, int requestCode, 

    OnIabPurchaseFinishedListener listener, String extraData)
    public void launchPurchaseFlow(Activity act, String sku,
    String itemType, int requestCode,
    OnIabPurchaseFinishedListener listener, String extraData)
    Purchase

    View Slide

  19. public void launchPurchaseFlow(
    Activity act, 

    String sku, 

    String itemType, 

    int requestCode,

    OnIabPurchaseFinishedListener listener,

    String extraData
    )
    Purchase

    View Slide

  20. void consume(Purchase itemInfo) throws IabException
    public void consumeAsync(Purchase purchase,
    OnConsumeFinishedListener listener)
    public void consumeAsync(List purchases,
    OnConsumeMultiFinishedListener listener)
    Consume

    View Slide

  21. public boolean handleActivityResult(int requestCode, 

    int resultCode, Intent data)
    public void enableDebugLogging(boolean enable, String tag)
    public void enableDebugLogging(boolean enable)
    public void startSetup(OnIabSetupFinishedListener listener)
    public void dispose()
    Misc

    View Slide

  22. The Ideal Billing API
    • query(…)
    • purchase(…)
    • consume(…)
    • Not too much else

    View Slide

  23. RxJava
    • A library for composing asynchronous and
    event-based programs by using observable
    sequences
    • Parameterized concurrency
    • Uniform, composable interface
    https://github.com/ReactiveX/RxJava

    View Slide

  24. “observable sequences”
    http://rxmarbles.com/#map

    View Slide

  25. “composable”
    http://rxmarbles.com/#filter

    View Slide

  26. “parameterized concurrency”
    http://reactivex.io/documentation/operators/observeon.html

    View Slide

  27. Let’s create a Billing
    API with Rx

    View Slide

  28. Going Reactive
    • Remember “The ideal Billing API”?
    • query(…)
    • purchase(…)
    • consume(…)
    • (Not much else)

    View Slide

  29. Observable queryInventory(

    boolean querySkuDetails, 

    List moreItemSkus, 

    List moreSubsSkus)
    Observable consume(List toConsume)
    Observable launchPurchaseFlow(

    Activity activity,

    SkuDetails sku,

    int requestCode,

    String extraData)
    Going Reactive

    View Slide

  30. Observable consume(List toConsume)
    • sync/async versions of the method
    • Listener to be notified of the result
    • Checked exceptions
    • Single/multiple product consumption
    What’s Missing?

    View Slide

  31. final Observable consumeObs = billingService.consume(purchases);
    consumeObs.subscribe(new Action1() {
    @Override
    public void call(Purchase purchase) {
    // Successful consume
    }
    }, new Action1() {
    @Override
    public void call(Throwable throwable) {
    // Show error message
    }
    });
    Using the API

    View Slide

  32. final Observable consumeObs
    = billingService.consume(purchases)
    .subscribeOn(io())
    .observeOn(mainThread());
    consumeObs.subscribe(new Action1() {
    @Override
    public void call(Purchase purchase) {
    // Successful consume
    }
    });
    Using the API

    View Slide

  33. final Observable> consumeObs
    = billingService.consume(purchases).toList()
    consumeObs.subscribe(new Action1>() {
    @Override
    public void call(List purchases) {
    // Successful consume
    }
    });
    Using the API

    View Slide

  34. billingService.queryInventory(true)
    .flatMap(inventory -> just(getPurchases())
    .flatMap(purchases -> billingService.consume(purchases))
    .subscribe()
    Using the API (Advanced)

    View Slide

  35. Additional Benefits
    Your
    App
    Google
    Play
    App
    Google
    Play
    Server
    IPC Magic
    Play
    Billing
    Service
    RxJava
    Amazon
    Billing
    Service
    Amazon
    Server
    Magic
    Billing
    Service
    Polymorphism

    View Slide

  36. Additional Benefits
    Your
    App
    Mock
    Billing
    Service
    RxJava
    Testability
    Billing
    Service

    View Slide

  37. Observable queryInventory(

    boolean querySkuDetails, 

    List moreItemSkus, 

    List moreSubsSkus)
    Observable consume(List toConsume)
    Observable launchPurchaseFlow(

    Activity activity,

    SkuDetails sku,

    int requestCode,

    String extraData)
    Reactive In-App Billing
    Coming soon

    as Open Source
    library

    View Slide

  38. Questions?
    Edward Dale

    [email protected]
    @scompt
    Now hiring Android,
    iOS, Ruby backend,
    DevOps in Germany

    View Slide

  39. View Slide