Skip to content

Commit 7d452e7

Browse files
Merge pull request #255 from Ayush0Chaudhary/revenue-cat
💵 Added integration for the revennue cat
2 parents 1d497dd + e039ae5 commit 7d452e7

File tree

6 files changed

+86
-16
lines changed

6 files changed

+86
-16
lines changed

app/build.gradle.kts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ android {
4141
val googlecloudProxyURL = localProperties.getProperty("GCLOUD_PROXY_URL") ?: ""
4242
val googlecloudProxyURLKey = localProperties.getProperty("GCLOUD_PROXY_URL_KEY") ?: ""
4343
val revenueCatSDK = localProperties.getProperty("REVENUE_CAT_PUBLIC_URL") ?: ""
44+
val revenueCatApiKey = localProperties.getProperty("REVENUECAT_API_KEY") ?: ""
45+
4446
val debugSha1 = "D0:A1:49:03:FD:B5:37:DF:B5:36:51:B1:66:AE:70:11:E2:59:08:33"
4547

4648
defaultConfig {
@@ -65,6 +67,8 @@ android {
6567
buildConfigField("String", "GCLOUD_PROXY_URL", "\"$googlecloudProxyURL\"")
6668
buildConfigField("String", "GCLOUD_PROXY_URL_KEY", "\"$googlecloudProxyURLKey\"")
6769
buildConfigField("String", "REVENUE_CAT_PUBLIC_URL", "\"$revenueCatSDK\"")
70+
buildConfigField("String", "REVENUECAT_API_KEY", "\"$revenueCatApiKey\"")
71+
6872
}
6973

7074
buildTypes {
@@ -149,7 +153,8 @@ dependencies {
149153
implementation("com.google.firebase:firebase-crashlytics-ndk")
150154
implementation(libs.firebase.firestore)
151155
implementation("androidx.recyclerview:recyclerview:1.3.2")
152-
156+
implementation("com.revenuecat.purchases:purchases:9.7.0")
157+
implementation("com.revenuecat.purchases:purchases-ui:9.7.0")
153158
}
154159

155160
// Task to increment version for release builds

app/src/main/AndroidManifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
android:name=".MainActivity"
3535
android:exported="true"
3636
android:label="@string/app_name"
37+
android:launchMode="singleTop"
3738
android:theme="@style/Theme.Blurr">
3839
<intent-filter>
3940
<action android:name="android.intent.action.MAIN" />

app/src/main/java/com/blurr/voice/MainActivity.kt

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import android.os.Bundle
1717
import android.os.Handler
1818
import android.os.Looper
1919
import android.provider.Settings
20+
import android.provider.SyncStateContract
2021
import android.util.Log
2122
import android.view.View
2223
import android.view.ViewGroup
@@ -48,10 +49,17 @@ import com.google.android.gms.auth.api.signin.GoogleSignInOptions
4849
import com.google.firebase.Firebase
4950
import com.google.firebase.auth.FirebaseAuth
5051
import com.google.firebase.auth.auth
52+
import com.revenuecat.purchases.Purchases
53+
import com.revenuecat.purchases.awaitCustomerInfo
54+
import com.revenuecat.purchases.ui.revenuecatui.ExperimentalPreviewRevenueCatUIPurchasesAPI
55+
import com.revenuecat.purchases.ui.revenuecatui.activity.PaywallActivityLauncher
56+
import com.revenuecat.purchases.ui.revenuecatui.activity.PaywallResult
57+
import com.revenuecat.purchases.ui.revenuecatui.activity.PaywallResultHandler
5158
import kotlinx.coroutines.launch
5259
import java.io.File
5360

54-
class MainActivity : AppCompatActivity() {
61+
@OptIn(ExperimentalPreviewRevenueCatUIPurchasesAPI::class)
62+
class MainActivity : AppCompatActivity(), PaywallResultHandler {
5563

5664
private lateinit var handler: Handler
5765
private lateinit var managePermissionsButton: TextView
@@ -68,6 +76,9 @@ class MainActivity : AppCompatActivity() {
6876
private lateinit var increaseLimitsLink: TextView
6977
private lateinit var onboardingManager: OnboardingManager
7078
private lateinit var requestRoleLauncher: ActivityResultLauncher<Intent>
79+
80+
private lateinit var paywallActivityLauncher: PaywallActivityLauncher
81+
private lateinit var root: View
7182
companion object {
7283
const val ACTION_WAKE_WORD_FAILED = "com.blurr.voice.WAKE_WORD_FAILED"
7384
}
@@ -91,9 +102,16 @@ class MainActivity : AppCompatActivity() {
91102
}
92103
}
93104

105+
override fun onActivityResult(result: PaywallResult) {}
106+
107+
private fun launchPaywallActivity() {
108+
paywallActivityLauncher.launchIfNeeded(requiredEntitlementIdentifier = "pro")
109+
}
110+
94111
@RequiresApi(Build.VERSION_CODES.R)
95112
override fun onCreate(savedInstanceState: Bundle?) {
96113
super.onCreate(savedInstanceState)
114+
paywallActivityLauncher = PaywallActivityLauncher(this, this)
97115

98116
auth = Firebase.auth
99117
val currentUser = auth.currentUser
@@ -276,8 +294,11 @@ class MainActivity : AppCompatActivity() {
276294
findViewById<TextView>(R.id.triggersButton).setOnClickListener {
277295
startActivity(Intent(this, com.blurr.voice.triggers.ui.TriggersActivity::class.java))
278296
}
279-
findViewById<TextView>(R.id.memoriesButton).setOnClickListener {
280-
startActivity(Intent(this, MemoriesActivity::class.java))
297+
// findViewById<TextView>(R.id.memoriesButton).setOnClickListener {
298+
// startActivity(Intent(this, MemoriesActivity::class.java))
299+
// }
300+
findViewById<TextView>(R.id.goProButton).setOnClickListener {
301+
launchPaywallActivity()
281302
}
282303
saveKeyButton.setOnClickListener {
283304
startActivity(Intent(this, SettingsActivity::class.java))
@@ -421,23 +442,29 @@ class MainActivity : AppCompatActivity() {
421442
private fun updateTaskCounter() {
422443
lifecycleScope.launch {
423444
val tasksLeft = freemiumManager.getTasksRemaining()
424-
if (tasksLeft != null && tasksLeft >= 0) {
445+
val goProButton = findViewById<TextView>(R.id.goProButton)
446+
447+
if (tasksLeft == Long.MAX_VALUE) {
448+
tasksRemainingTextView.visibility = View.GONE
449+
increaseLimitsLink.visibility = View.GONE
450+
goProButton.visibility = View.GONE
451+
452+
} else if (tasksLeft != null && tasksLeft >= 0) {
453+
425454
tasksRemainingTextView.text = "You have $tasksLeft free tasks remaining."
426455
tasksRemainingTextView.visibility = View.VISIBLE
456+
goProButton.visibility = View.VISIBLE
427457

428-
// ADDED: Logic to show/hide the increase limits link
429-
// Show the link if the user has 5 or fewer tasks left.
430458
if (tasksLeft <= 10) {
431459
increaseLimitsLink.visibility = View.VISIBLE
432460
} else {
433461
increaseLimitsLink.visibility = View.GONE
434462
}
435463

436464
} else {
437-
// Hide both text views if there's an error or count is invalid
438465
tasksRemainingTextView.visibility = View.GONE
439-
increaseLimitsLink.visibility = View.GONE // ADDED
440-
}
466+
increaseLimitsLink.visibility = View.GONE
467+
goProButton.visibility = View.VISIBLE }
441468
}
442469
}
443470

app/src/main/java/com/blurr/voice/MyApplication.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ import com.blurr.voice.intents.impl.DialIntent
77
import com.blurr.voice.intents.impl.EmailComposeIntent
88
import com.blurr.voice.intents.impl.ShareTextIntent
99
import com.blurr.voice.intents.impl.ViewUrlIntent
10+
import com.revenuecat.purchases.LogLevel
11+
import com.revenuecat.purchases.Purchases
12+
import com.revenuecat.purchases.PurchasesConfiguration
1013

1114
class MyApplication : Application() {
1215

@@ -19,6 +22,11 @@ class MyApplication : Application() {
1922
super.onCreate()
2023
appContext = applicationContext
2124

25+
Purchases.logLevel = LogLevel.DEBUG
26+
Purchases.configure(
27+
PurchasesConfiguration.Builder(this, BuildConfig.REVENUECAT_API_KEY).build()
28+
)
29+
2230
// Register built-in app intents (plug-and-play extensions can add their own here)
2331
IntentRegistry.register(DialIntent())
2432
IntentRegistry.register(ViewUrlIntent())

app/src/main/java/com/blurr/voice/utilities/FreemiumManager.kt

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import com.google.firebase.Firebase
55
import com.google.firebase.auth.auth
66
import com.google.firebase.firestore.FieldValue
77
import com.google.firebase.firestore.firestore
8+
import com.revenuecat.purchases.Purchases
9+
import com.revenuecat.purchases.awaitCustomerInfo
810

911
import kotlinx.coroutines.tasks.await
1012

@@ -17,6 +19,16 @@ class FreemiumManager {
1719
const val FREE_PLAN_TASK_LIMIT = 15 // Set your free task limit here
1820
}
1921

22+
private suspend fun isUserSubscribed(): Boolean {
23+
return try {
24+
val customerInfo = Purchases.sharedInstance.awaitCustomerInfo()
25+
customerInfo.entitlements["pro"]?.isActive == true
26+
} catch (e: Exception) {
27+
Log.e("FreemiumManager", "Error fetching customer info: $e")
28+
false
29+
}
30+
}
31+
2032
/**
2133
* Checks if a user document exists in Firestore. If not, creates one with
2234
* the default free plan values. This should be called upon successful login.
@@ -46,6 +58,7 @@ class FreemiumManager {
4658
}
4759

4860
suspend fun getTasksRemaining(): Long? {
61+
if (isUserSubscribed()) return Long.MAX_VALUE
4962
val currentUser = auth.currentUser ?: return null
5063
return try {
5164
val document = db.collection("users").document(currentUser.uid).get().await()
@@ -61,6 +74,8 @@ class FreemiumManager {
6174
* @return true if tasksRemaining > 0, false otherwise.
6275
*/
6376
suspend fun canPerformTask(): Boolean {
77+
if (isUserSubscribed()) return true
78+
6479
val currentUser = auth.currentUser
6580
if (currentUser == null) {
6681
Log.w("FreemiumManager", "Cannot check task count, user is not logged in.")
@@ -83,7 +98,9 @@ class FreemiumManager {
8398
* Uses an atomic increment operation for safety.
8499
* This is a "fire and forget" call, we don't block the UI for it.
85100
*/
86-
fun decrementTaskCount() {
101+
suspend fun decrementTaskCount() {
102+
if (isUserSubscribed()) return
103+
87104
val currentUser = auth.currentUser ?: return
88105
db.collection("users").document(currentUser.uid)
89106
.update("tasksRemaining", FieldValue.increment(-1))

app/src/main/res/layout/activity_main.xml

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,21 @@
5858
android:textSize="40sp"
5959
tools:ignore="RtlCompat" />
6060

61+
<!-- <TextView-->
62+
<!-- android:id="@+id/memoriesButton"-->
63+
<!-- android:layout_width="match_parent"-->
64+
<!-- android:layout_height="wrap_content"-->
65+
<!-- android:layout_marginTop="16dp"-->
66+
<!-- android:background="@drawable/rounded_button"-->
67+
<!-- android:clickable="true"-->
68+
<!-- android:focusable="true"-->
69+
<!-- android:gravity="center"-->
70+
<!-- android:padding="12dp"-->
71+
<!-- android:text="Panda's Memories"-->
72+
<!-- android:textColor="@android:color/white"-->
73+
<!-- android:textSize="16sp" />-->
6174
<TextView
62-
android:id="@+id/memoriesButton"
75+
android:id="@+id/triggersButton"
6376
android:layout_width="match_parent"
6477
android:layout_height="wrap_content"
6578
android:layout_marginTop="16dp"
@@ -68,11 +81,11 @@
6881
android:focusable="true"
6982
android:gravity="center"
7083
android:padding="12dp"
71-
android:text="Panda's Memories"
84+
android:text="Set up Triggers"
7285
android:textColor="@android:color/white"
7386
android:textSize="16sp" />
7487
<TextView
75-
android:id="@+id/triggersButton"
88+
android:id="@+id/goProButton"
7689
android:layout_width="match_parent"
7790
android:layout_height="wrap_content"
7891
android:layout_marginTop="16dp"
@@ -81,10 +94,9 @@
8194
android:focusable="true"
8295
android:gravity="center"
8396
android:padding="12dp"
84-
android:text="Triggers"
97+
android:text="Go Pro"
8598
android:textColor="@android:color/white"
8699
android:textSize="16sp" />
87-
88100
<TextView
89101
android:id="@+id/saveKeyButton"
90102
android:layout_width="match_parent"

0 commit comments

Comments
 (0)