Skip to content

Commit

Permalink
Hard-code restored event names on first app launch
Browse files Browse the repository at this point in the history
Summary: Log restored events on first app launch

Reviewed By: jjiang10

Differential Revision:
D64879673

Privacy Context Container: L1285343

fbshipit-source-id: 15f53e63b5882f172bd14edb462a4d4ee0f4bf04
  • Loading branch information
maxalbrightmeta authored and facebook-github-bot committed Oct 25, 2024
1 parent 26f5048 commit e44a8b3
Show file tree
Hide file tree
Showing 7 changed files with 207 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import com.facebook.appevents.iap.InAppPurchaseUtils.BillingClientVersion.V5_V7
import com.facebook.appevents.iap.InAppPurchaseUtils.IAPProductType.INAPP
import android.content.Context
import androidx.annotation.RestrictTo
import com.facebook.appevents.iap.InAppPurchaseLoggerManager.getIsFirstAppLaunch
import com.facebook.appevents.iap.InAppPurchaseLoggerManager.setAppHasBeenLaunched
import com.facebook.appevents.iap.InAppPurchaseUtils.IAPProductType.SUBS
import com.facebook.appevents.integrity.ProtectedModeManager
import com.facebook.internal.FeatureManager
Expand Down Expand Up @@ -46,7 +48,7 @@ object InAppPurchaseAutoLogger {
failedToCreateWrapper.set(true)
return
}

