Slide 1

Slide 1 text

Monetizing Android apps on the Play Store Yash Prabhu @yashvprabhu | @dramafever Slides https://goo.gl/1p9k1r Image credit: Stock Android lollipop wallpaper

Slide 2

Slide 2 text

Why are we here? Image credit

Slide 3

Slide 3 text

7 Things we will learn today

Slide 4

Slide 4 text

Security Google Play Developer API Revenue Models Product Types Purchase Workflow In-app Billing v3 API Testing Image credit: Material icons

Slide 5

Slide 5 text

Revenue Models One

Slide 6

Slide 6 text

Digital & Physical Goods ● Freemium - 30% ○ In-app products ○ Subscription ● Paid ● AdMob ● Android Pay Digital Goods Physical Goods

Slide 7

Slide 7 text

Product Types Two

Slide 8

Slide 8 text

Non-Consumable ● Can be purchased only once ● Permanent benefit Managed: For One time purchases Consumable ● Can be purchased multiple times ● Temporary benefit Image credit: Material icons

Slide 9

Slide 9 text

Subscriptions - For automated, recurring billing ● Weekly, monthly, annual, seasonal ● Free trials - 7 to 30 days ● Manual renewal ● Upgrade/downgrade ● Deferred Billing

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

Purchase Workflow Three

Slide 12

Slide 12 text

Purchase response Response data GOOGLE PLAY DEVELOPER API YOUR SERVER Purchase request Purchase response GOOGLE PLAY APP ANDROID CLIENT APP Purchase response GOOGLE PLAY SERVER

Slide 13

Slide 13 text

In-app Billing v3 API Client side workflow Four

Slide 14

Slide 14 text

Image credit

Slide 15

Slide 15 text

In-app billing setup 1. Set up Merchant account 2. Integrate in-app billing v3 API 3. Define in-app products 4. Provision premium content 5. Profit!

Slide 16

Slide 16 text

Set up Merchant Account 1. Go to https://play.google.com/apps/publish/ 2. Open Financial reports on the side bar 3. Click Setup a Merchant Account now Step 1

Slide 17

Slide 17 text

Set up In-app billing v3 ● Go to sdk/extras/google/play_billing ● Copy into your project ○ IInAppBillingService.aidl ○ All Java files in trivialdrivesample/util ● Add billing permission into your manifest 1Step 2

Slide 18

Slide 18 text

Copy your license key into IabHelper.java Iab => In-app billing

Slide 19

Slide 19 text

Upload alpha apk. Hit Publish!

Slide 20

Slide 20 text

Set up a new product on Developer Console 1Step 3

Slide 21

Slide 21 text

Your in- app billing app Google Play App isBillingSupported() Supported/Not Supported getPurchases() Bundle(purchase info ....) getSkuDetails() Bundle(response code, sku info) getBuyIntent() Bundle(response code, buy intent) startIntentSenderForResult() Bundle(response code, purchase data, signature)

Slide 22

Slide 22 text

