├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── codelab-00
├── .gitignore
├── README.md
├── app
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── playbilling
│ │ │ └── trivialdrive
│ │ │ └── kotlin
│ │ │ ├── GameFragment.kt
│ │ │ ├── MainActivity.kt
│ │ │ └── MakePurchaseFragment.kt
│ │ └── res
│ │ ├── drawable-v24
│ │ ├── free_car.png
│ │ ├── gas.png
│ │ ├── gas_level_0.png
│ │ ├── gas_level_1.png
│ │ ├── gas_level_2.png
│ │ ├── gas_level_3.png
│ │ ├── gas_level_4.png
│ │ ├── gold_status.png
│ │ ├── gold_subs_icon.png
│ │ ├── ic_launcher_foreground.xml
│ │ ├── premium_car.png
│ │ └── title.png
│ │ ├── drawable
│ │ └── ic_launcher_background.xml
│ │ ├── layout
│ │ ├── activity_main.xml
│ │ ├── fragment_game.xml
│ │ └── fragment_make_purchase.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── navigation
│ │ └── navigation_graph.xml
│ │ └── values
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── keystore.properties
├── kotlin_td_keystore.jks
└── settings.gradle
├── codelab-01
├── .gitignore
├── README.md
├── app
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── playbilling
│ │ │ └── trivialdrive
│ │ │ └── kotlin
│ │ │ ├── GameFragment.kt
│ │ │ ├── MainActivity.kt
│ │ │ ├── MakePurchaseFragment.kt
│ │ │ └── billingrepo
│ │ │ ├── BillingRepository.kt
│ │ │ └── localdb
│ │ │ ├── AugmentedSkuDetails.kt
│ │ │ ├── AugmentedSkuDetailsDao.kt
│ │ │ ├── CachedPurchase.kt
│ │ │ ├── Entitlements.kt
│ │ │ ├── EntitlementsDao.kt
│ │ │ ├── LocalBillingDb.kt
│ │ │ └── PurchaseDao.kt
│ │ └── res
│ │ ├── drawable-v24
│ │ ├── free_car.png
│ │ ├── gas.png
│ │ ├── gas_level_0.png
│ │ ├── gas_level_1.png
│ │ ├── gas_level_2.png
│ │ ├── gas_level_3.png
│ │ ├── gas_level_4.png
│ │ ├── gold_status.png
│ │ ├── gold_subs_icon.png
│ │ ├── ic_launcher_foreground.xml
│ │ ├── premium_car.png
│ │ └── title.png
│ │ ├── drawable
│ │ └── ic_launcher_background.xml
│ │ ├── layout
│ │ ├── activity_main.xml
│ │ ├── fragment_game.xml
│ │ └── fragment_make_purchase.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── navigation
│ │ └── navigation_graph.xml
│ │ └── values
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── keystore.properties
├── kotlin_td_keystore.jks
└── settings.gradle
├── codelab-02
├── .gitignore
├── README.md
├── app
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── playbilling
│ │ │ └── trivialdrive
│ │ │ └── kotlin
│ │ │ ├── GameFragment.kt
│ │ │ ├── MainActivity.kt
│ │ │ ├── MakePurchaseFragment.kt
│ │ │ └── billingrepo
│ │ │ ├── BillingRepository.kt
│ │ │ ├── BillingWebservice.kt
│ │ │ ├── Security.kt
│ │ │ └── localdb
│ │ │ ├── AugmentedSkuDetails.kt
│ │ │ ├── AugmentedSkuDetailsDao.kt
│ │ │ ├── CachedPurchase.kt
│ │ │ ├── Entitlements.kt
│ │ │ ├── EntitlementsDao.kt
│ │ │ ├── LocalBillingDb.kt
│ │ │ └── PurchaseDao.kt
│ │ └── res
│ │ ├── drawable-v24
│ │ ├── free_car.png
│ │ ├── gas.png
│ │ ├── gas_level_0.png
│ │ ├── gas_level_1.png
│ │ ├── gas_level_2.png
│ │ ├── gas_level_3.png
│ │ ├── gas_level_4.png
│ │ ├── gold_status.png
│ │ ├── gold_subs_icon.png
│ │ ├── ic_launcher_foreground.xml
│ │ ├── premium_car.png
│ │ └── title.png
│ │ ├── drawable
│ │ └── ic_launcher_background.xml
│ │ ├── layout
│ │ ├── activity_main.xml
│ │ ├── fragment_game.xml
│ │ └── fragment_make_purchase.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── navigation
│ │ └── navigation_graph.xml
│ │ └── values
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── keystore.properties
├── kotlin_td_keystore.jks
└── settings.gradle
├── codelab-03
├── .gitignore
├── README.md
├── app
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── playbilling
│ │ │ └── trivialdrive
│ │ │ └── kotlin
│ │ │ ├── GameFragment.kt
│ │ │ ├── MainActivity.kt
│ │ │ ├── MakePurchaseFragment.kt
│ │ │ ├── billingrepo
│ │ │ ├── BillingRepository.kt
│ │ │ ├── BillingWebservice.kt
│ │ │ ├── Security.kt
│ │ │ └── localdb
│ │ │ │ ├── AugmentedSkuDetails.kt
│ │ │ │ ├── AugmentedSkuDetailsDao.kt
│ │ │ │ ├── CachedPurchase.kt
│ │ │ │ ├── Entitlements.kt
│ │ │ │ ├── EntitlementsDao.kt
│ │ │ │ ├── LocalBillingDb.kt
│ │ │ │ └── PurchaseDao.kt
│ │ │ └── viewmodels
│ │ │ └── BillingViewModel.kt
│ │ └── res
│ │ ├── drawable-v24
│ │ ├── free_car.png
│ │ ├── gas.png
│ │ ├── gas_level_0.png
│ │ ├── gas_level_1.png
│ │ ├── gas_level_2.png
│ │ ├── gas_level_3.png
│ │ ├── gas_level_4.png
│ │ ├── gold_status.png
│ │ ├── gold_subs_icon.png
│ │ ├── ic_launcher_foreground.xml
│ │ ├── premium_car.png
│ │ └── title.png
│ │ ├── drawable
│ │ └── ic_launcher_background.xml
│ │ ├── layout
│ │ ├── activity_main.xml
│ │ ├── fragment_game.xml
│ │ └── fragment_make_purchase.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── navigation
│ │ └── navigation_graph.xml
│ │ └── values
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── keystore.properties
├── kotlin_td_keystore.jks
└── settings.gradle
└── codelab-04
├── .gitignore
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── example
│ │ └── playbilling
│ │ └── trivialdrive
│ │ └── kotlin
│ │ ├── GameFragment.kt
│ │ ├── MainActivity.kt
│ │ ├── MakePurchaseFragment.kt
│ │ ├── adapters
│ │ └── InventoryAdapter.kt
│ │ ├── billingrepo
│ │ ├── BillingRepository.kt
│ │ ├── BillingWebservice.kt
│ │ ├── Security.kt
│ │ └── localdb
│ │ │ ├── AugmentedSkuDetails.kt
│ │ │ ├── AugmentedSkuDetailsDao.kt
│ │ │ ├── CachedPurchase.kt
│ │ │ ├── Entitlements.kt
│ │ │ ├── EntitlementsDao.kt
│ │ │ ├── LocalBillingDb.kt
│ │ │ └── PurchaseDao.kt
│ │ └── viewmodels
│ │ └── BillingViewModel.kt
│ └── res
│ ├── drawable-v24
│ ├── free_car.png
│ ├── gas.png
│ ├── gas_level_0.png
│ ├── gas_level_1.png
│ ├── gas_level_2.png
│ ├── gas_level_3.png
│ ├── gas_level_4.png
│ ├── gold_status.png
│ ├── gold_subs_icon.png
│ ├── ic_launcher_foreground.xml
│ ├── premium_car.png
│ └── title.png
│ ├── drawable
│ └── ic_launcher_background.xml
│ ├── layout
│ ├── activity_main.xml
│ ├── fragment_game.xml
│ ├── fragment_make_purchase.xml
│ └── inventory_item.xml
│ ├── mipmap-anydpi-v26
│ ├── ic_launcher.xml
│ └── ic_launcher_round.xml
│ ├── mipmap-hdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-mdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxxhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── navigation
│ └── navigation_graph.xml
│ └── values
│ ├── colors.xml
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── keystore.properties
├── kotlin_td_keystore.jks
└── settings.gradle
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # How to Contribute
2 |
3 | We'd love to accept your patches and contributions to this project. There are
4 | just a few small guidelines you need to follow.
5 |
6 | ## Contributor License Agreement
7 |
8 | Contributions to this project must be accompanied by a Contributor License
9 | Agreement. You (or your employer) retain the copyright to your contribution,
10 | this simply gives us permission to use and redistribute your contributions as
11 | part of the project. Head over to to see
12 | your current agreements on file or to sign a new one.
13 |
14 | You generally only need to submit a CLA once, so if you've already submitted one
15 | (even if it was for a different project), you probably don't need to do it
16 | again.
17 |
18 | ## Code reviews
19 |
20 | All submissions, including submissions by project members, require review. We
21 | use GitHub pull requests for this purpose. Consult
22 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
23 | information on using pull requests.
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Codelab: Scalable Implementation of Play Billing in Kotlin
2 |
3 | Sample application sources for Google Play Billing Codelab
4 |
5 | ## Introduction
6 |
7 | This sample is provided to demonstrate a scalable way of integrating with Google Play Billing.
8 | To read more please open the codelab page.
9 |
10 | ## Support
11 |
12 | If you've found an error in this sample, please file an issue:
13 | https://github.com/googlecodelabs/play-billing-scalable-kotlin/issues
14 |
15 | ## License
16 |
17 | Copyright 2019 Google, Inc.
18 |
19 | Licensed to the Apache Software Foundation (ASF) under one or more contributor
20 | license agreements. See the NOTICE file distributed with this work for
21 | additional information regarding copyright ownership. The ASF licenses this
22 | file to you under the Apache License, Version 2.0 (the "License"); you may not
23 | use this file except in compliance with the License. You may obtain a copy of
24 | the License at
25 |
26 | http://www.apache.org/licenses/LICENSE-2.0
27 |
28 | Unless required by applicable law or agreed to in writing, software
29 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
30 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
31 | License for the specific language governing permissions and limitations under
32 | the License.
33 |
34 | ## CHANGELOG
35 |
36 |
--------------------------------------------------------------------------------
/codelab-00/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea
5 | /.idea/caches/build_file_checksums.ser
6 | /.idea/libraries
7 | /.idea/modules.xml
8 | /.idea/workspace.xml
9 | .DS_Store
10 | /build
11 | /captures
12 | .externalNativeBuild
13 | /app/release
--------------------------------------------------------------------------------
/codelab-00/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/codelab-00/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/codelab-00/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
21 |
22 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/codelab-00/app/src/main/java/com/example/playbilling/trivialdrive/kotlin/MainActivity.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2018 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.example.playbilling.trivialdrive.kotlin
17 |
18 | import android.os.Bundle
19 | import androidx.appcompat.app.AppCompatActivity
20 | import com.kotlin.trivialdrive.R
21 |
22 | class MainActivity : AppCompatActivity() {
23 |
24 | override fun onCreate(savedInstanceState: Bundle?) {
25 | super.onCreate(savedInstanceState)
26 | setContentView(R.layout.activity_main)
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/codelab-00/app/src/main/java/com/example/playbilling/trivialdrive/kotlin/MakePurchaseFragment.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2018 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.example.playbilling.trivialdrive.kotlin
17 |
18 |
19 | import android.os.Bundle
20 | import android.util.Log
21 | import android.view.LayoutInflater
22 | import android.view.View
23 | import android.view.ViewGroup
24 | import androidx.fragment.app.Fragment
25 | import androidx.recyclerview.widget.RecyclerView
26 | import com.kotlin.trivialdrive.R
27 |
28 | /**
29 | * This Fragment is simply a wrapper for the inventory (i.e. items for sale). It contains two
30 | * [lists][RecyclerView], one for subscriptions and one for in-app products. Here again there is
31 | * no complicated billing logic. All the billing logic reside inside the [BillingRepository].
32 | * The [BillingRepository] provides a [AugmentedSkuDetails] object that shows what
33 | * is for sale and whether the user is allowed to buy the item at this moment. E.g. if the user
34 | * already has a full tank of gas, then they cannot buy gas at this moment.
35 | */
36 | class MakePurchaseFragment : Fragment() {
37 |
38 | val LOG_TAG = "MakePurchaseFragment"
39 |
40 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
41 | return inflater.inflate(R.layout.fragment_make_purchase, container, false)
42 | }
43 |
44 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
45 | super.onViewCreated(view, savedInstanceState)
46 | Log.d(LOG_TAG, "onViewCreated")
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/codelab-00/app/src/main/res/drawable-v24/free_car.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-00/app/src/main/res/drawable-v24/free_car.png
--------------------------------------------------------------------------------
/codelab-00/app/src/main/res/drawable-v24/gas.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-00/app/src/main/res/drawable-v24/gas.png
--------------------------------------------------------------------------------
/codelab-00/app/src/main/res/drawable-v24/gas_level_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-00/app/src/main/res/drawable-v24/gas_level_0.png
--------------------------------------------------------------------------------
/codelab-00/app/src/main/res/drawable-v24/gas_level_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-00/app/src/main/res/drawable-v24/gas_level_1.png
--------------------------------------------------------------------------------
/codelab-00/app/src/main/res/drawable-v24/gas_level_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-00/app/src/main/res/drawable-v24/gas_level_2.png
--------------------------------------------------------------------------------
/codelab-00/app/src/main/res/drawable-v24/gas_level_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-00/app/src/main/res/drawable-v24/gas_level_3.png
--------------------------------------------------------------------------------
/codelab-00/app/src/main/res/drawable-v24/gas_level_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-00/app/src/main/res/drawable-v24/gas_level_4.png
--------------------------------------------------------------------------------
/codelab-00/app/src/main/res/drawable-v24/gold_status.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-00/app/src/main/res/drawable-v24/gold_status.png
--------------------------------------------------------------------------------
/codelab-00/app/src/main/res/drawable-v24/gold_subs_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-00/app/src/main/res/drawable-v24/gold_subs_icon.png
--------------------------------------------------------------------------------
/codelab-00/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/codelab-00/app/src/main/res/drawable-v24/premium_car.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-00/app/src/main/res/drawable-v24/premium_car.png
--------------------------------------------------------------------------------
/codelab-00/app/src/main/res/drawable-v24/title.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-00/app/src/main/res/drawable-v24/title.png
--------------------------------------------------------------------------------
/codelab-00/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
26 |
27 |
36 |
37 |
--------------------------------------------------------------------------------
/codelab-00/app/src/main/res/layout/fragment_make_purchase.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
26 |
29 |
35 |
38 |
44 |
45 |
--------------------------------------------------------------------------------
/codelab-00/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/codelab-00/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/codelab-00/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-00/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/codelab-00/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-00/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/codelab-00/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-00/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/codelab-00/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-00/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/codelab-00/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-00/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/codelab-00/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-00/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/codelab-00/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-00/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/codelab-00/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-00/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/codelab-00/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-00/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/codelab-00/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-00/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/codelab-00/app/src/main/res/navigation/navigation_graph.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
24 |
25 |
30 |
33 |
34 |
38 |
41 |
42 |
--------------------------------------------------------------------------------
/codelab-00/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
20 | #008577
21 | #00574B
22 | #FFCA28
23 | #FFE082
24 | #FFECB3
25 | #CFD8DC
26 | #90A4AE
27 | #263238
28 |
29 |
--------------------------------------------------------------------------------
/codelab-00/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
20 | 16dp
21 | 8dp
22 | 32dp
23 | 8dp
24 | 8dp
25 |
--------------------------------------------------------------------------------
/codelab-00/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 | Trivial Drive Kotlin
19 | Hello blank fragment
20 | Fun Products
21 | Fun Subscriptions
22 | Vroooom, you drove a few miles!
23 | Oh, no! You are out of gas! Try buying some!
24 |
25 |
--------------------------------------------------------------------------------
/codelab-00/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 |
20 |
26 |
27 |
35 |
36 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/codelab-00/build.gradle:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2018 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
18 |
19 | buildscript {
20 | ext {
21 | APP_ID = "com.isaidamier.kotlin.trivialdrive"
22 |
23 | //keystorePropertiesFilename lives in gradle.properties
24 | keystorePropertiesFile = rootProject.file(keystorePropertiesFilename)
25 | keystoreProperties = new Properties()
26 | if (keystorePropertiesFile.exists()) {
27 | keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
28 | } else {
29 | println "Cannot find keystore properties file. " +
30 | "A) Create this file, B) use a different file, or C) use assembleDebug."
31 | println "A) Create $keystorePropertiesFilename"
32 | println "B) ./gradlew -PkeystorePropertiesFilename=release-keystore.properties assembleRelease"
33 | println "C) ./gradlew assembleDebug"
34 | println ""
35 | }
36 | keystoreFilename = keystoreProperties['storeFile']
37 | //signing config values
38 | releaseStoreFile = keystoreFilename == null ? null : rootProject.file(keystoreFilename)
39 | releaseStorePassword = keystoreProperties['storePassword']
40 | releaseKeyAlias = keystoreProperties['keyAlias']
41 | releaseKeyPassword = keystoreProperties['keyPassword']
42 |
43 | version_kotlin = '1.3.0'
44 | version_lifecycle = '2.0.0'
45 | version_coroutines = '1.0.1'
46 | version_room = "2.1.0-alpha03"
47 | version_nav = "1.0.0-alpha07"
48 | version_support = "1.0.0"
49 | version_espresso = "3.1.0-alpha4"
50 | version_runner = "1.1.0-alpha4"
51 | version_rules = "1.1.0-alpha4"
52 | version_arch_core = "2.0.0"
53 | }
54 |
55 | repositories {
56 | google()
57 | jcenter()
58 | }
59 | dependencies {
60 | classpath 'com.android.tools.build:gradle:3.2.1'
61 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$version_kotlin"
62 | }
63 | }
64 |
65 | allprojects {
66 | repositories {
67 | google()
68 | jcenter()
69 | }
70 | }
71 |
72 | task clean(type: Delete) {
73 | delete rootProject.buildDir
74 | }
75 |
--------------------------------------------------------------------------------
/codelab-00/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | android.enableJetifier=true
15 | android.useAndroidX=true
16 |
17 | # You can specify the keystore properties file from the command line.
18 | # Example release build using release keystore 'release-keystore.properties':
19 | # ./gradlew -PkeystorePropertiesFilename=release-keystore.properties assembleRelease
20 | #
21 | # Default source: keystore.properties
22 | #
23 | keystorePropertiesFilename=keystore.properties
24 |
25 |
--------------------------------------------------------------------------------
/codelab-00/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-00/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/codelab-00/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/codelab-00/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/codelab-00/keystore.properties:
--------------------------------------------------------------------------------
1 | storeFile=kotlin_td_keystore.jks
2 | storePassword=B!llingS@mpl3
3 | keyAlias=IAB
4 | keyPassword=B!llingS@mpl3
5 |
--------------------------------------------------------------------------------
/codelab-00/kotlin_td_keystore.jks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-00/kotlin_td_keystore.jks
--------------------------------------------------------------------------------
/codelab-00/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/codelab-01/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea
5 | /.idea/caches/build_file_checksums.ser
6 | /.idea/libraries
7 | /.idea/modules.xml
8 | /.idea/workspace.xml
9 | .DS_Store
10 | /build
11 | /captures
12 | .externalNativeBuild
13 | /app/release
--------------------------------------------------------------------------------
/codelab-01/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/codelab-01/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/codelab-01/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
21 |
22 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/codelab-01/app/src/main/java/com/example/playbilling/trivialdrive/kotlin/MainActivity.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2019 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.example.playbilling.trivialdrive.kotlin
17 |
18 | import android.os.Bundle
19 | import androidx.appcompat.app.AppCompatActivity
20 |
21 | class MainActivity : AppCompatActivity() {
22 |
23 | override fun onCreate(savedInstanceState: Bundle?) {
24 | super.onCreate(savedInstanceState)
25 | setContentView(R.layout.activity_main)
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/codelab-01/app/src/main/java/com/example/playbilling/trivialdrive/kotlin/MakePurchaseFragment.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2019 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.example.playbilling.trivialdrive.kotlin
17 |
18 |
19 | import android.os.Bundle
20 | import android.util.Log
21 | import android.view.LayoutInflater
22 | import android.view.View
23 | import android.view.ViewGroup
24 | import androidx.fragment.app.Fragment
25 | import androidx.recyclerview.widget.RecyclerView
26 |
27 | /**
28 | * This Fragment is simply a wrapper for the inventory (i.e. items for sale). It contains two
29 | * [lists][RecyclerView], one for subscriptions and one for in-app products. Here again there is
30 | * no complicated billing logic. All the billing logic reside inside the [BillingRepository].
31 | * The [BillingRepository] provides a [AugmentedSkuDetails] object that shows what
32 | * is for sale and whether the user is allowed to buy the item at this moment. E.g. if the user
33 | * already has a full tank of gas, then they cannot buy gas at this moment.
34 | */
35 | class MakePurchaseFragment : Fragment() {
36 |
37 | val LOG_TAG = "MakePurchaseFragment"
38 |
39 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
40 | return inflater.inflate(R.layout.fragment_make_purchase, container, false)
41 | }
42 |
43 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
44 | super.onViewCreated(view, savedInstanceState)
45 | Log.d(LOG_TAG, "onViewCreated")
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/codelab-01/app/src/main/java/com/example/playbilling/trivialdrive/kotlin/billingrepo/BillingRepository.kt:
--------------------------------------------------------------------------------
1 | package com.example.playbilling.trivialdrive.kotlin.billingrepo
2 |
3 | /**
4 | * Copyright (C) 2019 Google Inc. All Rights Reserved.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 | class BillingRepository {
19 |
20 | }
--------------------------------------------------------------------------------
/codelab-01/app/src/main/java/com/example/playbilling/trivialdrive/kotlin/billingrepo/localdb/AugmentedSkuDetails.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2018 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.example.playbilling.trivialdrive.kotlin.billingrepo.localdb
17 |
18 | import androidx.room.Entity
19 | import androidx.room.PrimaryKey
20 |
21 | @Entity
22 | data class AugmentedSkuDetails(val canPurchase: Boolean, /* Not in SkuDetails; it's the augmentation */
23 | @PrimaryKey val sku: String,
24 | val type: String?,
25 | val price: String?,
26 | val title: String?,
27 | val description: String?,
28 | val originalJson: String?)
--------------------------------------------------------------------------------
/codelab-01/app/src/main/java/com/example/playbilling/trivialdrive/kotlin/billingrepo/localdb/AugmentedSkuDetailsDao.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2018 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.example.playbilling.trivialdrive.kotlin.billingrepo.localdb
17 |
18 | import androidx.lifecycle.LiveData
19 | import androidx.room.Dao
20 | import androidx.room.Insert
21 | import androidx.room.OnConflictStrategy
22 | import androidx.room.Query
23 | import androidx.room.Transaction
24 | import com.android.billingclient.api.BillingClient
25 | import com.android.billingclient.api.SkuDetails
26 |
27 | @Dao
28 | interface AugmentedSkuDetailsDao {
29 |
30 | @Query("SELECT * FROM AugmentedSkuDetails WHERE type = '${BillingClient.SkuType.SUBS}'")
31 | fun getSubscriptionSkuDetails(): LiveData>
32 |
33 | @Query("SELECT * FROM AugmentedSkuDetails WHERE type = '${BillingClient.SkuType.INAPP}'")
34 | fun getInappSkuDetails(): LiveData>
35 |
36 | @Transaction
37 | fun insertOrUpdate(skuDetails: SkuDetails) = skuDetails.apply {
38 | val result = getById(sku)
39 | val canPurchase = if (result == null) true else result.canPurchase
40 | val originalJson = toString().substring("SkuDetails: ".length)
41 | val skuDetails = AugmentedSkuDetails(canPurchase, sku, type, price, title, description, originalJson)
42 | insert(skuDetails)
43 | }
44 |
45 | @Transaction
46 | fun insertOrUpdate(sku: String, canPurchase: Boolean) {
47 | val result = getById(sku)
48 | if (result != null) {
49 | update(sku, canPurchase)
50 | } else {
51 | insert(AugmentedSkuDetails(canPurchase, sku, null, null, null, null, null))
52 | }
53 | }
54 |
55 | @Query("SELECT * FROM AugmentedSkuDetails WHERE sku = :sku")
56 | fun getById(sku: String): AugmentedSkuDetails
57 |
58 | @Insert(onConflict = OnConflictStrategy.REPLACE)
59 | fun insert(augmentedSkuDetails: AugmentedSkuDetails)
60 |
61 | @Query("UPDATE AugmentedSkuDetails SET canPurchase = :canPurchase WHERE sku = :sku")
62 | fun update(sku: String, canPurchase: Boolean)
63 | }
--------------------------------------------------------------------------------
/codelab-01/app/src/main/java/com/example/playbilling/trivialdrive/kotlin/billingrepo/localdb/CachedPurchase.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2018 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.example.playbilling.trivialdrive.kotlin.billingrepo.localdb
17 |
18 | import androidx.room.Entity
19 | import androidx.room.Ignore
20 | import androidx.room.PrimaryKey
21 | import androidx.room.TypeConverter
22 | import androidx.room.TypeConverters
23 | import com.android.billingclient.api.Purchase
24 |
25 | @Entity(tableName = "purchase_table")
26 | @TypeConverters(PurchaseTypeConverter::class)
27 | class CachedPurchase(val data: Purchase) {
28 |
29 | @PrimaryKey(autoGenerate = true)
30 | var id: Int = 0
31 |
32 | @Ignore
33 | val purchaseToken = data.purchaseToken
34 | @Ignore
35 | val sku = data.sku
36 |
37 | override fun equals(other: Any?): Boolean {
38 | return when (other) {
39 | is CachedPurchase -> data.equals(other.data)
40 | is Purchase -> data.equals(other)
41 | else -> false
42 | }
43 | }
44 |
45 | override fun hashCode(): Int {
46 | return data.hashCode()
47 | }
48 |
49 | }
50 |
51 | class PurchaseTypeConverter {
52 | @TypeConverter
53 | fun toString(purchase: Purchase): String = purchase.originalJson + '|' + purchase.signature
54 |
55 | @TypeConverter
56 | fun toPurchase(data: String): Purchase = data.split('|').let {
57 | Purchase(it[0], it[1])
58 | }
59 | }
--------------------------------------------------------------------------------
/codelab-01/app/src/main/java/com/example/playbilling/trivialdrive/kotlin/billingrepo/localdb/Entitlements.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2018 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.playbilling.trivialdrive.kotlin.billingrepo.localdb
18 |
19 | import androidx.room.Entity
20 | import androidx.room.PrimaryKey
21 |
22 | private const val FULL_TANK = 4
23 | private const val EMPTY_TANK = 0
24 | const val GAS_PURCHASE = 1
25 |
26 | abstract class Entitlement {
27 | @PrimaryKey
28 | var id: Int = 1
29 |
30 | abstract fun mayPurchase(): Boolean
31 | }
32 |
33 | @Entity(tableName = "premium_car")
34 | data class PremiumCar(val entitled: Boolean) : Entitlement() {
35 | override fun mayPurchase(): Boolean = !entitled
36 | }
37 |
38 | @Entity(tableName = "gold_status")
39 | data class GoldStatus(val entitled: Boolean) : Entitlement() {
40 | override fun mayPurchase(): Boolean = !entitled
41 | }
42 |
43 | @Entity(tableName = "gas_tank")
44 | class GasTank(private var level: Int) : Entitlement() {
45 |
46 | fun getLevel() = level
47 |
48 | override fun mayPurchase(): Boolean = level < FULL_TANK
49 |
50 | fun needGas(): Boolean = level <= EMPTY_TANK
51 |
52 | fun decrement(by: Int = 1) {
53 | level -= by
54 | }
55 |
56 | }
--------------------------------------------------------------------------------
/codelab-01/app/src/main/java/com/example/playbilling/trivialdrive/kotlin/billingrepo/localdb/LocalBillingDb.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2018 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.example.playbilling.trivialdrive.kotlin.billingrepo.localdb
17 |
18 |
19 | import android.content.Context
20 | import androidx.room.Database
21 | import androidx.room.Room
22 | import androidx.room.RoomDatabase
23 |
24 | @Database(entities = [CachedPurchase::class, GasTank::class, PremiumCar::class, GoldStatus::class, AugmentedSkuDetails::class],
25 | version = 1, exportSchema = false)
26 | abstract class LocalBillingDb : RoomDatabase() {
27 | abstract fun purchaseDao(): PurchaseDao
28 | abstract fun entitlementsDao(): EntitlementsDao
29 | abstract fun skuDetailsDao(): AugmentedSkuDetailsDao
30 |
31 | companion object {
32 | @Volatile
33 | private var INSTANCE: LocalBillingDb? = null
34 |
35 | fun getInstance(context: Context): LocalBillingDb {
36 | return INSTANCE
37 | ?: synchronized(this) {
38 | var instance = INSTANCE
39 | if (instance == null) {
40 | instance = Room.databaseBuilder(
41 | context.applicationContext,
42 | LocalBillingDb::class.java,
43 | "purchase_db")
44 | .fallbackToDestructiveMigration()//remote sources more reliable
45 | .build()
46 | INSTANCE = instance
47 | }
48 | instance!!
49 | }
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/codelab-01/app/src/main/java/com/example/playbilling/trivialdrive/kotlin/billingrepo/localdb/PurchaseDao.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2018 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.example.playbilling.trivialdrive.kotlin.billingrepo.localdb
17 |
18 | import androidx.room.Dao
19 | import androidx.room.Delete
20 | import androidx.room.Insert
21 | import androidx.room.Query
22 | import androidx.room.Transaction
23 | import com.android.billingclient.api.Purchase
24 |
25 | @Dao
26 | interface PurchaseDao {
27 | @Query("SELECT * FROM purchase_table")
28 | fun getPurchases(): List
29 |
30 | @Insert
31 | fun insert(purchase: CachedPurchase)
32 |
33 | @Transaction
34 | fun insert(vararg purchases: Purchase) {
35 | purchases.forEach {
36 | insert(CachedPurchase(data = it))
37 | }
38 | }
39 |
40 | @Delete
41 | fun delete(vararg purchases: CachedPurchase)
42 |
43 | @Query("DELETE FROM purchase_table")
44 | fun deleteAll()
45 | }
--------------------------------------------------------------------------------
/codelab-01/app/src/main/res/drawable-v24/free_car.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-01/app/src/main/res/drawable-v24/free_car.png
--------------------------------------------------------------------------------
/codelab-01/app/src/main/res/drawable-v24/gas.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-01/app/src/main/res/drawable-v24/gas.png
--------------------------------------------------------------------------------
/codelab-01/app/src/main/res/drawable-v24/gas_level_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-01/app/src/main/res/drawable-v24/gas_level_0.png
--------------------------------------------------------------------------------
/codelab-01/app/src/main/res/drawable-v24/gas_level_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-01/app/src/main/res/drawable-v24/gas_level_1.png
--------------------------------------------------------------------------------
/codelab-01/app/src/main/res/drawable-v24/gas_level_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-01/app/src/main/res/drawable-v24/gas_level_2.png
--------------------------------------------------------------------------------
/codelab-01/app/src/main/res/drawable-v24/gas_level_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-01/app/src/main/res/drawable-v24/gas_level_3.png
--------------------------------------------------------------------------------
/codelab-01/app/src/main/res/drawable-v24/gas_level_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-01/app/src/main/res/drawable-v24/gas_level_4.png
--------------------------------------------------------------------------------
/codelab-01/app/src/main/res/drawable-v24/gold_status.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-01/app/src/main/res/drawable-v24/gold_status.png
--------------------------------------------------------------------------------
/codelab-01/app/src/main/res/drawable-v24/gold_subs_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-01/app/src/main/res/drawable-v24/gold_subs_icon.png
--------------------------------------------------------------------------------
/codelab-01/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/codelab-01/app/src/main/res/drawable-v24/premium_car.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-01/app/src/main/res/drawable-v24/premium_car.png
--------------------------------------------------------------------------------
/codelab-01/app/src/main/res/drawable-v24/title.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-01/app/src/main/res/drawable-v24/title.png
--------------------------------------------------------------------------------
/codelab-01/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
26 |
27 |
36 |
37 |
--------------------------------------------------------------------------------
/codelab-01/app/src/main/res/layout/fragment_make_purchase.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
26 |
29 |
35 |
38 |
44 |
45 |
--------------------------------------------------------------------------------
/codelab-01/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/codelab-01/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/codelab-01/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-01/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/codelab-01/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-01/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/codelab-01/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-01/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/codelab-01/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-01/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/codelab-01/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-01/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/codelab-01/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-01/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/codelab-01/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-01/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/codelab-01/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-01/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/codelab-01/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-01/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/codelab-01/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-01/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/codelab-01/app/src/main/res/navigation/navigation_graph.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
24 |
25 |
30 |
33 |
34 |
38 |
41 |
42 |
--------------------------------------------------------------------------------
/codelab-01/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
20 | #008577
21 | #00574B
22 | #FFCA28
23 | #FFE082
24 | #FFECB3
25 | #CFD8DC
26 | #90A4AE
27 | #263238
28 |
29 |
--------------------------------------------------------------------------------
/codelab-01/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
20 | 16dp
21 | 8dp
22 | 32dp
23 | 8dp
24 | 8dp
25 |
--------------------------------------------------------------------------------
/codelab-01/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 | Trivial Drive Kotlin
19 | Hello blank fragment
20 | Fun Products
21 | Fun Subscriptions
22 | Vroooom, you drove a few miles!
23 | Oh, no! You are out of gas! Try buying some!
24 |
25 |
--------------------------------------------------------------------------------
/codelab-01/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 |
20 |
26 |
27 |
35 |
36 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/codelab-01/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | android.enableJetifier=true
15 | android.useAndroidX=true
16 |
17 | # You can specify the keystore properties file from the command line.
18 | # Example release build using release keystore 'release-keystore.properties':
19 | # ./gradlew -PkeystorePropertiesFilename=release-keystore.properties assembleRelease
20 | #
21 | # Default source: keystore.properties
22 | #
23 | keystorePropertiesFilename=keystore.properties
24 |
25 |
--------------------------------------------------------------------------------
/codelab-01/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-01/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/codelab-01/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/codelab-01/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/codelab-01/keystore.properties:
--------------------------------------------------------------------------------
1 | storeFile=kotlin_td_keystore.jks
2 | storePassword=B!llingS@mpl3
3 | keyAlias=IAB
4 | keyPassword=B!llingS@mpl3
5 |
--------------------------------------------------------------------------------
/codelab-01/kotlin_td_keystore.jks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-01/kotlin_td_keystore.jks
--------------------------------------------------------------------------------
/codelab-01/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/codelab-02/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea
5 | /.idea/caches/build_file_checksums.ser
6 | /.idea/libraries
7 | /.idea/modules.xml
8 | /.idea/workspace.xml
9 | .DS_Store
10 | /build
11 | /captures
12 | .externalNativeBuild
13 | /app/release
--------------------------------------------------------------------------------
/codelab-02/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/codelab-02/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/codelab-02/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
21 |
22 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/codelab-02/app/src/main/java/com/example/playbilling/trivialdrive/kotlin/MainActivity.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2019 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.example.playbilling.trivialdrive.kotlin
17 |
18 | import android.os.Bundle
19 | import androidx.appcompat.app.AppCompatActivity
20 |
21 | class MainActivity : AppCompatActivity() {
22 |
23 | override fun onCreate(savedInstanceState: Bundle?) {
24 | super.onCreate(savedInstanceState)
25 | setContentView(R.layout.activity_main)
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/codelab-02/app/src/main/java/com/example/playbilling/trivialdrive/kotlin/MakePurchaseFragment.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2019 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.example.playbilling.trivialdrive.kotlin
17 |
18 |
19 | import android.os.Bundle
20 | import android.util.Log
21 | import android.view.LayoutInflater
22 | import android.view.View
23 | import android.view.ViewGroup
24 | import androidx.fragment.app.Fragment
25 | import androidx.recyclerview.widget.RecyclerView
26 |
27 | /**
28 | * This Fragment is simply a wrapper for the inventory (i.e. items for sale). It contains two
29 | * [lists][RecyclerView], one for subscriptions and one for in-app products. Here again there is
30 | * no complicated billing logic. All the billing logic reside inside the [BillingRepository].
31 | * The [BillingRepository] provides a [AugmentedSkuDetails] object that shows what
32 | * is for sale and whether the user is allowed to buy the item at this moment. E.g. if the user
33 | * already has a full tank of gas, then they cannot buy gas at this moment.
34 | */
35 | class MakePurchaseFragment : Fragment() {
36 |
37 | val LOG_TAG = "MakePurchaseFragment"
38 |
39 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
40 | return inflater.inflate(R.layout.fragment_make_purchase, container, false)
41 | }
42 |
43 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
44 | super.onViewCreated(view, savedInstanceState)
45 | Log.d(LOG_TAG, "onViewCreated")
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/codelab-02/app/src/main/java/com/example/playbilling/trivialdrive/kotlin/billingrepo/BillingWebservice.kt:
--------------------------------------------------------------------------------
1 | package com.example.playbilling.trivialdrive.kotlin.billingrepo
2 |
3 | import com.android.billingclient.api.Purchase
4 |
5 | /**
6 | * Copyright (C) 2019 Google Inc. All Rights Reserved.
7 | *
8 | * Licensed under the Apache License, Version 2.0 (the "License");
9 | * you may not use this file except in compliance with the License.
10 | * You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing, software
15 | * distributed under the License is distributed on an "AS IS" BASIS,
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | * See the License for the specific language governing permissions and
18 | * limitations under the License.
19 | */
20 |
21 | class BillingWebservice {
22 | fun getPurchases(): Any {
23 | return Any()//TODO("not implemented")
24 | }
25 | fun updateServer(purchases: Set) {
26 | //TODO("not implemented")
27 | }
28 | fun onComsumeResponse(purchaseToken: String?, responseCode: Int) {
29 | //TODO("not implemented")
30 | }
31 | companion object {
32 | fun create(): BillingWebservice {
33 | //TODO("not implemented")
34 | return BillingWebservice()
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/codelab-02/app/src/main/java/com/example/playbilling/trivialdrive/kotlin/billingrepo/localdb/AugmentedSkuDetails.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2018 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.example.playbilling.trivialdrive.kotlin.billingrepo.localdb
17 |
18 | import androidx.room.Entity
19 | import androidx.room.PrimaryKey
20 |
21 | @Entity
22 | data class AugmentedSkuDetails(val canPurchase: Boolean, /* Not in SkuDetails; it's the augmentation */
23 | @PrimaryKey val sku: String,
24 | val type: String?,
25 | val price: String?,
26 | val title: String?,
27 | val description: String?,
28 | val originalJson: String?)
--------------------------------------------------------------------------------
/codelab-02/app/src/main/java/com/example/playbilling/trivialdrive/kotlin/billingrepo/localdb/AugmentedSkuDetailsDao.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2018 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.example.playbilling.trivialdrive.kotlin.billingrepo.localdb
17 |
18 | import androidx.lifecycle.LiveData
19 | import androidx.room.*
20 | import com.android.billingclient.api.BillingClient
21 | import com.android.billingclient.api.SkuDetails
22 |
23 | @Dao
24 | interface AugmentedSkuDetailsDao {
25 |
26 | @Query("SELECT * FROM AugmentedSkuDetails WHERE type = '${BillingClient.SkuType.SUBS}'")
27 | fun getSubscriptionSkuDetails(): LiveData>
28 |
29 | @Query("SELECT * FROM AugmentedSkuDetails WHERE type = '${BillingClient.SkuType.INAPP}'")
30 | fun getInappSkuDetails(): LiveData>
31 |
32 | @Transaction
33 | fun insertOrUpdate(skuDetails: SkuDetails) = skuDetails.apply {
34 | val result = getById(sku)
35 | val bool = if (result == null) true else result.canPurchase
36 | val originalJson = toString().substring("SkuDetails: ".length)
37 | val skuDetails = AugmentedSkuDetails(bool, sku, type, price, title, description, originalJson)
38 | insert(skuDetails)
39 | }
40 |
41 | @Transaction
42 | fun insertOrUpdate(sku: String, canPurchase: Boolean) {
43 | val result = getById(sku)
44 | if (result != null) {
45 | update(sku, canPurchase)
46 | } else {
47 | insert(AugmentedSkuDetails(canPurchase, sku, null, null, null, null, null))
48 | }
49 | }
50 |
51 | @Query("SELECT * FROM AugmentedSkuDetails WHERE sku = :sku")
52 | fun getById(sku: String): AugmentedSkuDetails
53 |
54 | @Insert(onConflict = OnConflictStrategy.REPLACE)
55 | fun insert(augmentedSkuDetails: AugmentedSkuDetails)
56 |
57 | @Query("UPDATE AugmentedSkuDetails SET canPurchase = :canPurchase WHERE sku = :sku")
58 | fun update(sku: String, canPurchase: Boolean)
59 | }
--------------------------------------------------------------------------------
/codelab-02/app/src/main/java/com/example/playbilling/trivialdrive/kotlin/billingrepo/localdb/CachedPurchase.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2018 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.example.playbilling.trivialdrive.kotlin.billingrepo.localdb
17 |
18 | import androidx.room.*
19 | import com.android.billingclient.api.Purchase
20 |
21 | @Entity(tableName = "purchase_table")
22 | @TypeConverters(PurchaseTypeConverter::class)
23 | class CachedPurchase(val data: Purchase) {
24 |
25 | @PrimaryKey(autoGenerate = true)
26 | var id: Int = 0
27 |
28 | @Ignore
29 | val purchaseToken = data.purchaseToken
30 | @Ignore
31 | val sku = data.sku
32 |
33 | override fun equals(other: Any?): Boolean {
34 | return when (other) {
35 | is CachedPurchase -> data.equals(other.data)
36 | is Purchase -> data.equals(other)
37 | else -> false
38 | }
39 | }
40 |
41 | override fun hashCode(): Int {
42 | return data.hashCode()
43 | }
44 |
45 | }
46 |
47 | class PurchaseTypeConverter {
48 | @TypeConverter
49 | fun toString(purchase: Purchase): String = purchase.originalJson + '|' + purchase.signature
50 |
51 | @TypeConverter
52 | fun toPurchase(data: String): Purchase = data.split('|').let {
53 | Purchase(it[0], it[1])
54 | }
55 | }
--------------------------------------------------------------------------------
/codelab-02/app/src/main/java/com/example/playbilling/trivialdrive/kotlin/billingrepo/localdb/Entitlements.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2018 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.playbilling.trivialdrive.kotlin.billingrepo.localdb
18 |
19 | import androidx.room.Entity
20 | import androidx.room.PrimaryKey
21 |
22 | private const val FULL_TANK = 4
23 | private const val EMPTY_TANK = 0
24 | const val GAS_PURCHASE = 1
25 |
26 | abstract class Entitlement {
27 | @PrimaryKey
28 | var id: Int = 1
29 |
30 | abstract fun mayPurchase(): Boolean
31 | }
32 |
33 | @Entity(tableName = "premium_car")
34 | data class PremiumCar(val entitled: Boolean) : Entitlement() {
35 | override fun mayPurchase(): Boolean = !entitled
36 | }
37 |
38 | @Entity(tableName = "gold_status")
39 | data class GoldStatus(val entitled: Boolean) : Entitlement() {
40 | override fun mayPurchase(): Boolean = !entitled
41 | }
42 |
43 | @Entity(tableName = "gas_tank")
44 | class GasTank(private var level: Int) : Entitlement() {
45 |
46 | fun getLevel() = level
47 |
48 | override fun mayPurchase(): Boolean = level < FULL_TANK
49 |
50 | fun needGas(): Boolean = level <= EMPTY_TANK
51 |
52 | fun decrement(by: Int = 1) {
53 | level -= by
54 | }
55 |
56 | }
--------------------------------------------------------------------------------
/codelab-02/app/src/main/java/com/example/playbilling/trivialdrive/kotlin/billingrepo/localdb/LocalBillingDb.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2018 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.example.playbilling.trivialdrive.kotlin.billingrepo.localdb
17 |
18 |
19 | import android.content.Context
20 | import androidx.room.Database
21 | import androidx.room.Room
22 | import androidx.room.RoomDatabase
23 |
24 | @Database(entities = [CachedPurchase::class, GasTank::class, PremiumCar::class, GoldStatus::class, AugmentedSkuDetails::class],
25 | version = 1, exportSchema = false)
26 | abstract class LocalBillingDb : RoomDatabase() {
27 | abstract fun purchaseDao(): PurchaseDao
28 | abstract fun entitlementsDao(): EntitlementsDao
29 | abstract fun skuDetailsDao(): AugmentedSkuDetailsDao
30 |
31 | companion object {
32 | @Volatile
33 | private var INSTANCE: LocalBillingDb? = null
34 |
35 | fun getInstance(context: Context): LocalBillingDb {
36 | return INSTANCE
37 | ?: synchronized(this) {
38 | var instance = INSTANCE
39 | if (instance == null) {
40 | instance = Room.databaseBuilder(
41 | context.applicationContext,
42 | LocalBillingDb::class.java,
43 | "purchase_db")
44 | .fallbackToDestructiveMigration()//remote sources more reliable
45 | .build()
46 | INSTANCE = instance
47 | }
48 | instance!!
49 | }
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/codelab-02/app/src/main/java/com/example/playbilling/trivialdrive/kotlin/billingrepo/localdb/PurchaseDao.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2018 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.example.playbilling.trivialdrive.kotlin.billingrepo.localdb
17 |
18 | import androidx.room.*
19 | import com.android.billingclient.api.Purchase
20 |
21 | @Dao
22 | interface PurchaseDao {
23 | @Query("SELECT * FROM purchase_table")
24 | fun getPurchases(): List
25 |
26 | @Insert
27 | fun insert(purchase: CachedPurchase)
28 |
29 | @Transaction
30 | fun insert(vararg purchases: Purchase) {
31 | purchases.forEach {
32 | insert(CachedPurchase(data = it))
33 | }
34 | }
35 |
36 | @Delete
37 | fun delete(vararg purchases: CachedPurchase)
38 |
39 | @Query("DELETE FROM purchase_table")
40 | fun deleteAll()
41 | }
--------------------------------------------------------------------------------
/codelab-02/app/src/main/res/drawable-v24/free_car.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-02/app/src/main/res/drawable-v24/free_car.png
--------------------------------------------------------------------------------
/codelab-02/app/src/main/res/drawable-v24/gas.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-02/app/src/main/res/drawable-v24/gas.png
--------------------------------------------------------------------------------
/codelab-02/app/src/main/res/drawable-v24/gas_level_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-02/app/src/main/res/drawable-v24/gas_level_0.png
--------------------------------------------------------------------------------
/codelab-02/app/src/main/res/drawable-v24/gas_level_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-02/app/src/main/res/drawable-v24/gas_level_1.png
--------------------------------------------------------------------------------
/codelab-02/app/src/main/res/drawable-v24/gas_level_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-02/app/src/main/res/drawable-v24/gas_level_2.png
--------------------------------------------------------------------------------
/codelab-02/app/src/main/res/drawable-v24/gas_level_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-02/app/src/main/res/drawable-v24/gas_level_3.png
--------------------------------------------------------------------------------
/codelab-02/app/src/main/res/drawable-v24/gas_level_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-02/app/src/main/res/drawable-v24/gas_level_4.png
--------------------------------------------------------------------------------
/codelab-02/app/src/main/res/drawable-v24/gold_status.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-02/app/src/main/res/drawable-v24/gold_status.png
--------------------------------------------------------------------------------
/codelab-02/app/src/main/res/drawable-v24/gold_subs_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-02/app/src/main/res/drawable-v24/gold_subs_icon.png
--------------------------------------------------------------------------------
/codelab-02/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/codelab-02/app/src/main/res/drawable-v24/premium_car.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-02/app/src/main/res/drawable-v24/premium_car.png
--------------------------------------------------------------------------------
/codelab-02/app/src/main/res/drawable-v24/title.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-02/app/src/main/res/drawable-v24/title.png
--------------------------------------------------------------------------------
/codelab-02/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
26 |
27 |
36 |
37 |
--------------------------------------------------------------------------------
/codelab-02/app/src/main/res/layout/fragment_make_purchase.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
26 |
29 |
35 |
38 |
44 |
45 |
--------------------------------------------------------------------------------
/codelab-02/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/codelab-02/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/codelab-02/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-02/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/codelab-02/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-02/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/codelab-02/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-02/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/codelab-02/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-02/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/codelab-02/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-02/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/codelab-02/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-02/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/codelab-02/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-02/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/codelab-02/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-02/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/codelab-02/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-02/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/codelab-02/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-02/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/codelab-02/app/src/main/res/navigation/navigation_graph.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
24 |
25 |
30 |
33 |
34 |
38 |
41 |
42 |
--------------------------------------------------------------------------------
/codelab-02/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
20 | #008577
21 | #00574B
22 | #FFCA28
23 | #FFE082
24 | #FFECB3
25 | #CFD8DC
26 | #90A4AE
27 | #263238
28 |
29 |
--------------------------------------------------------------------------------
/codelab-02/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
20 | 16dp
21 | 8dp
22 | 32dp
23 | 8dp
24 | 8dp
25 |
--------------------------------------------------------------------------------
/codelab-02/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 | Trivial Drive Kotlin
19 | Hello blank fragment
20 | Fun Products
21 | Fun Subscriptions
22 | Vroooom, you drove a few miles!
23 | Oh, no! You are out of gas! Try buying some!
24 |
25 |
--------------------------------------------------------------------------------
/codelab-02/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 |
20 |
26 |
27 |
35 |
36 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/codelab-02/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | android.enableJetifier=true
15 | android.useAndroidX=true
16 |
17 | # You can specify the keystore properties file from the command line.
18 | # Example release build using release keystore 'release-keystore.properties':
19 | # ./gradlew -PkeystorePropertiesFilename=release-keystore.properties assembleRelease
20 | #
21 | # Default source: keystore.properties
22 | #
23 | keystorePropertiesFilename=keystore.properties
24 |
25 |
--------------------------------------------------------------------------------
/codelab-02/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-02/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/codelab-02/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/codelab-02/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/codelab-02/keystore.properties:
--------------------------------------------------------------------------------
1 | storeFile=kotlin_td_keystore.jks
2 | storePassword=B!llingS@mpl3
3 | keyAlias=IAB
4 | keyPassword=B!llingS@mpl3
5 |
--------------------------------------------------------------------------------
/codelab-02/kotlin_td_keystore.jks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-02/kotlin_td_keystore.jks
--------------------------------------------------------------------------------
/codelab-02/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/codelab-03/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea
5 | /.idea/caches/build_file_checksums.ser
6 | /.idea/libraries
7 | /.idea/modules.xml
8 | /.idea/workspace.xml
9 | .DS_Store
10 | /build
11 | /captures
12 | .externalNativeBuild
13 | /app/release
--------------------------------------------------------------------------------
/codelab-03/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/codelab-03/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/codelab-03/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
21 |
22 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/codelab-03/app/src/main/java/com/example/playbilling/trivialdrive/kotlin/MainActivity.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2019 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.example.playbilling.trivialdrive.kotlin
17 |
18 | import android.os.Bundle
19 | import androidx.appcompat.app.AppCompatActivity
20 |
21 | class MainActivity : AppCompatActivity() {
22 |
23 | override fun onCreate(savedInstanceState: Bundle?) {
24 | super.onCreate(savedInstanceState)
25 | setContentView(R.layout.activity_main)
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/codelab-03/app/src/main/java/com/example/playbilling/trivialdrive/kotlin/MakePurchaseFragment.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2019 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.example.playbilling.trivialdrive.kotlin
17 |
18 |
19 | import android.os.Bundle
20 | import android.util.Log
21 | import android.view.LayoutInflater
22 | import android.view.View
23 | import android.view.ViewGroup
24 | import androidx.fragment.app.Fragment
25 | import androidx.recyclerview.widget.RecyclerView
26 |
27 | /**
28 | * This Fragment is simply a wrapper for the inventory (i.e. items for sale). It contains two
29 | * [lists][RecyclerView], one for subscriptions and one for in-app products. Here again there is
30 | * no complicated billing logic. All the billing logic reside inside the [BillingRepository].
31 | * The [BillingRepository] provides a [AugmentedSkuDetails] object that shows what
32 | * is for sale and whether the user is allowed to buy the item at this moment. E.g. if the user
33 | * already has a full tank of gas, then they cannot buy gas at this moment.
34 | */
35 | class MakePurchaseFragment : Fragment() {
36 |
37 | val LOG_TAG = "MakePurchaseFragment"
38 |
39 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
40 | return inflater.inflate(R.layout.fragment_make_purchase, container, false)
41 | }
42 |
43 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
44 | super.onViewCreated(view, savedInstanceState)
45 | Log.d(LOG_TAG, "onViewCreated")
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/codelab-03/app/src/main/java/com/example/playbilling/trivialdrive/kotlin/billingrepo/BillingWebservice.kt:
--------------------------------------------------------------------------------
1 | package com.example.playbilling.trivialdrive.kotlin.billingrepo
2 |
3 | import com.android.billingclient.api.Purchase
4 |
5 | /**
6 | * Copyright (C) 2019 Google Inc. All Rights Reserved.
7 | *
8 | * Licensed under the Apache License, Version 2.0 (the "License");
9 | * you may not use this file except in compliance with the License.
10 | * You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing, software
15 | * distributed under the License is distributed on an "AS IS" BASIS,
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | * See the License for the specific language governing permissions and
18 | * limitations under the License.
19 | */
20 |
21 | class BillingWebservice {
22 | fun getPurchases(): Any {
23 | return Any()//TODO("not implemented")
24 | }
25 | fun updateServer(purchases: Set) {
26 | //TODO("not implemented")
27 | }
28 | fun onComsumeResponse(purchaseToken: String?, responseCode: Int) {
29 | //TODO("not implemented")
30 | }
31 | companion object {
32 | fun create(): BillingWebservice {
33 | //TODO("not implemented")
34 | return BillingWebservice()
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/codelab-03/app/src/main/java/com/example/playbilling/trivialdrive/kotlin/billingrepo/localdb/AugmentedSkuDetails.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2018 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.example.playbilling.trivialdrive.kotlin.billingrepo.localdb
17 |
18 | import androidx.room.Entity
19 | import androidx.room.PrimaryKey
20 |
21 | @Entity
22 | data class AugmentedSkuDetails(val canPurchase: Boolean, /* Not in SkuDetails; it's the augmentation */
23 | @PrimaryKey val sku: String,
24 | val type: String?,
25 | val price: String?,
26 | val title: String?,
27 | val description: String?,
28 | val originalJson: String?)
--------------------------------------------------------------------------------
/codelab-03/app/src/main/java/com/example/playbilling/trivialdrive/kotlin/billingrepo/localdb/AugmentedSkuDetailsDao.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2018 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.example.playbilling.trivialdrive.kotlin.billingrepo.localdb
17 |
18 | import androidx.lifecycle.LiveData
19 | import androidx.room.*
20 | import com.android.billingclient.api.BillingClient
21 | import com.android.billingclient.api.SkuDetails
22 |
23 | @Dao
24 | interface AugmentedSkuDetailsDao {
25 |
26 | @Query("SELECT * FROM AugmentedSkuDetails WHERE type = '${BillingClient.SkuType.SUBS}'")
27 | fun getSubscriptionSkuDetails(): LiveData>
28 |
29 | @Query("SELECT * FROM AugmentedSkuDetails WHERE type = '${BillingClient.SkuType.INAPP}'")
30 | fun getInappSkuDetails(): LiveData>
31 |
32 | @Transaction
33 | fun insertOrUpdate(skuDetails: SkuDetails) = skuDetails.apply {
34 | val result = getById(sku)
35 | val bool = if (result == null) true else result.canPurchase
36 | val originalJson = toString().substring("SkuDetails: ".length)
37 | val skuDetails = AugmentedSkuDetails(bool, sku, type, price, title, description, originalJson)
38 | insert(skuDetails)
39 | }
40 |
41 | @Transaction
42 | fun insertOrUpdate(sku: String, canPurchase: Boolean) {
43 | val result = getById(sku)
44 | if (result != null) {
45 | update(sku, canPurchase)
46 | } else {
47 | insert(AugmentedSkuDetails(canPurchase, sku, null, null, null, null, null))
48 | }
49 | }
50 |
51 | @Query("SELECT * FROM AugmentedSkuDetails WHERE sku = :sku")
52 | fun getById(sku: String): AugmentedSkuDetails
53 |
54 | @Insert(onConflict = OnConflictStrategy.REPLACE)
55 | fun insert(augmentedSkuDetails: AugmentedSkuDetails)
56 |
57 | @Query("UPDATE AugmentedSkuDetails SET canPurchase = :canPurchase WHERE sku = :sku")
58 | fun update(sku: String, canPurchase: Boolean)
59 | }
--------------------------------------------------------------------------------
/codelab-03/app/src/main/java/com/example/playbilling/trivialdrive/kotlin/billingrepo/localdb/CachedPurchase.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2018 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.example.playbilling.trivialdrive.kotlin.billingrepo.localdb
17 |
18 | import androidx.room.*
19 | import com.android.billingclient.api.Purchase
20 |
21 | @Entity(tableName = "purchase_table")
22 | @TypeConverters(PurchaseTypeConverter::class)
23 | class CachedPurchase(val data: Purchase) {
24 |
25 | @PrimaryKey(autoGenerate = true)
26 | var id: Int = 0
27 |
28 | @Ignore
29 | val purchaseToken = data.purchaseToken
30 | @Ignore
31 | val sku = data.sku
32 |
33 | override fun equals(other: Any?): Boolean {
34 | return when (other) {
35 | is CachedPurchase -> data.equals(other.data)
36 | is Purchase -> data.equals(other)
37 | else -> false
38 | }
39 | }
40 |
41 | override fun hashCode(): Int {
42 | return data.hashCode()
43 | }
44 |
45 | }
46 |
47 | class PurchaseTypeConverter {
48 | @TypeConverter
49 | fun toString(purchase: Purchase): String = purchase.originalJson + '|' + purchase.signature
50 |
51 | @TypeConverter
52 | fun toPurchase(data: String): Purchase = data.split('|').let {
53 | Purchase(it[0], it[1])
54 | }
55 | }
--------------------------------------------------------------------------------
/codelab-03/app/src/main/java/com/example/playbilling/trivialdrive/kotlin/billingrepo/localdb/Entitlements.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2018 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.playbilling.trivialdrive.kotlin.billingrepo.localdb
18 |
19 | import androidx.room.Entity
20 | import androidx.room.PrimaryKey
21 |
22 | private const val FULL_TANK = 4
23 | private const val EMPTY_TANK = 0
24 | const val GAS_PURCHASE = 1
25 |
26 | abstract class Entitlement {
27 | @PrimaryKey
28 | var id: Int = 1
29 |
30 | abstract fun mayPurchase(): Boolean
31 | }
32 |
33 | @Entity(tableName = "premium_car")
34 | data class PremiumCar(val entitled: Boolean) : Entitlement() {
35 | override fun mayPurchase(): Boolean = !entitled
36 | }
37 |
38 | @Entity(tableName = "gold_status")
39 | data class GoldStatus(val entitled: Boolean) : Entitlement() {
40 | override fun mayPurchase(): Boolean = !entitled
41 | }
42 |
43 | @Entity(tableName = "gas_tank")
44 | class GasTank(private var level: Int) : Entitlement() {
45 |
46 | fun getLevel() = level
47 |
48 | override fun mayPurchase(): Boolean = level < FULL_TANK
49 |
50 | fun needGas(): Boolean = level <= EMPTY_TANK
51 |
52 | fun decrement(by: Int = 1) {
53 | level -= by
54 | }
55 |
56 | }
--------------------------------------------------------------------------------
/codelab-03/app/src/main/java/com/example/playbilling/trivialdrive/kotlin/billingrepo/localdb/LocalBillingDb.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2018 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.example.playbilling.trivialdrive.kotlin.billingrepo.localdb
17 |
18 |
19 | import android.content.Context
20 | import androidx.room.Database
21 | import androidx.room.Room
22 | import androidx.room.RoomDatabase
23 |
24 | @Database(entities = [CachedPurchase::class, GasTank::class, PremiumCar::class, GoldStatus::class, AugmentedSkuDetails::class],
25 | version = 1, exportSchema = false)
26 | abstract class LocalBillingDb : RoomDatabase() {
27 | abstract fun purchaseDao(): PurchaseDao
28 | abstract fun entitlementsDao(): EntitlementsDao
29 | abstract fun skuDetailsDao(): AugmentedSkuDetailsDao
30 |
31 | companion object {
32 | @Volatile
33 | private var INSTANCE: LocalBillingDb? = null
34 |
35 | fun getInstance(context: Context): LocalBillingDb = INSTANCE ?: synchronized(this) {
36 | INSTANCE ?: Room.databaseBuilder(
37 | context.applicationContext,
38 | LocalBillingDb::class.java,
39 | "purchase_db")
40 | .fallbackToDestructiveMigration()
41 | .build().also { INSTANCE = it }
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/codelab-03/app/src/main/java/com/example/playbilling/trivialdrive/kotlin/billingrepo/localdb/PurchaseDao.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2018 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.example.playbilling.trivialdrive.kotlin.billingrepo.localdb
17 |
18 | import androidx.room.*
19 | import com.android.billingclient.api.Purchase
20 |
21 | @Dao
22 | interface PurchaseDao {
23 | @Query("SELECT * FROM purchase_table")
24 | fun getPurchases(): List
25 |
26 | @Insert
27 | fun insert(purchase: CachedPurchase)
28 |
29 | @Transaction
30 | fun insert(vararg purchases: Purchase) {
31 | purchases.forEach {
32 | insert(CachedPurchase(data = it))
33 | }
34 | }
35 |
36 | @Delete
37 | fun delete(vararg purchases: CachedPurchase)
38 |
39 | @Query("DELETE FROM purchase_table")
40 | fun deleteAll()
41 | }
--------------------------------------------------------------------------------
/codelab-03/app/src/main/res/drawable-v24/free_car.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-03/app/src/main/res/drawable-v24/free_car.png
--------------------------------------------------------------------------------
/codelab-03/app/src/main/res/drawable-v24/gas.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-03/app/src/main/res/drawable-v24/gas.png
--------------------------------------------------------------------------------
/codelab-03/app/src/main/res/drawable-v24/gas_level_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-03/app/src/main/res/drawable-v24/gas_level_0.png
--------------------------------------------------------------------------------
/codelab-03/app/src/main/res/drawable-v24/gas_level_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-03/app/src/main/res/drawable-v24/gas_level_1.png
--------------------------------------------------------------------------------
/codelab-03/app/src/main/res/drawable-v24/gas_level_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-03/app/src/main/res/drawable-v24/gas_level_2.png
--------------------------------------------------------------------------------
/codelab-03/app/src/main/res/drawable-v24/gas_level_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-03/app/src/main/res/drawable-v24/gas_level_3.png
--------------------------------------------------------------------------------
/codelab-03/app/src/main/res/drawable-v24/gas_level_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-03/app/src/main/res/drawable-v24/gas_level_4.png
--------------------------------------------------------------------------------
/codelab-03/app/src/main/res/drawable-v24/gold_status.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-03/app/src/main/res/drawable-v24/gold_status.png
--------------------------------------------------------------------------------
/codelab-03/app/src/main/res/drawable-v24/gold_subs_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-03/app/src/main/res/drawable-v24/gold_subs_icon.png
--------------------------------------------------------------------------------
/codelab-03/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/codelab-03/app/src/main/res/drawable-v24/premium_car.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-03/app/src/main/res/drawable-v24/premium_car.png
--------------------------------------------------------------------------------
/codelab-03/app/src/main/res/drawable-v24/title.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-03/app/src/main/res/drawable-v24/title.png
--------------------------------------------------------------------------------
/codelab-03/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
26 |
27 |
36 |
37 |
--------------------------------------------------------------------------------
/codelab-03/app/src/main/res/layout/fragment_make_purchase.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
26 |
29 |
35 |
38 |
44 |
45 |
--------------------------------------------------------------------------------
/codelab-03/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/codelab-03/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/codelab-03/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-03/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/codelab-03/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-03/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/codelab-03/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-03/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/codelab-03/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-03/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/codelab-03/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-03/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/codelab-03/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-03/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/codelab-03/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-03/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/codelab-03/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-03/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/codelab-03/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-03/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/codelab-03/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-03/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/codelab-03/app/src/main/res/navigation/navigation_graph.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
24 |
25 |
30 |
33 |
34 |
38 |
41 |
42 |
--------------------------------------------------------------------------------
/codelab-03/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
20 | #008577
21 | #00574B
22 | #FFCA28
23 | #FFE082
24 | #FFECB3
25 | #CFD8DC
26 | #90A4AE
27 | #263238
28 |
29 |
--------------------------------------------------------------------------------
/codelab-03/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
20 | 16dp
21 | 8dp
22 | 32dp
23 | 8dp
24 | 8dp
25 |
--------------------------------------------------------------------------------
/codelab-03/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 | Trivial Drive Kotlin
19 | Hello blank fragment
20 | Fun Products
21 | Fun Subscriptions
22 | Vroooom, you drove a few miles!
23 | Oh, no! You are out of gas! Try buying some!
24 |
25 |
--------------------------------------------------------------------------------
/codelab-03/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 |
20 |
26 |
27 |
35 |
36 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/codelab-03/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | android.enableJetifier=true
15 | android.useAndroidX=true
16 |
17 | # You can specify the keystore properties file from the command line.
18 | # Example release build using release keystore 'release-keystore.properties':
19 | # ./gradlew -PkeystorePropertiesFilename=release-keystore.properties assembleRelease
20 | #
21 | # Default source: keystore.properties
22 | #
23 | keystorePropertiesFilename=keystore.properties
24 |
25 |
--------------------------------------------------------------------------------
/codelab-03/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-03/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/codelab-03/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/codelab-03/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/codelab-03/keystore.properties:
--------------------------------------------------------------------------------
1 | storeFile=kotlin_td_keystore.jks
2 | storePassword=B!llingS@mpl3
3 | keyAlias=IAB
4 | keyPassword=B!llingS@mpl3
5 |
--------------------------------------------------------------------------------
/codelab-03/kotlin_td_keystore.jks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-03/kotlin_td_keystore.jks
--------------------------------------------------------------------------------
/codelab-03/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/codelab-04/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea
5 | /.idea/caches/build_file_checksums.ser
6 | /.idea/libraries
7 | /.idea/modules.xml
8 | /.idea/workspace.xml
9 | .DS_Store
10 | /build
11 | /captures
12 | .externalNativeBuild
13 | /app/release
--------------------------------------------------------------------------------
/codelab-04/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/codelab-04/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/codelab-04/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
21 |
22 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/codelab-04/app/src/main/java/com/example/playbilling/trivialdrive/kotlin/MainActivity.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2019 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.example.playbilling.trivialdrive.kotlin
17 |
18 | import android.os.Bundle
19 | import androidx.appcompat.app.AppCompatActivity
20 |
21 | class MainActivity : AppCompatActivity() {
22 |
23 | override fun onCreate(savedInstanceState: Bundle?) {
24 | super.onCreate(savedInstanceState)
25 | setContentView(R.layout.activity_main)
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/codelab-04/app/src/main/java/com/example/playbilling/trivialdrive/kotlin/billingrepo/BillingWebservice.kt:
--------------------------------------------------------------------------------
1 | package com.example.playbilling.trivialdrive.kotlin.billingrepo
2 |
3 | import com.android.billingclient.api.Purchase
4 |
5 | /**
6 | * Copyright (C) 2019 Google Inc. All Rights Reserved.
7 | *
8 | * Licensed under the Apache License, Version 2.0 (the "License");
9 | * you may not use this file except in compliance with the License.
10 | * You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing, software
15 | * distributed under the License is distributed on an "AS IS" BASIS,
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | * See the License for the specific language governing permissions and
18 | * limitations under the License.
19 | */
20 |
21 | class BillingWebservice {
22 | fun getPurchases(): Any {
23 | return Any()//TODO("not implemented")
24 | }
25 | fun updateServer(purchases: Set) {
26 | //TODO("not implemented")
27 | }
28 | fun onComsumeResponse(purchaseToken: String?, responseCode: Int) {
29 | //TODO("not implemented")
30 | }
31 | companion object {
32 | fun create(): BillingWebservice {
33 | //TODO("not implemented")
34 | return BillingWebservice()
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/codelab-04/app/src/main/java/com/example/playbilling/trivialdrive/kotlin/billingrepo/localdb/AugmentedSkuDetails.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2018 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.example.playbilling.trivialdrive.kotlin.billingrepo.localdb
17 |
18 | import androidx.room.Entity
19 | import androidx.room.PrimaryKey
20 |
21 | @Entity
22 | data class AugmentedSkuDetails(val canPurchase: Boolean, /* Not in SkuDetails; it's the augmentation */
23 | @PrimaryKey val sku: String,
24 | val type: String?,
25 | val price: String?,
26 | val title: String?,
27 | val description: String?,
28 | val originalJson: String?)
--------------------------------------------------------------------------------
/codelab-04/app/src/main/java/com/example/playbilling/trivialdrive/kotlin/billingrepo/localdb/AugmentedSkuDetailsDao.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2018 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.example.playbilling.trivialdrive.kotlin.billingrepo.localdb
17 |
18 | import androidx.lifecycle.LiveData
19 | import androidx.room.*
20 | import com.android.billingclient.api.BillingClient
21 | import com.android.billingclient.api.SkuDetails
22 |
23 | @Dao
24 | interface AugmentedSkuDetailsDao {
25 |
26 | @Query("SELECT * FROM AugmentedSkuDetails WHERE type = '${BillingClient.SkuType.SUBS}'")
27 | fun getSubscriptionSkuDetails(): LiveData>
28 |
29 | @Query("SELECT * FROM AugmentedSkuDetails WHERE type = '${BillingClient.SkuType.INAPP}'")
30 | fun getInappSkuDetails(): LiveData>
31 |
32 | @Transaction
33 | fun insertOrUpdate(skuDetails: SkuDetails) = skuDetails.apply {
34 | val result = getById(sku)
35 | val bool = if (result == null) true else result.canPurchase
36 | val originalJson = toString().substring("SkuDetails: ".length)
37 | val skuDetails = AugmentedSkuDetails(bool, sku, type, price, title, description, originalJson)
38 | insert(skuDetails)
39 | }
40 |
41 | @Transaction
42 | fun insertOrUpdate(sku: String, canPurchase: Boolean) {
43 | val result = getById(sku)
44 | if (result != null) {
45 | update(sku, canPurchase)
46 | } else {
47 | insert(AugmentedSkuDetails(canPurchase, sku, null, null, null, null, null))
48 | }
49 | }
50 |
51 | @Query("SELECT * FROM AugmentedSkuDetails WHERE sku = :sku")
52 | fun getById(sku: String): AugmentedSkuDetails
53 |
54 | @Insert(onConflict = OnConflictStrategy.REPLACE)
55 | fun insert(augmentedSkuDetails: AugmentedSkuDetails)
56 |
57 | @Query("UPDATE AugmentedSkuDetails SET canPurchase = :canPurchase WHERE sku = :sku")
58 | fun update(sku: String, canPurchase: Boolean)
59 | }
--------------------------------------------------------------------------------
/codelab-04/app/src/main/java/com/example/playbilling/trivialdrive/kotlin/billingrepo/localdb/CachedPurchase.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2018 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.example.playbilling.trivialdrive.kotlin.billingrepo.localdb
17 |
18 | import androidx.room.*
19 | import com.android.billingclient.api.Purchase
20 |
21 | @Entity(tableName = "purchase_table")
22 | @TypeConverters(PurchaseTypeConverter::class)
23 | class CachedPurchase(val data: Purchase) {
24 |
25 | @PrimaryKey(autoGenerate = true)
26 | var id: Int = 0
27 |
28 | @Ignore
29 | val purchaseToken = data.purchaseToken
30 | @Ignore
31 | val sku = data.sku
32 |
33 | override fun equals(other: Any?): Boolean {
34 | return when (other) {
35 | is CachedPurchase -> data.equals(other.data)
36 | is Purchase -> data.equals(other)
37 | else -> false
38 | }
39 | }
40 |
41 | override fun hashCode(): Int {
42 | return data.hashCode()
43 | }
44 |
45 | }
46 |
47 | class PurchaseTypeConverter {
48 | @TypeConverter
49 | fun toString(purchase: Purchase): String = purchase.originalJson + '|' + purchase.signature
50 |
51 | @TypeConverter
52 | fun toPurchase(data: String): Purchase = data.split('|').let {
53 | Purchase(it[0], it[1])
54 | }
55 | }
--------------------------------------------------------------------------------
/codelab-04/app/src/main/java/com/example/playbilling/trivialdrive/kotlin/billingrepo/localdb/Entitlements.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2018 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.playbilling.trivialdrive.kotlin.billingrepo.localdb
18 |
19 | import androidx.room.Entity
20 | import androidx.room.PrimaryKey
21 |
22 | private const val FULL_TANK = 4
23 | private const val EMPTY_TANK = 0
24 | const val GAS_PURCHASE = 1
25 |
26 | abstract class Entitlement {
27 | @PrimaryKey
28 | var id: Int = 1
29 |
30 | abstract fun mayPurchase(): Boolean
31 | }
32 |
33 | @Entity(tableName = "premium_car")
34 | data class PremiumCar(val entitled: Boolean) : Entitlement() {
35 | override fun mayPurchase(): Boolean = !entitled
36 | }
37 |
38 | @Entity(tableName = "gold_status")
39 | data class GoldStatus(val entitled: Boolean) : Entitlement() {
40 | override fun mayPurchase(): Boolean = !entitled
41 | }
42 |
43 | @Entity(tableName = "gas_tank")
44 | class GasTank(private var level: Int) : Entitlement() {
45 |
46 | fun getLevel() = level
47 |
48 | override fun mayPurchase(): Boolean = level < FULL_TANK
49 |
50 | fun needGas(): Boolean = level <= EMPTY_TANK
51 |
52 | fun decrement(by: Int = 1) {
53 | level -= by
54 | }
55 |
56 | }
--------------------------------------------------------------------------------
/codelab-04/app/src/main/java/com/example/playbilling/trivialdrive/kotlin/billingrepo/localdb/LocalBillingDb.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2018 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.example.playbilling.trivialdrive.kotlin.billingrepo.localdb
17 |
18 |
19 | import android.content.Context
20 | import androidx.room.Database
21 | import androidx.room.Room
22 | import androidx.room.RoomDatabase
23 |
24 | @Database(entities = [CachedPurchase::class, GasTank::class, PremiumCar::class, GoldStatus::class, AugmentedSkuDetails::class],
25 | version = 1, exportSchema = false)
26 | abstract class LocalBillingDb : RoomDatabase() {
27 | abstract fun purchaseDao(): PurchaseDao
28 | abstract fun entitlementsDao(): EntitlementsDao
29 | abstract fun skuDetailsDao(): AugmentedSkuDetailsDao
30 |
31 | companion object {
32 | @Volatile
33 | private var INSTANCE: LocalBillingDb? = null
34 |
35 | fun getInstance(context: Context): LocalBillingDb = INSTANCE?: synchronized(this) {
36 | INSTANCE ?: Room.databaseBuilder(
37 | context.applicationContext,
38 | LocalBillingDb::class.java,
39 | "purchase_db")
40 | .fallbackToDestructiveMigration()//remote sources more reliable
41 | .build().also { INSTANCE=it }
42 | }
43 | }
44 | }
--------------------------------------------------------------------------------
/codelab-04/app/src/main/java/com/example/playbilling/trivialdrive/kotlin/billingrepo/localdb/PurchaseDao.kt:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2018 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.example.playbilling.trivialdrive.kotlin.billingrepo.localdb
17 |
18 | import androidx.room.*
19 | import com.android.billingclient.api.Purchase
20 |
21 | @Dao
22 | interface PurchaseDao {
23 | @Query("SELECT * FROM purchase_table")
24 | fun getPurchases(): List
25 |
26 | @Insert
27 | fun insert(purchase: CachedPurchase)
28 |
29 | @Transaction
30 | fun insert(vararg purchases: Purchase) {
31 | purchases.forEach {
32 | insert(CachedPurchase(data = it))
33 | }
34 | }
35 |
36 | @Delete
37 | fun delete(vararg purchases: CachedPurchase)
38 |
39 | @Query("DELETE FROM purchase_table")
40 | fun deleteAll()
41 | }
--------------------------------------------------------------------------------
/codelab-04/app/src/main/res/drawable-v24/free_car.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-04/app/src/main/res/drawable-v24/free_car.png
--------------------------------------------------------------------------------
/codelab-04/app/src/main/res/drawable-v24/gas.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-04/app/src/main/res/drawable-v24/gas.png
--------------------------------------------------------------------------------
/codelab-04/app/src/main/res/drawable-v24/gas_level_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-04/app/src/main/res/drawable-v24/gas_level_0.png
--------------------------------------------------------------------------------
/codelab-04/app/src/main/res/drawable-v24/gas_level_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-04/app/src/main/res/drawable-v24/gas_level_1.png
--------------------------------------------------------------------------------
/codelab-04/app/src/main/res/drawable-v24/gas_level_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-04/app/src/main/res/drawable-v24/gas_level_2.png
--------------------------------------------------------------------------------
/codelab-04/app/src/main/res/drawable-v24/gas_level_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-04/app/src/main/res/drawable-v24/gas_level_3.png
--------------------------------------------------------------------------------
/codelab-04/app/src/main/res/drawable-v24/gas_level_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-04/app/src/main/res/drawable-v24/gas_level_4.png
--------------------------------------------------------------------------------
/codelab-04/app/src/main/res/drawable-v24/gold_status.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-04/app/src/main/res/drawable-v24/gold_status.png
--------------------------------------------------------------------------------
/codelab-04/app/src/main/res/drawable-v24/gold_subs_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-04/app/src/main/res/drawable-v24/gold_subs_icon.png
--------------------------------------------------------------------------------
/codelab-04/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/codelab-04/app/src/main/res/drawable-v24/premium_car.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-04/app/src/main/res/drawable-v24/premium_car.png
--------------------------------------------------------------------------------
/codelab-04/app/src/main/res/drawable-v24/title.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-04/app/src/main/res/drawable-v24/title.png
--------------------------------------------------------------------------------
/codelab-04/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
26 |
27 |
36 |
37 |
--------------------------------------------------------------------------------
/codelab-04/app/src/main/res/layout/fragment_make_purchase.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
26 |
29 |
35 |
38 |
44 |
45 |
--------------------------------------------------------------------------------
/codelab-04/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/codelab-04/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/codelab-04/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-04/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/codelab-04/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-04/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/codelab-04/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-04/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/codelab-04/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-04/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/codelab-04/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-04/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/codelab-04/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-04/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/codelab-04/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-04/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/codelab-04/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-04/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/codelab-04/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-04/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/codelab-04/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-04/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/codelab-04/app/src/main/res/navigation/navigation_graph.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
24 |
25 |
30 |
33 |
34 |
38 |
41 |
42 |
--------------------------------------------------------------------------------
/codelab-04/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
20 | #008577
21 | #00574B
22 | #FFCA28
23 | #FFE082
24 | #FFECB3
25 | #CFD8DC
26 | #90A4AE
27 | #263238
28 |
29 |
--------------------------------------------------------------------------------
/codelab-04/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
20 | 16dp
21 | 8dp
22 | 32dp
23 | 8dp
24 | 8dp
25 |
--------------------------------------------------------------------------------
/codelab-04/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 | Trivial Drive Kotlin
19 | Hello blank fragment
20 | Fun Products
21 | Fun Subscriptions
22 | Vroooom, you drove a few miles!
23 | Oh, no! You are out of gas! Try buying some!
24 |
25 |
--------------------------------------------------------------------------------
/codelab-04/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 |
20 |
26 |
27 |
35 |
36 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/codelab-04/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | android.enableJetifier=true
15 | android.useAndroidX=true
16 |
17 | # You can specify the keystore properties file from the command line.
18 | # Example release build using release keystore 'release-keystore.properties':
19 | # ./gradlew -PkeystorePropertiesFilename=release-keystore.properties assembleRelease
20 | #
21 | # Default source: keystore.properties
22 | #
23 | keystorePropertiesFilename=keystore.properties
24 |
25 |
--------------------------------------------------------------------------------
/codelab-04/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-04/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/codelab-04/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/codelab-04/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/codelab-04/keystore.properties:
--------------------------------------------------------------------------------
1 | storeFile=kotlin_td_keystore.jks
2 | storePassword=B!llingS@mpl3
3 | keyAlias=IAB
4 | keyPassword=B!llingS@mpl3
5 |
--------------------------------------------------------------------------------
/codelab-04/kotlin_td_keystore.jks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/googlecodelabs/play-billing-scalable-kotlin/c87da2b89f98f76a336c2f4193f124f4384240fe/codelab-04/kotlin_td_keystore.jks
--------------------------------------------------------------------------------
/codelab-04/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------