if (isEnabled(FeatureManager.Feature.AndroidIAPSubscriptionAutoLogging)
&& (!ProtectedModeManager.isEnabled() || billingClientVersion == V2_V4)
) {
Expand All @@ -66,20 +68,23 @@ object InAppPurchaseAutoLogger {
billingClientVersion: InAppPurchaseUtils.BillingClientVersion,
packageName: String
) {
val isFirstAppLaunch = getIsFirstAppLaunch()
if (billingClientVersion == V2_V4) {
InAppPurchaseLoggerManager.filterPurchaseLogging(
InAppPurchaseBillingClientWrapperV2V4.iapPurchaseDetailsMap,
InAppPurchaseBillingClientWrapperV2V4.skuDetailsMap,
false,
packageName,
billingClientVersion
billingClientVersion,
isFirstAppLaunch
)
InAppPurchaseLoggerManager.filterPurchaseLogging(
InAppPurchaseBillingClientWrapperV2V4.subsPurchaseDetailsMap,
InAppPurchaseBillingClientWrapperV2V4.skuDetailsMap,
true,
packageName,
billingClientVersion
billingClientVersion,
isFirstAppLaunch
)
InAppPurchaseBillingClientWrapperV2V4.iapPurchaseDetailsMap.clear()
InAppPurchaseBillingClientWrapperV2V4.subsPurchaseDetailsMap.clear()
Expand All @@ -89,17 +94,22 @@ object InAppPurchaseAutoLogger {
InAppPurchaseBillingClientWrapperV5V7.productDetailsMap,
false,
packageName,
billingClientVersion
billingClientVersion,
isFirstAppLaunch
)
InAppPurchaseLoggerManager.filterPurchaseLogging(
InAppPurchaseBillingClientWrapperV5V7.subsPurchaseDetailsMap,
InAppPurchaseBillingClientWrapperV5V7.productDetailsMap,
true,
packageName,
billingClientVersion
billingClientVersion,
isFirstAppLaunch
)
InAppPurchaseBillingClientWrapperV5V7.iapPurchaseDetailsMap.clear()
InAppPurchaseBillingClientWrapperV5V7.subsPurchaseDetailsMap.clear()
}
if (isFirstAppLaunch) {
setAppHasBeenLaunched()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ import com.facebook.FacebookSdk.getApplicationContext
import com.facebook.appevents.internal.AutomaticAnalyticsLogger.logPurchase
import com.facebook.appevents.internal.Constants
import com.facebook.internal.instrument.crashshield.AutoHandleExceptions
import java.lang.Exception
import java.util.HashMap
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.CopyOnWriteArraySet
import org.json.JSONObject
import kotlin.Exception
import kotlin.math.max
import kotlin.math.min

Expand All @@ -38,9 +38,10 @@ object InAppPurchaseLoggerManager {

private const val IAP_CACHE_GPBLV2V7 = "com.facebook.internal.iap.IAP_CACHE_GPBLV2V7"
private const val CACHED_PURCHASES_KEY = "PURCHASE_DETAILS_SET"
private const val APP_HAS_BEEN_LAUNCHED_KEY = "APP_HAS_BEEN_LAUNCHED_KEY"
private const val TIME_OF_LAST_LOGGED_PURCHASE_KEY = "TIME_OF_LAST_LOGGED_PURCHASE"
private const val TIME_OF_LAST_LOGGED_SUBSCRIPTION_KEY = "TIME_OF_LAST_LOGGED_SUBSCRIPTION"
private var firstTimeLoggingIAP = false
private var oldCacheHistoryExists = false

private fun readOldCaches() {
// clear cached purchases logged by lib 1
Expand All @@ -53,14 +54,13 @@ object InAppPurchaseLoggerManager {
cachedSkuSharedPref.edit().clear().apply()
cachedPurchaseSharedPref.edit().clear().apply()


sharedPreferences =
getApplicationContext().getSharedPreferences(
IAP_CACHE_OLD,
Context.MODE_PRIVATE
)
if (sharedPreferences.contains(CACHED_PURCHASES_KEY)) {
firstTimeLoggingIAP = true
oldCacheHistoryExists = true
cachedPurchaseSet.addAll(
sharedPreferences.getStringSet(CACHED_PURCHASES_KEY, hashSetOf()) ?: hashSetOf()
)
Expand All @@ -70,30 +70,56 @@ object InAppPurchaseLoggerManager {
val splitPurchase = purchaseHistory.split(";", limit = 2)
cachedPurchaseMap[splitPurchase[0]] = splitPurchase[1].toLong()
}

}


// clear cached purchases logged by lib2 - lib4 in the old implementation of IAP auto-logging
sharedPreferences.edit().clear().apply()
}

@JvmStatic
fun getIsFirstAppLaunch(): Boolean {
val iapCache =
getApplicationContext().getSharedPreferences(
IAP_CACHE_GPBLV2V7,
Context.MODE_PRIVATE
)
return !iapCache.contains(APP_HAS_BEEN_LAUNCHED_KEY)
}

@JvmStatic
fun setAppHasBeenLaunched() {
val iapCache =
getApplicationContext().getSharedPreferences(
IAP_CACHE_GPBLV2V7,
Context.MODE_PRIVATE
)
try {
iapCache.edit()
.putBoolean(APP_HAS_BEEN_LAUNCHED_KEY, true)
.apply()
} catch (e: Exception) {
val x = 1
}
}

@JvmStatic
fun filterPurchaseLogging(
purchaseDetailsMap: MutableMap<String, JSONObject>,
skuDetailsMap: Map<String, JSONObject?>,
isSubscription: Boolean,
packageName: String,
billingClientVersion: InAppPurchaseUtils.BillingClientVersion

billingClientVersion: InAppPurchaseUtils.BillingClientVersion,
isFirstAppLaunch: Boolean
) {
readOldCaches()
val loggingReadyMap: Map<String, String> =
constructLoggingReadyMap(
cacheDeDupPurchase(purchaseDetailsMap, isSubscription),
skuDetailsMap,
packageName
)
logPurchases(loggingReadyMap, isSubscription, billingClientVersion)
val deduped = cacheDeDupPurchase(purchaseDetailsMap, isSubscription)
val loggingReady = constructLoggingReadyMap(
deduped,
skuDetailsMap,
packageName
)
logPurchases(loggingReady, isSubscription, billingClientVersion, isFirstAppLaunch)
}

@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
Expand All @@ -111,11 +137,19 @@ object InAppPurchaseLoggerManager {
private fun logPurchases(
purchaseDetailsMap: Map<String, String>,
isSubscription: Boolean,
billingClientVersion: InAppPurchaseUtils.BillingClientVersion
billingClientVersion: InAppPurchaseUtils.BillingClientVersion,
isFirstAppLaunch: Boolean
) {
for ((purchaseDetails, skuDetails) in purchaseDetailsMap) {
logPurchase(purchaseDetails, skuDetails, isSubscription, billingClientVersion)
logPurchase(
purchaseDetails,
skuDetails,
isSubscription,
billingClientVersion,
isFirstAppLaunch
)
}

}

@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
Expand All @@ -130,7 +164,7 @@ object InAppPurchaseLoggerManager {
)
var timeOfLatestNewlyLoggedPurchase: Long = 0
var timeOfLastLoggedPurchase: Long = 0
if (firstTimeLoggingIAP) {
if (oldCacheHistoryExists) {
timeOfLastLoggedPurchase = getTimeOfNewestPurchaseInOldCache()
} else {
if (isSubscription) {
Expand Down Expand Up @@ -159,7 +193,7 @@ object InAppPurchaseLoggerManager {
/* swallow */
}
}
if (firstTimeLoggingIAP) {
if (oldCacheHistoryExists) {
iapCache.edit()
.putLong(TIME_OF_LAST_LOGGED_SUBSCRIPTION_KEY, timeOfLatestNewlyLoggedPurchase)
.apply()
Expand All @@ -177,7 +211,7 @@ object InAppPurchaseLoggerManager {
.apply()
}
}
firstTimeLoggingIAP = false
oldCacheHistoryExists = false
return HashMap(purchaseDetailsMap)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ object AutomaticAnalyticsLogger {
purchase: String,
skuDetails: String,
isSubscription: Boolean,
billingClientVersion: InAppPurchaseUtils.BillingClientVersion?
billingClientVersion: InAppPurchaseUtils.BillingClientVersion?,
isFirstAppLaunch: Boolean = false
) {
if (!isImplicitPurchaseLoggingEnabled()) {
return
Expand All @@ -104,14 +105,20 @@ object AutomaticAnalyticsLogger {
FacebookSdk.getApplicationId(),
false
)
var eventName = AppEventsConstants.EVENT_NAME_PURCHASED
if (logAsSubs) {
eventName =
if (InAppPurchaseEventManager.hasFreeTrialPeirod(skuDetails)) {
AppEventsConstants.EVENT_NAME_START_TRIAL
} else {
AppEventsConstants.EVENT_NAME_SUBSCRIBE
}
val eventName = if (logAsSubs) {
if (isFirstAppLaunch) {
Constants.EVENT_NAME_SUBSCRIPTION_RESTORED
} else if (InAppPurchaseEventManager.hasFreeTrialPeirod(skuDetails)) {
AppEventsConstants.EVENT_NAME_START_TRIAL
} else {
AppEventsConstants.EVENT_NAME_SUBSCRIBE
}
} else {
if (isFirstAppLaunch) {
Constants.EVENT_NAME_PURCHASE_RESTORED
} else {
AppEventsConstants.EVENT_NAME_PURCHASED
}
}
val dedupeParameters =
if (isSubscription &&
Expand All @@ -131,7 +138,7 @@ object AutomaticAnalyticsLogger {
)
loggingParameters[0].param = combinedParameters ?: Bundle()

if (logAsSubs) {
if (eventName != AppEventsConstants.EVENT_NAME_PURCHASED) {
internalAppEventsLogger.logEventImplicitly(
eventName,
loggingParameters[0].purchaseAmount,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ package com.facebook.appevents.internal
object Constants {
const val LOG_TIME_APP_EVENT_KEY = "_logTime"
const val EVENT_NAME_EVENT_KEY = "_eventName"
const val EVENT_NAME_PURCHASE_RESTORED = "fb_mobile_purchase_restored"
const val EVENT_NAME_SUBSCRIPTION_RESTORED = "SubscriptionRestore"

// The following are for Automatic Analytics events and parameters
const val AA_TIME_SPENT_EVENT_NAME = "fb_aa_time_spent_on_view"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,8 @@ class InAppPurchaseAutoLoggerTest : FacebookPowerMockTestCase() {
any(),
any(),
any(),
any()
any(),
any(),
)
).thenAnswer {
logPurchaseCallTimes++
Expand Down Expand Up @@ -196,6 +197,7 @@ class InAppPurchaseAutoLoggerTest : FacebookPowerMockTestCase() {
any(),
any(),
any(),
any(),
any()
)
).thenAnswer {
Expand Down Expand Up @@ -245,6 +247,7 @@ class InAppPurchaseAutoLoggerTest : FacebookPowerMockTestCase() {
any(),
any(),
any(),
any(),
any()
)
).thenAnswer {
Expand Down Expand Up @@ -308,7 +311,8 @@ class InAppPurchaseAutoLoggerTest : FacebookPowerMockTestCase() {
any(),
any(),
any(),
any()
any(),
any(),
)
).thenAnswer {
logPurchaseCallTimes++
Expand Down Expand Up @@ -369,6 +373,7 @@ class InAppPurchaseAutoLoggerTest : FacebookPowerMockTestCase() {
any(),
any(),
any(),
any(),
any()
)
).thenAnswer {
Expand Down
Loading

0 comments on commit e44a8b3

Please sign in to comment.