Is billing supported? public void onServiceConnected(ComponentName name, IBinder service) { mService = IInAppBillingService.Stub.asInterface(service); int response = mService.isBillingSupported(3, packageName, itemType); if (response == BILLING_RESPONSE_RESULT_OK) { // billing is supported } else { // billing is not supported } }

Slide 23

Slide 23 text

Query user’s owned products Bundle ownedItems = mService.getPurchases(3, packageName, itemType, continueToken); itemType => “inapp” || “subs” continueToken => retrieve next set of owned purchases

Slide 24

Slide 24 text

Query in-app product details Bundle skuDetails = mService.getSkuDetails(3, packageName, itemType, querySkus); itemType => “inapp” || “subs” querySkus => Bundle of all owned skus

Slide 25

Slide 25 text

When user wants to purchase public void launchPurchaseFlow(Activity act, String sku, String itemType, int requestCode, OnIabPurchaseFinishedListener listener, String extraData) { .... Bundle buyIntentBundle = mService.getBuyIntent(3, packageName, sku, itemType, extraData); .... }

Slide 26

Slide 26 text

App launches the pending intent PendingIntent pendingIntent = buyIntentBundle.getParcelable(RESPONSE_BUY_INTENT); activity.startIntentSenderForResult( pendingIntent.getIntentSender(), requestCode, new Intent(), flagsMask, flagsValues, extraFlags);

Slide 27

Slide 27 text

Get purchase information public boolean handleActivityResult(int requestCode, int resultCode, Intent data) { int responseCode = getResponseCodeFromIntent(data); String purchaseData = data.getStringExtra(RESPONSE_INAPP_PURCHASE_DATA); String dataSignature = data.getStringExtra(RESPONSE_INAPP_SIGNATURE); return true; }

Slide 28

Slide 28 text

Google Play App Your in- app billing app getPurchases() Bundle(purchase info ....) consumePurchase() Success/Failure

Slide 29

Slide 29 text

Consume a purchase void consume(Purchase itemInfo) throws IabException { String token = itemInfo.getToken(); String sku = itemInfo.getSku(); int response = mService.consumePurchase(3, packageName, token); if (response == BILLING_RESPONSE_RESULT_OK) { // sku consumed successfully } }

Slide 30

Slide 30 text

Quick Recap ● isBillingSupported? ● getPurchases() ● getSkuDetails() ● getBuyIntent() ● handleActivityResult() ● if consumable purchase is successful, consume() On startup On purchase After purchase

Slide 31

Slide 31 text

Purchase data { "orderId": "1299911111111111.145333335334137..0", "packageName": "com.sample.app", "productId": "test_inapp_upgrade", "purchaseTime": 1384834368656, "purchaseState": 0, "developerPayload": "abcdef", "purchaseToken": "fdgdghdjdp86dg", "autoRenewing":true }

Slide 32

Slide 32 text

Signature & Response code Signature: jHCzy6MGITNtOuF0nfYyiEyGw== Response codes 0 - Purchased 1 - Canceled 2 - Refunded

Slide 33

Slide 33 text

Testing Client side workflow Five

Slide 34

Slide 34 text

Testing ● Add licensed test users to Google Play developer console ● Reserved product ids ● No charges ● ● Regular users who can download your app from the Play Store ● Real product ids ● Actual charges Similar: Publish on Alpha, Beta or Production channels Test Purchases Regular Purchases

Slide 35

Slide 35 text

No content

Slide 36

Slide 36 text

Reserved product IDs ● android.test.purchased ● android.test.canceled ● android.test.refunded ● android.test.item_unavailable

Slide 37

Slide 37 text

Testing with reserved product IDs ● Install signed apk on a test device. No emulators! ● Sign into device with your developer account ● Google Play version 2.3.4+ or MyApps app 5.0.12+ ● Android 2.2+ ● Run your app and purchase reserved product ID

Slide 38

Slide 38 text

No content

Slide 39

Slide 39 text

Testing with actual product IDs ● No draft apks: Upload signed apk to alpha/beta channel ● Add a real managed product to Developer Console ● Install signed apk on a test device. No emulators! ● Google Play version 2.3.4+ or MyApps app 5.0.12+ ● Android 2.2+ ● Purchase the real product with a real credit card ● Factory reset device for same product purchase!

Slide 40

Slide 40 text

Testing subscriptions before Feb 2015 ● There was no sandbox! ● Create a test $0.99 monthly subscription product ● Purchase product with real credit card ● Refund & cancel order on the Google Wallet console ● Wait till end of subscription period to retest or factory reset device! https://www.emojibase.com/emoji/1f622/cryingface

Slide 41

Slide 41 text

Testing subscriptions after Feb 2015 ● Use android.test.purchased reserved product ● Buy the product ● Wait for 1 day to retest subscription Image credit

Slide 42

Slide 42 text

Valid subscription product purchase!

Slide 43

Slide 43 text

Common errors

Slide 44

Slide 44 text

No content

Slide 45

Slide 45 text

Security Client side workflow Six

Slide 46

Slide 46 text

Security ● Obfuscate code using Proguard -keep class com.android.vending.billing.** ● Protect unlocked/premium content ● Protect your Google Play Public Key ● Modify sample application code ● Use developer payload to uniquely identify user ● Signature verification on your client and server

Slide 47

Slide 47 text

Decode base64 Public Key & verify signature public static boolean verifyPurchase(String base64PublicKey, String purchaseData, String signature) { boolean verified = false; if (!TextUtils.isEmpty(signature)) { PublicKey key = Security.generatePublicKey(base64PublicKey); verified = Security.verify(key, purchaseData, signature); } return true; }

Slide 48

Slide 48 text

Google Play Developer API Server side workflow Seven

Slide 49

Slide 49 text

Purchase response Response data GOOGLE PLAY DEVELOPER API YOUR SERVER Purchase request Purchase response GOOGLE PLAY APP ANDROID CLIENT APP Purchase response GOOGLE PLAY SERVER

Slide 50

Slide 50 text

Why use Google Play Developer API? ● 200,000 queries per day for free! ● Publishing API ● Subscriptions & In-app purchases API

Slide 51

Slide 51 text

Setting up Google Play Developer API 1. Set up an APIs Console Project https://console.developers.google.com/ 2. Create an OAuth 2.0 Client ID 3. Generate a refresh token & access tokens 4. Access the API

Slide 52

Slide 52 text

Purchases.products.get request Checks the purchase and consumption status of an inapp item. GET https://www.googleapis.com/androidpublisher/v2/app lications/packageName/purchases/products/productI d/tokens/token

Slide 53

Slide 53 text

Purchases.products.get response { "kind": "androidpublisher#productPurchase", "purchaseTimeMillis": long, "purchaseState": integer, "consumptionState": integer, "developerPayload": string }

Slide 54

Slide 54 text

Purchases.subscriptions.get request Checks validity & expiration of a user's subscription purchase GET https://www.googleapis.com/androidpublisher/v2/app lications/packageName/purchases/subscriptions/subs criptionId/tokens/token

Slide 55

Slide 55 text

Purchases.subscriptions.get response { "kind": "androidpublisher#subscriptionPurchase", "startTimeMillis": long, "expiryTimeMillis": long, "autoRenewing": boolean }

Slide 56

Slide 56 text

Google API Client libraries ● Easier to set up authentication and authorization ● Reduces OAuth 2.0 code ● Featured: Java, Python, .NET, PHP, Javascript ● Early-stage: Go, Dart, Ruby, Node-js, Objective-C ● https://developers.google.com/api-client-library/

Slide 57

Slide 57 text

References ● Google Play In-app Billing ● Training: Using Google Play to Distribute and Monetize ● Video: In-app Billing Version 3 (Google I/O 2013) ● Using OAuth 2.0 to access Google Play APIs ● Google API client libraries

Slide 58

Slide 58 text

Q&A Yash Prabhu @yashvprabhu Slides https://goo.gl/1p9k1r Work at DramaFever http://goo.gl/gWUM5U