diff --git a/build.gradle b/build.gradle index f8f5143a..18d5d471 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ import io.gitlab.arturbosch.detekt.DetektCreateBaselineTask buildscript { ext { release = [ - versionName: "7.4.1", + versionName: "7.5.0", versionCode: 1 ] } diff --git a/config/detekt/baseline.xml b/config/detekt/baseline.xml index a91d68c2..65ec9b6a 100644 --- a/config/detekt/baseline.xml +++ b/config/detekt/baseline.xml @@ -270,6 +270,7 @@ TooManyFunctions:QProductCenterManager.kt$QProductCenterManager : PurchasesListenerUserStateProvider TooManyFunctions:QRemoteConfigManager.kt$QRemoteConfigManager TooManyFunctions:QRepository.kt$QRepository + TooManyFunctions:QUserPropertiesManager.kt$QUserPropertiesManager : FacebookAttributionListener TooManyFunctions:Qonversion.kt$Qonversion TooManyFunctions:QonversionBillingService.kt$QonversionBillingService : PurchasesUpdatedListenerConnectionListenerBillingService TooManyFunctions:QonversionInternal.kt$QonversionInternal : QonversionLifecycleDelegateAppStateProvider diff --git a/fastlane/report.xml b/fastlane/report.xml index 62c5fd4e..da5ada95 100644 --- a/fastlane/report.xml +++ b/fastlane/report.xml @@ -5,7 +5,7 @@ - + diff --git a/sdk/src/main/java/com/qonversion/android/sdk/internal/QRemoteConfigManager.kt b/sdk/src/main/java/com/qonversion/android/sdk/internal/QRemoteConfigManager.kt index 4d537b65..df770515 100644 --- a/sdk/src/main/java/com/qonversion/android/sdk/internal/QRemoteConfigManager.kt +++ b/sdk/src/main/java/com/qonversion/android/sdk/internal/QRemoteConfigManager.kt @@ -5,6 +5,7 @@ import com.qonversion.android.sdk.dto.QRemoteConfigList import com.qonversion.android.sdk.dto.QonversionError import com.qonversion.android.sdk.internal.provider.UserStateProvider import com.qonversion.android.sdk.internal.services.QRemoteConfigService +import com.qonversion.android.sdk.listeners.QonversionEmptyCallback import com.qonversion.android.sdk.listeners.QonversionExperimentAttachCallback import com.qonversion.android.sdk.listeners.QonversionRemoteConfigCallback import com.qonversion.android.sdk.listeners.QonversionRemoteConfigListCallback @@ -31,6 +32,7 @@ internal class QRemoteConfigManager @Inject constructor( lateinit var userStateProvider: UserStateProvider private var loadingStates = mutableMapOf() private val listRequests = mutableListOf() + lateinit var userPropertiesManager: QUserPropertiesManager fun handlePendingRequests() { loadingStates.filter { it.value.callbacks.isNotEmpty() } @@ -77,14 +79,19 @@ internal class QRemoteConfigManager @Inject constructor( loadingState.isInProgress = true loadingState.loadedConfig = null - remoteConfigService.loadRemoteConfig(contextKey, object : QonversionRemoteConfigCallback { - override fun onSuccess(remoteConfig: QRemoteConfig) { - loadingState.loadedConfig = remoteConfig - fireToCallbacks(contextKey) { onSuccess(remoteConfig) } - } - override fun onError(error: QonversionError) { - fireToCallbacks(contextKey) { onError(error) } + userPropertiesManager.forceSendProperties(object : QonversionEmptyCallback { + override fun onComplete() { + remoteConfigService.loadRemoteConfig(contextKey, object : QonversionRemoteConfigCallback { + override fun onSuccess(remoteConfig: QRemoteConfig) { + loadingState.loadedConfig = remoteConfig + fireToCallbacks(contextKey) { onSuccess(remoteConfig) } + } + + override fun onError(error: QonversionError) { + fireToCallbacks(contextKey) { onError(error) } + } + }) } }) } @@ -106,11 +113,15 @@ internal class QRemoteConfigManager @Inject constructor( return } - remoteConfigService.loadRemoteConfigs( - contextKeys, - includeEmptyContextKey, - getRemoteConfigListCallbackWrapper(callback), - ) + userPropertiesManager.forceSendProperties(object : QonversionEmptyCallback { + override fun onComplete() { + remoteConfigService.loadRemoteConfigs( + contextKeys, + includeEmptyContextKey, + getRemoteConfigListCallbackWrapper(callback), + ) + } + }) } fun loadRemoteConfigList(callback: QonversionRemoteConfigListCallback) { @@ -119,7 +130,11 @@ internal class QRemoteConfigManager @Inject constructor( return } - remoteConfigService.loadRemoteConfigs(getRemoteConfigListCallbackWrapper(callback)) + userPropertiesManager.forceSendProperties(object : QonversionEmptyCallback { + override fun onComplete() { + remoteConfigService.loadRemoteConfigs(getRemoteConfigListCallbackWrapper(callback)) + } + }) } fun attachUserToExperiment(experimentId: String, groupId: String, callback: QonversionExperimentAttachCallback) { diff --git a/sdk/src/main/java/com/qonversion/android/sdk/internal/QUserPropertiesManager.kt b/sdk/src/main/java/com/qonversion/android/sdk/internal/QUserPropertiesManager.kt index 6148b4d1..e78e98dd 100644 --- a/sdk/src/main/java/com/qonversion/android/sdk/internal/QUserPropertiesManager.kt +++ b/sdk/src/main/java/com/qonversion/android/sdk/internal/QUserPropertiesManager.kt @@ -14,6 +14,7 @@ import com.qonversion.android.sdk.internal.logger.Logger import com.qonversion.android.sdk.internal.provider.AppStateProvider import com.qonversion.android.sdk.internal.repository.QRepository import com.qonversion.android.sdk.internal.storage.PropertiesStorage +import com.qonversion.android.sdk.listeners.QonversionEmptyCallback import com.qonversion.android.sdk.listeners.QonversionUserPropertiesCallback import javax.inject.Inject @@ -31,6 +32,7 @@ internal class QUserPropertiesManager @Inject internal constructor( private var isSendingScheduled = false private var retryDelay = PROPERTY_UPLOAD_MIN_DELAY private var retriesCounter = 0 + private var completions = mutableListOf() companion object { private const val LOOPER_THREAD_NAME = "userPropertiesThread" @@ -67,19 +69,27 @@ internal class QUserPropertiesManager @Inject internal constructor( setCustomUserProperty(QUserPropertyKey.FacebookAttribution.userPropertyCode, id) } - fun forceSendProperties() { + public fun forceSendProperties(callback: QonversionEmptyCallback? = null) { if (isRequestInProgress) { + if (callback != null) { + completions.add(callback) + } return } val properties = propertiesStorage.getProperties() if (properties.isNotEmpty()) { + if (callback != null) { + completions.add(callback) + } + isRequestInProgress = true isSendingScheduled = false repository.sendProperties(properties, onSuccess = { result -> + fireCallbacks() result.propertyErrors.forEach { propertyError -> logger.error("Failed to save property ${propertyError.key}: ${propertyError.error}") } @@ -92,6 +102,7 @@ internal class QUserPropertiesManager @Inject internal constructor( propertiesStorage.clear(properties) }, onError = { + fireCallbacks() isRequestInProgress = false if (it.code === QonversionErrorCode.InvalidClientUid) { @@ -108,9 +119,18 @@ internal class QUserPropertiesManager @Inject internal constructor( retryPropertiesRequest() } }) + } else { + callback?.onComplete() } } + private fun fireCallbacks() { + val callbacks = completions.toList() + completions.clear() + + callbacks.forEach { callback -> callback.onComplete() } + } + @VisibleForTesting fun retryPropertiesRequest() { retriesCounter++ diff --git a/sdk/src/main/java/com/qonversion/android/sdk/internal/QonversionInternal.kt b/sdk/src/main/java/com/qonversion/android/sdk/internal/QonversionInternal.kt index 35f0e7e6..dd74687c 100644 --- a/sdk/src/main/java/com/qonversion/android/sdk/internal/QonversionInternal.kt +++ b/sdk/src/main/java/com/qonversion/android/sdk/internal/QonversionInternal.kt @@ -104,6 +104,8 @@ internal class QonversionInternal( userPropertiesManager.productCenterManager = productCenterManager userPropertiesManager.sendFacebookAttribution() + remoteConfigManager.userPropertiesManager = userPropertiesManager + val lifecycleHandler = AppLifecycleHandler(this) postToMainThread { ProcessLifecycleOwner.get().lifecycle.addObserver(lifecycleHandler) } diff --git a/sdk/src/main/java/com/qonversion/android/sdk/listeners/QonversionCallback.kt b/sdk/src/main/java/com/qonversion/android/sdk/listeners/QonversionCallback.kt index 48deeeca..6ec342b3 100644 --- a/sdk/src/main/java/com/qonversion/android/sdk/listeners/QonversionCallback.kt +++ b/sdk/src/main/java/com/qonversion/android/sdk/listeners/QonversionCallback.kt @@ -70,3 +70,8 @@ interface QonversionUserPropertiesCallback { fun onSuccess(userProperties: QUserProperties) fun onError(error: QonversionError) } + +interface QonversionEmptyCallback { + + fun onComplete() +}