From 9a0685a16536f3a9f51169ed535f45d193ac8b99 Mon Sep 17 00:00:00 2001 From: William Brawner Date: Wed, 10 Jun 2020 11:46:05 -0700 Subject: [PATCH] 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 --- app/build.gradle | 20 +++- .../utility/SupportLinkProvider.kt | 9 ++ .../view/activity/SupportActivity.kt | 71 ++---------- .../utility/SupportLinkProvider.kt | 105 ++++++++++++++++++ 4 files changed, 139 insertions(+), 66 deletions(-) create mode 100644 app/src/free/java/com/wbrawner/simplemarkdown/utility/SupportLinkProvider.kt create mode 100644 app/src/play/java/com/wbrawner/simplemarkdown/utility/SupportLinkProvider.kt diff --git a/app/build.gradle b/app/build.gradle index 9cecc07..adc8182 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -68,6 +68,14 @@ android { buildConfigField "boolean", "ENABLE_CUSTOM_CSS", "false" } } + flavorDimensions "freedom" + productFlavors { + play {} + free { + applicationIdSuffix ".free" + versionNameSuffix "-free" + } + } dexOptions { jumboMode true } @@ -100,8 +108,8 @@ dependencies { implementation 'com.google.android.material:material:1.1.0' implementation 'androidx.legacy:legacy-support-v13:1.0.0' implementation 'com.commonsware.cwac:anddown:0.3.0' - implementation 'com.android.billingclient:billing:3.0.0' - implementation 'com.google.firebase:firebase-core:17.4.3' + playImplementation 'com.android.billingclient:billing:3.0.0' + playImplementation 'com.google.firebase:firebase-core:17.4.3' implementation "androidx.core:core-ktx:1.3.0" implementation 'androidx.browser:browser:1.2.0' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" @@ -116,7 +124,13 @@ dependencies { 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 { mavenCentral() jcenter() diff --git a/app/src/free/java/com/wbrawner/simplemarkdown/utility/SupportLinkProvider.kt b/app/src/free/java/com/wbrawner/simplemarkdown/utility/SupportLinkProvider.kt new file mode 100644 index 0000000..2bff236 --- /dev/null +++ b/app/src/free/java/com/wbrawner/simplemarkdown/utility/SupportLinkProvider.kt @@ -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>() +} \ No newline at end of file diff --git a/app/src/main/java/com/wbrawner/simplemarkdown/view/activity/SupportActivity.kt b/app/src/main/java/com/wbrawner/simplemarkdown/view/activity/SupportActivity.kt index 5990a65..a726625 100644 --- a/app/src/main/java/com/wbrawner/simplemarkdown/view/activity/SupportActivity.kt +++ b/app/src/main/java/com/wbrawner/simplemarkdown/view/activity/SupportActivity.kt @@ -6,18 +6,15 @@ import android.net.Uri import android.os.Bundle import android.view.MenuItem import android.view.View -import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.browser.customtabs.CustomTabsIntent -import com.android.billingclient.api.* -import com.google.android.material.button.MaterialButton +import androidx.lifecycle.Observer import com.wbrawner.simplemarkdown.R +import com.wbrawner.simplemarkdown.utility.SupportLinkProvider import kotlinx.android.synthetic.main.activity_support.* -class SupportActivity : AppCompatActivity(), BillingClientStateListener, PurchasesUpdatedListener { - private lateinit var billingClient: BillingClient - +class SupportActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_support) @@ -31,11 +28,6 @@ class SupportActivity : AppCompatActivity(), BillingClientStateListener, Purchas } setTitle(R.string.support_title) supportActionBar?.setDisplayHomeAsUpEnabled(true) - billingClient = BillingClient.newBuilder(applicationContext) - .setListener(this) - .enablePendingPurchases() - .build() - billingClient.startConnection(this) githubButton.setOnClickListener { CustomTabsIntent.Builder() .addDefaultShareMenuItem() @@ -57,6 +49,11 @@ class SupportActivity : AppCompatActivity(), BillingClientStateListener, Purchas startActivity(playStoreIntent) } } + SupportLinkProvider(this).supportLinks.observe(this, Observer { links -> + links.forEach { + supportButtons.addView(it) + } + }) } override fun onOptionsItemSelected(item: MenuItem): Boolean { @@ -66,56 +63,4 @@ class SupportActivity : AppCompatActivity(), BillingClientStateListener, Purchas } 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?) { - 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() - } - } - } } \ No newline at end of file diff --git a/app/src/play/java/com/wbrawner/simplemarkdown/utility/SupportLinkProvider.kt b/app/src/play/java/com/wbrawner/simplemarkdown/utility/SupportLinkProvider.kt new file mode 100644 index 0000000..8f8f3db --- /dev/null +++ b/app/src/play/java/com/wbrawner/simplemarkdown/utility/SupportLinkProvider.kt @@ -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>() + + 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?) { + 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() + } + } + } +} \ No newline at end of file