Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 32 additions & 1 deletion app/src/main/kotlin/com/google/ai/sample/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -657,21 +657,52 @@ class MainActivity : ComponentActivity() {
}
} else {
Log.i(TAG, "queryActiveSubscriptions: User has no active subscription for $subscriptionProductId. Re-evaluating trial logic.")
// --- START: MODIFICATION ---
if (TrialManager.isPurchased(this@MainActivity)) {
Log.w(TAG, "queryActiveSubscriptions: No active subscription found by Google Play Billing, but app was previously marked as purchased. Clearing purchase mark.")
TrialManager.clearPurchaseMark(this@MainActivity)
}
// --- END: MODIFICATION ---
if (TrialManager.getTrialState(this, null) != TrialManager.TrialState.PURCHASED) {
Log.d(TAG, "queryActiveSubscriptions: No active sub, and TrialManager confirms not purchased. Re-evaluating trial state and starting service if needed.")
updateTrialState(TrialManager.getTrialState(this, null))
// --- START: MODIFICATION ---
if (currentTrialState == TrialManager.TrialState.EXPIRED_INTERNET_TIME_CONFIRMED) {
Log.i(TAG, "queryActiveSubscriptions: Subscription deactivated (no active sub and trial expired). Showing Toast.")
Toast.makeText(this@MainActivity, "Subscription is deactivated", Toast.LENGTH_LONG).show()
}
// --- END: MODIFICATION ---
startTrialServiceIfNeeded()
} else {
Log.w(TAG, "queryActiveSubscriptions: No active sub from Google, but TrialManager says PURCHASED. This could be due to restored SharedPreferences without active subscription. Re-evaluating trial logic based on no internet time.")
updateTrialState(TrialManager.getTrialState(this, null))
updateTrialState(TrialManager.getTrialState(this, null))
// --- START: MODIFICATION ---
if (currentTrialState == TrialManager.TrialState.EXPIRED_INTERNET_TIME_CONFIRMED) {
Log.i(TAG, "queryActiveSubscriptions: Subscription deactivated (no active sub, was purchased, now trial expired). Showing Toast.")
Toast.makeText(this@MainActivity, "Subscription is deactivated", Toast.LENGTH_LONG).show()
}
// --- END: MODIFICATION ---
startTrialServiceIfNeeded()
}
}
} else {
Log.e(TAG, "Failed to query active subscriptions: ${billingResult.debugMessage}")
Log.d(TAG, "queryActiveSubscriptions: Query failed. Re-evaluating trial state based on no internet time and starting service if needed.")
// --- START: MODIFICATION ---
// It's important to also check/clear purchase mark here if query fails but app thought it was purchased
if (TrialManager.isPurchased(this@MainActivity)) {
Log.w(TAG, "queryActiveSubscriptions: Failed to query active subscriptions, but app was previously marked as purchased. Clearing purchase mark.")
TrialManager.clearPurchaseMark(this@MainActivity)
}
// --- END: MODIFICATION ---
if (TrialManager.getTrialState(this, null) != TrialManager.TrialState.PURCHASED) {
updateTrialState(TrialManager.getTrialState(this, null))
// --- START: MODIFICATION ---
if (currentTrialState == TrialManager.TrialState.EXPIRED_INTERNET_TIME_CONFIRMED) {
Log.i(TAG, "queryActiveSubscriptions: Subscription deactivated (query failed, trial expired). Showing Toast.")
Toast.makeText(this@MainActivity, "Subscription is deactivated", Toast.LENGTH_LONG).show()
}
// --- END: MODIFICATION ---
startTrialServiceIfNeeded()
}
}
Expand Down
17 changes: 16 additions & 1 deletion app/src/main/kotlin/com/google/ai/sample/TrialManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -235,14 +235,29 @@ object TrialManager {
Log.i(TAG, "App marked as purchased. Trial data (including obfuscated end time and confirmed expired flag) cleared. Purchase status stored in KEY_FEATURE_ACCESS_FLAG.")
}

private fun isPurchased(context: Context): Boolean {
internal fun isPurchased(context: Context): Boolean {
// Comment for future AI: KEY_FEATURE_ACCESS_FLAG indicates the app has been purchased.
Log.d(TAG, "isPurchased called, checking KEY_FEATURE_ACCESS_FLAG")
val purchased = getSharedPreferences(context).getBoolean(KEY_FEATURE_ACCESS_FLAG, false)
Log.d(TAG, "isPurchased (KEY_FEATURE_ACCESS_FLAG) returning: $purchased")
return purchased
}

fun clearPurchaseMark(context: Context) {
Log.d(TAG, "clearPurchaseMark called")
val editor = getSharedPreferences(context).edit()
// Comment for future AI: KEY_FEATURE_ACCESS_FLAG is set to false to indicate the feature is no longer accessed via purchase.
Log.d(TAG, "Setting KEY_FEATURE_ACCESS_FLAG to false")
editor.putBoolean(KEY_FEATURE_ACCESS_FLAG, false)
// Comment for future AI: KEY_INITIAL_SETUP_FLAG is reset to true to allow trial re-evaluation.
Log.d(TAG, "Setting KEY_INITIAL_SETUP_FLAG to true")
editor.putBoolean(KEY_INITIAL_SETUP_FLAG, true)
// IMPORTANT: KEY_CFG_TS (obfuscated trial end time) and KEY_CFG_ST (obfuscated confirmed expired flag)
// are intentionally NOT cleared here. The original trial period might still be relevant.
editor.apply()
Log.i(TAG, "Purchase mark cleared. Feature access flag set to false, initial setup flag reset to true. Trial end time and expired flag preserved.")
}

fun initializeTrialStateFlagsIfNecessary(context: Context) {
Log.d(TAG, "initializeTrialStateFlagsIfNecessary called")
val prefs = getSharedPreferences(context)
Expand Down