Implement freedom build flavors
This is a necessary step in separating the proprietary code (like Google Play Billing) from the FLOSS code so that I can eventually get around to publishing the app on fdroid Signed-off-by: William Brawner <me@wbrawner.com>
This commit is contained in:
parent
c3821fbfc9
commit
9a0685a165
4 changed files with 139 additions and 66 deletions
|
@ -68,6 +68,14 @@ android {
|
||||||
buildConfigField "boolean", "ENABLE_CUSTOM_CSS", "false"
|
buildConfigField "boolean", "ENABLE_CUSTOM_CSS", "false"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
flavorDimensions "freedom"
|
||||||
|
productFlavors {
|
||||||
|
play {}
|
||||||
|
free {
|
||||||
|
applicationIdSuffix ".free"
|
||||||
|
versionNameSuffix "-free"
|
||||||
|
}
|
||||||
|
}
|
||||||
dexOptions {
|
dexOptions {
|
||||||
jumboMode true
|
jumboMode true
|
||||||
}
|
}
|
||||||
|
@ -100,8 +108,8 @@ dependencies {
|
||||||
implementation 'com.google.android.material:material:1.1.0'
|
implementation 'com.google.android.material:material:1.1.0'
|
||||||
implementation 'androidx.legacy:legacy-support-v13:1.0.0'
|
implementation 'androidx.legacy:legacy-support-v13:1.0.0'
|
||||||
implementation 'com.commonsware.cwac:anddown:0.3.0'
|
implementation 'com.commonsware.cwac:anddown:0.3.0'
|
||||||
implementation 'com.android.billingclient:billing:3.0.0'
|
playImplementation 'com.android.billingclient:billing:3.0.0'
|
||||||
implementation 'com.google.firebase:firebase-core:17.4.3'
|
playImplementation 'com.google.firebase:firebase-core:17.4.3'
|
||||||
implementation "androidx.core:core-ktx:1.3.0"
|
implementation "androidx.core:core-ktx:1.3.0"
|
||||||
implementation 'androidx.browser:browser:1.2.0'
|
implementation 'androidx.browser:browser:1.2.0'
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||||
|
@ -116,7 +124,13 @@ dependencies {
|
||||||
implementation 'eu.crydee:syllable-counter:4.0.2'
|
implementation 'eu.crydee:syllable-counter:4.0.2'
|
||||||
}
|
}
|
||||||
|
|
||||||
apply plugin: 'com.google.gms.google-services'
|
android.productFlavors.each { flavor ->
|
||||||
|
if (getGradle().getStartParameter().getTaskRequests().toString().toLowerCase().contains(flavor.name)
|
||||||
|
&& flavor.name == 'play') {
|
||||||
|
apply plugin: 'com.google.gms.google-services'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
jcenter()
|
jcenter()
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
package com.wbrawner.simplemarkdown.utility
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import com.google.android.material.button.MaterialButton
|
||||||
|
|
||||||
|
class SupportLinkProvider(@Suppress("unused") private val activity: Activity) {
|
||||||
|
val supportLinks = MutableLiveData<List<MaterialButton>>()
|
||||||
|
}
|
|
@ -6,18 +6,15 @@ import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.browser.customtabs.CustomTabsIntent
|
import androidx.browser.customtabs.CustomTabsIntent
|
||||||
import com.android.billingclient.api.*
|
import androidx.lifecycle.Observer
|
||||||
import com.google.android.material.button.MaterialButton
|
|
||||||
import com.wbrawner.simplemarkdown.R
|
import com.wbrawner.simplemarkdown.R
|
||||||
|
import com.wbrawner.simplemarkdown.utility.SupportLinkProvider
|
||||||
import kotlinx.android.synthetic.main.activity_support.*
|
import kotlinx.android.synthetic.main.activity_support.*
|
||||||
|
|
||||||
|
|
||||||
class SupportActivity : AppCompatActivity(), BillingClientStateListener, PurchasesUpdatedListener {
|
class SupportActivity : AppCompatActivity() {
|
||||||
private lateinit var billingClient: BillingClient
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_support)
|
setContentView(R.layout.activity_support)
|
||||||
|
@ -31,11 +28,6 @@ class SupportActivity : AppCompatActivity(), BillingClientStateListener, Purchas
|
||||||
}
|
}
|
||||||
setTitle(R.string.support_title)
|
setTitle(R.string.support_title)
|
||||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||||
billingClient = BillingClient.newBuilder(applicationContext)
|
|
||||||
.setListener(this)
|
|
||||||
.enablePendingPurchases()
|
|
||||||
.build()
|
|
||||||
billingClient.startConnection(this)
|
|
||||||
githubButton.setOnClickListener {
|
githubButton.setOnClickListener {
|
||||||
CustomTabsIntent.Builder()
|
CustomTabsIntent.Builder()
|
||||||
.addDefaultShareMenuItem()
|
.addDefaultShareMenuItem()
|
||||||
|
@ -57,6 +49,11 @@ class SupportActivity : AppCompatActivity(), BillingClientStateListener, Purchas
|
||||||
startActivity(playStoreIntent)
|
startActivity(playStoreIntent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
SupportLinkProvider(this).supportLinks.observe(this, Observer { links ->
|
||||||
|
links.forEach {
|
||||||
|
supportButtons.addView(it)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
@ -66,56 +63,4 @@ class SupportActivity : AppCompatActivity(), BillingClientStateListener, Purchas
|
||||||
}
|
}
|
||||||
return super.onOptionsItemSelected(item)
|
return super.onOptionsItemSelected(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBillingSetupFinished(result: BillingResult) {
|
|
||||||
if (result.responseCode != BillingClient.BillingResponseCode.OK) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val skuDetails = SkuDetailsParams.newBuilder()
|
|
||||||
.setSkusList(listOf("support_the_developer", "tip_coffee", "tip_beer"))
|
|
||||||
.setType(BillingClient.SkuType.INAPP)
|
|
||||||
.build()
|
|
||||||
billingClient.querySkuDetailsAsync(skuDetails) { skuDetailsResponse, skuDetailsList ->
|
|
||||||
// Process the result.
|
|
||||||
if (skuDetailsResponse.responseCode != BillingClient.BillingResponseCode.OK || skuDetailsList.isNullOrEmpty()) {
|
|
||||||
return@querySkuDetailsAsync
|
|
||||||
}
|
|
||||||
|
|
||||||
skuDetailsList.sortedBy { it.priceAmountMicros }.forEach { skuDetails ->
|
|
||||||
val supportButton = MaterialButton(this@SupportActivity)
|
|
||||||
supportButton.text = getString(
|
|
||||||
R.string.support_button_purchase,
|
|
||||||
skuDetails.title,
|
|
||||||
skuDetails.price
|
|
||||||
)
|
|
||||||
supportButton.setOnClickListener {
|
|
||||||
val flowParams = BillingFlowParams.newBuilder()
|
|
||||||
.setSkuDetails(skuDetails)
|
|
||||||
.build()
|
|
||||||
billingClient.launchBillingFlow(this, flowParams)
|
|
||||||
}
|
|
||||||
supportButtons.addView(supportButton)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBillingServiceDisconnected() {
|
|
||||||
billingClient.startConnection(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPurchasesUpdated(result: BillingResult, purchases: MutableList<Purchase>?) {
|
|
||||||
purchases?.forEach { purchase ->
|
|
||||||
val consumeParams = ConsumeParams.newBuilder()
|
|
||||||
.setPurchaseToken(purchase.purchaseToken)
|
|
||||||
.build()
|
|
||||||
billingClient.consumeAsync(consumeParams) { _, _ ->
|
|
||||||
Toast.makeText(
|
|
||||||
this@SupportActivity,
|
|
||||||
getString(R.string.support_thank_you),
|
|
||||||
Toast.LENGTH_SHORT
|
|
||||||
).show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -0,0 +1,105 @@
|
||||||
|
package com.wbrawner.simplemarkdown.utility
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.app.Application
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import com.android.billingclient.api.*
|
||||||
|
import com.google.android.material.button.MaterialButton
|
||||||
|
import com.wbrawner.simplemarkdown.R
|
||||||
|
|
||||||
|
class SupportLinkProvider(private val activity: Activity) : BillingClientStateListener,
|
||||||
|
PurchasesUpdatedListener {
|
||||||
|
val supportLinks = MutableLiveData<List<MaterialButton>>()
|
||||||
|
|
||||||
|
private val billingClient: BillingClient = BillingClient.newBuilder(activity.applicationContext)
|
||||||
|
.setListener(this)
|
||||||
|
.enablePendingPurchases()
|
||||||
|
.build()
|
||||||
|
|
||||||
|
init {
|
||||||
|
billingClient.startConnection(this)
|
||||||
|
activity.application.registerActivityLifecycleCallbacks(
|
||||||
|
object : Application.ActivityLifecycleCallbacks {
|
||||||
|
override fun onActivityPaused(activity: Activity) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityStarted(activity: Activity) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityDestroyed(activity: Activity) {
|
||||||
|
billingClient.endConnection()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityStopped(activity: Activity) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityResumed(activity: Activity) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBillingSetupFinished(result: BillingResult) {
|
||||||
|
if (result.responseCode != BillingClient.BillingResponseCode.OK) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val skuDetails = SkuDetailsParams.newBuilder()
|
||||||
|
.setSkusList(listOf("support_the_developer", "tip_coffee", "tip_beer"))
|
||||||
|
.setType(BillingClient.SkuType.INAPP)
|
||||||
|
.build()
|
||||||
|
billingClient.querySkuDetailsAsync(skuDetails) { skuDetailsResponse, skuDetailsList ->
|
||||||
|
// Process the result.
|
||||||
|
if (skuDetailsResponse.responseCode != BillingClient.BillingResponseCode.OK || skuDetailsList.isNullOrEmpty()) {
|
||||||
|
return@querySkuDetailsAsync
|
||||||
|
}
|
||||||
|
|
||||||
|
skuDetailsList.sortedBy { it.priceAmountMicros }
|
||||||
|
.map { skuDetails ->
|
||||||
|
val supportButton = MaterialButton(activity)
|
||||||
|
supportButton.text = activity.getString(
|
||||||
|
R.string.support_button_purchase,
|
||||||
|
skuDetails.title,
|
||||||
|
skuDetails.price
|
||||||
|
)
|
||||||
|
supportButton.setOnClickListener {
|
||||||
|
val flowParams = BillingFlowParams.newBuilder()
|
||||||
|
.setSkuDetails(skuDetails)
|
||||||
|
.build()
|
||||||
|
billingClient.launchBillingFlow(activity, flowParams)
|
||||||
|
}
|
||||||
|
supportButton
|
||||||
|
}
|
||||||
|
.let {
|
||||||
|
supportLinks.postValue(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBillingServiceDisconnected() {
|
||||||
|
billingClient.startConnection(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPurchasesUpdated(result: BillingResult, purchases: MutableList<Purchase>?) {
|
||||||
|
purchases?.forEach { purchase ->
|
||||||
|
val consumeParams = ConsumeParams.newBuilder()
|
||||||
|
.setPurchaseToken(purchase.purchaseToken)
|
||||||
|
.build()
|
||||||
|
billingClient.consumeAsync(consumeParams) { _, _ ->
|
||||||
|
Toast.makeText(
|
||||||
|
activity,
|
||||||
|
activity.getString(R.string.support_thank_you),
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue