From bef1b21d3c1fcb31081cd4431518ff5f100f5d97 Mon Sep 17 00:00:00 2001 From: Kamo Spertsyan Date: Mon, 6 May 2024 13:29:36 +0300 Subject: [PATCH 1/2] Added identify method with callback (#582) * Added identify method with callback * Detekt fixes --- config/detekt/baseline.xml | 1 + .../com/qonversion/android/sdk/Qonversion.kt | 7 ++ .../android/sdk/internal/QIdentityManager.kt | 2 +- .../sdk/internal/QProductCenterManager.kt | 77 +++++++++++++++---- .../sdk/internal/QonversionInternal.kt | 16 +++- 5 files changed, 87 insertions(+), 16 deletions(-) diff --git a/config/detekt/baseline.xml b/config/detekt/baseline.xml index 6631e9c1..a91d68c2 100644 --- a/config/detekt/baseline.xml +++ b/config/detekt/baseline.xml @@ -226,6 +226,7 @@ ReturnCount:ExceptionHandler.kt$ExceptionHandler$private fun isQonversionException(exception: Throwable): Boolean ReturnCount:QExceptionManager.kt$QExceptionManager$private fun getContentOfCrashReport(filename: String): CrashRequest.ExceptionInfo? ReturnCount:QProductCenterManager.kt$QProductCenterManager$@Synchronized private fun executeProductsBlocks(loadStoreProductsError: QonversionError? = null) + ReturnCount:QProductCenterManager.kt$QProductCenterManager$fun identify(identityId: String, callback: QonversionUserCallback? = null) ReturnCount:ScreenPresenter.kt$ScreenPresenter$override fun shouldOverrideUrlLoading(url: String?): Boolean SpacingAroundColon:com.qonversion.android.sdk.internal.requests.ProviderDataRequestTest.kt:45 SpacingAroundCurly:com.qonversion.android.sdk.automations.internal.QAutomationsManagerTest.kt:263 diff --git a/sdk/src/main/java/com/qonversion/android/sdk/Qonversion.kt b/sdk/src/main/java/com/qonversion/android/sdk/Qonversion.kt index 333b8a0f..e4f993b7 100644 --- a/sdk/src/main/java/com/qonversion/android/sdk/Qonversion.kt +++ b/sdk/src/main/java/com/qonversion/android/sdk/Qonversion.kt @@ -227,6 +227,13 @@ interface Qonversion { */ fun identify(userID: String) + /** + * Call this function to link a user to his unique ID in your system and share purchase data. + * @param userID - unique user ID in your system + * @param callback - callback that will be called when response is received + */ + fun identify(userID: String, callback: QonversionUserCallback) + /** * Call this function to unlink a user from his unique ID in your system and his purchase data. */ diff --git a/sdk/src/main/java/com/qonversion/android/sdk/internal/QIdentityManager.kt b/sdk/src/main/java/com/qonversion/android/sdk/internal/QIdentityManager.kt index c21b9c34..3a7dd495 100644 --- a/sdk/src/main/java/com/qonversion/android/sdk/internal/QIdentityManager.kt +++ b/sdk/src/main/java/com/qonversion/android/sdk/internal/QIdentityManager.kt @@ -6,7 +6,7 @@ import com.qonversion.android.sdk.internal.services.QUserInfoService import javax.inject.Inject interface IdentityManagerCallback { - fun onSuccess(identityID: String) + fun onSuccess(qonversionUid: String) fun onError(error: QonversionError) } diff --git a/sdk/src/main/java/com/qonversion/android/sdk/internal/QProductCenterManager.kt b/sdk/src/main/java/com/qonversion/android/sdk/internal/QProductCenterManager.kt index 343cfd2b..ff6b01f3 100644 --- a/sdk/src/main/java/com/qonversion/android/sdk/internal/QProductCenterManager.kt +++ b/sdk/src/main/java/com/qonversion/android/sdk/internal/QProductCenterManager.kt @@ -83,6 +83,7 @@ internal class QProductCenterManager internal constructor( private var processingPartnersIdentityId: String? = null private var pendingPartnersIdentityId: String? = null + private var pendingIdentityCallbacks = mutableMapOf>() private var unhandledLogoutAvailable: Boolean = false private var installDate: Long = 0 @@ -163,24 +164,30 @@ internal class QProductCenterManager internal constructor( }) } - fun identify(userID: String) { - if (processingPartnersIdentityId == userID || identityManager.currentPartnersIdentityId == userID) { + fun identify(identityId: String, callback: QonversionUserCallback? = null) { + if (identityManager.currentPartnersIdentityId == identityId) { + callback?.let { getUserInfo(callback) } + return + } + + addIdentityCallback(identityId, callback) + if (processingPartnersIdentityId == identityId) { return } unhandledLogoutAvailable = false - pendingPartnersIdentityId = userID + pendingPartnersIdentityId = identityId if (!isLaunchingFinished || isRestoreInProgress) { return } - processingPartnersIdentityId = userID + processingPartnersIdentityId = identityId if (launchError != null) { - val callback = object : QonversionLaunchCallback { + val launchCallback = object : QonversionLaunchCallback { override fun onSuccess(launchResult: QLaunchResult) { - processIdentity(userID) + processIdentity(identityId) } override fun onError(error: QonversionError, httpCode: Int?) { @@ -191,28 +198,37 @@ internal class QProductCenterManager internal constructor( } } - val initRequestData = InitRequestData(installDate, advertisingID, callback = callback) + val initRequestData = InitRequestData(installDate, advertisingID, callback = launchCallback) repository.init(initRequestData) } else { - processIdentity(userID) + processIdentity(identityId) } } - private fun processIdentity(userID: String) { + private fun processIdentity(identityId: String) { val currentUserID = userInfoService.obtainUserID() - identityManager.identify(userID, object : IdentityManagerCallback { - override fun onSuccess(identityID: String) { + identityManager.identify(identityId, object : IdentityManagerCallback { + override fun onSuccess(qonversionUid: String) { pendingPartnersIdentityId = null processingPartnersIdentityId = null - if (currentUserID == identityID) { + if (currentUserID == qonversionUid) { handlePendingRequests() + fireIdentitySuccess(identityId) } else { - internalConfig.uid = identityID + internalConfig.uid = qonversionUid remoteConfigManager.onUserUpdate() launchResultCache.clearPermissionsCache() - launch() + launch(object : QonversionLaunchCallback { + override fun onSuccess(launchResult: QLaunchResult) { + fireIdentitySuccess(identityId) + } + + override fun onError(error: QonversionError, httpCode: Int?) { + fireIdentityError(identityId, error) + } + }) } } @@ -221,6 +237,8 @@ internal class QProductCenterManager internal constructor( executeEntitlementsBlock(error) remoteConfigManager.userChangingRequestFailedWithError(error) + + fireIdentityError(identityId, error) } }) } @@ -1005,4 +1023,35 @@ internal class QProductCenterManager internal constructor( httpCode?.isInternalServerError() == true ) } + + private fun addIdentityCallback(identityId: String, callback: QonversionUserCallback?) { + if (callback == null) { + return + } + + val callbacks = pendingIdentityCallbacks[identityId] ?: mutableListOf() + callbacks.add(callback) + pendingIdentityCallbacks[identityId] = callbacks + } + + private fun fireIdentitySuccess(identityId: String) { + val callbacks = pendingIdentityCallbacks[identityId] ?: return + pendingIdentityCallbacks[identityId] = mutableListOf() + + getUserInfo(object : QonversionUserCallback { + override fun onSuccess(user: QUser) { + callbacks.forEach { it.onSuccess(user) } + } + + override fun onError(error: QonversionError) { + callbacks.forEach { it.onError(error) } + } + }) + } + + private fun fireIdentityError(identityId: String, error: QonversionError) { + val callbacks = pendingIdentityCallbacks[identityId] ?: return + pendingIdentityCallbacks[identityId] = mutableListOf() + callbacks.forEach { it.onError(error) } + } } 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 781452bd..5a4778b5 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 @@ -13,6 +13,7 @@ import com.qonversion.android.sdk.dto.QPurchaseUpdateModel import com.qonversion.android.sdk.dto.entitlements.QEntitlement import com.qonversion.android.sdk.dto.QRemoteConfig import com.qonversion.android.sdk.dto.QRemoteConfigList +import com.qonversion.android.sdk.dto.QUser import com.qonversion.android.sdk.dto.properties.QUserPropertyKey import com.qonversion.android.sdk.dto.QonversionError import com.qonversion.android.sdk.dto.eligibility.QEligibility @@ -303,12 +304,16 @@ internal class QonversionInternal( productCenterManager.identify(userID) } + override fun identify(userID: String, callback: QonversionUserCallback) { + productCenterManager.identify(userID, callback) + } + override fun logout() { productCenterManager.logout() } override fun userInfo(callback: QonversionUserCallback) { - productCenterManager.getUserInfo(callback) + productCenterManager.getUserInfo(mainUserCallback(callback)) } override fun attribution(data: Map, provider: QAttributionProvider) { @@ -341,6 +346,15 @@ internal class QonversionInternal( postToMainThread { callback.onError(error) } } + private fun mainUserCallback(callback: QonversionUserCallback): QonversionUserCallback = + object : QonversionUserCallback { + override fun onSuccess(user: QUser) = + postToMainThread { callback.onSuccess(user) } + + override fun onError(error: QonversionError) = + postToMainThread { callback.onError(error) } + } + private fun postToMainThread(runnable: () -> Unit) { if (Looper.myLooper() == Looper.getMainLooper()) { runnable() From f1cfa45e0bc0815baa3c27d7b71739a98c4d8ea9 Mon Sep 17 00:00:00 2001 From: SpertsyanKM Date: Mon, 6 May 2024 10:30:39 +0000 Subject: [PATCH 2/2] [create-pull-request] automated change --- build.gradle | 2 +- fastlane/report.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 2683f45f..1a400598 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ import io.gitlab.arturbosch.detekt.DetektCreateBaselineTask buildscript { ext { release = [ - versionName: "7.3.4", + versionName: "7.4.0", versionCode: 1 ] } diff --git a/fastlane/report.xml b/fastlane/report.xml index ab39277f..e963cf14 100644 --- a/fastlane/report.xml +++ b/fastlane/report.xml @@ -5,7 +5,7 @@ - +