From 7f82a091bc1bb853827501a6e3a4e0c1a0731efc Mon Sep 17 00:00:00 2001 From: Elizaveta Nevostrueva Date: Wed, 5 May 2021 09:54:25 +0300 Subject: [PATCH 1/4] Started investigation track visit with source --- sdk/build.gradle | 2 + .../java/cloud/mindbox/mobile_sdk/Mindbox.kt | 21 ++++++-- .../mobile_sdk/managers/LifecycleManager.kt | 52 ++++++++++++++++--- 3 files changed, 63 insertions(+), 12 deletions(-) diff --git a/sdk/build.gradle b/sdk/build.gradle index 88428f93c..f2da050aa 100644 --- a/sdk/build.gradle +++ b/sdk/build.gradle @@ -140,4 +140,6 @@ dependencies { // dex implementation "androidx.multidex:multidex:2.0.1" + implementation "androidx.lifecycle:lifecycle-process:2.3.1" + } \ No newline at end of file diff --git a/sdk/src/main/java/cloud/mindbox/mobile_sdk/Mindbox.kt b/sdk/src/main/java/cloud/mindbox/mobile_sdk/Mindbox.kt index ffdbd8dc8..4596745a9 100644 --- a/sdk/src/main/java/cloud/mindbox/mobile_sdk/Mindbox.kt +++ b/sdk/src/main/java/cloud/mindbox/mobile_sdk/Mindbox.kt @@ -2,6 +2,7 @@ package cloud.mindbox.mobile_sdk import android.app.Application import android.content.Context +import androidx.lifecycle.ProcessLifecycleOwner import cloud.mindbox.mobile_sdk.logger.Level import cloud.mindbox.mobile_sdk.logger.MindboxLogger import cloud.mindbox.mobile_sdk.managers.* @@ -24,6 +25,7 @@ object Mindbox { private val mindboxScope = CoroutineScope(Default + mindboxJob) private val deviceUuidCallbacks = ConcurrentHashMap Unit>() private val fmsTokenCallbacks = ConcurrentHashMap Unit>() + private lateinit var lifecycleManager: LifecycleManager /** * Subscribe to gets token of Firebase Messaging Service used by SDK @@ -190,13 +192,22 @@ object Mindbox { MindboxEventManager.sendEventsIfExist(context) } sendTrackVisitEvent(context, configuration.endpointId) + } - // Handle back app in foreground - val lifecycleManager = LifecycleManager { - sendTrackVisitEvent(context, configuration.endpointId) + // Handle back app in foreground + (context.applicationContext as? Application)?.apply { + if (!Mindbox::lifecycleManager.isInitialized) { + lifecycleManager = LifecycleManager { + sendTrackVisitEvent(context, configuration.endpointId) + } + } else { + unregisterComponentCallbacks(lifecycleManager) + unregisterActivityLifecycleCallbacks(lifecycleManager) + ProcessLifecycleOwner.get().lifecycle.removeObserver(lifecycleManager) } - (context.applicationContext as? Application) - ?.registerActivityLifecycleCallbacks(lifecycleManager) + registerComponentCallbacks(lifecycleManager) + registerActivityLifecycleCallbacks(lifecycleManager) + ProcessLifecycleOwner.get().lifecycle.addObserver(lifecycleManager) } }.returnOnException { } } diff --git a/sdk/src/main/java/cloud/mindbox/mobile_sdk/managers/LifecycleManager.kt b/sdk/src/main/java/cloud/mindbox/mobile_sdk/managers/LifecycleManager.kt index 5ce3d9641..731b667e6 100644 --- a/sdk/src/main/java/cloud/mindbox/mobile_sdk/managers/LifecycleManager.kt +++ b/sdk/src/main/java/cloud/mindbox/mobile_sdk/managers/LifecycleManager.kt @@ -2,23 +2,37 @@ package cloud.mindbox.mobile_sdk.managers import android.app.Activity import android.app.Application +import android.content.ComponentCallbacks2 +import android.content.res.Configuration import android.os.Bundle +import android.util.Log +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleObserver +import androidx.lifecycle.OnLifecycleEvent internal class LifecycleManager( private val onAppStarted: () -> Unit -) : Application.ActivityLifecycleCallbacks { +) : Application.ActivityLifecycleCallbacks, ComponentCallbacks2, LifecycleObserver { - private var currentActivity: Activity? = null + var currentActivity: Activity? = null - override fun onActivityCreated(activity: Activity, p1: Bundle?) { + private var isConfigurationChanged = false + override fun onActivityCreated(activity: Activity, p1: Bundle?) { + Log.d("______", "created cur $currentActivity act $activity") } override fun onActivityStarted(activity: Activity) { - if (currentActivity?.javaClass?.name == activity.javaClass.name) { - onAppStarted() - } else { - currentActivity = activity + Log.d("______", "cur $currentActivity act $activity action ${activity.intent.action} extas ${activity.intent.extras} data ${activity.intent.data} cat ${activity.intent.categories} schema ${activity.intent.scheme}") +activity.intent.scheme + + when { + isConfigurationChanged -> isConfigurationChanged = false + currentActivity?.javaClass?.name == activity.javaClass.name -> { + Log.d("______", "app started") + onAppStarted() + } + else -> currentActivity = activity } } @@ -34,6 +48,7 @@ internal class LifecycleManager( if (currentActivity == null) { currentActivity = activity } + Log.d("______", "stopped cur $currentActivity act $activity action ${activity.intent.action} extas ${activity.intent.extras} data ${activity.intent.data} cat ${activity.intent.categories}") } override fun onActivitySaveInstanceState(activity: Activity, p1: Bundle) { @@ -44,4 +59,27 @@ internal class LifecycleManager( } + override fun onConfigurationChanged(newConfig: Configuration) { + Log.d("______", "onConfigurationChanged") + isConfigurationChanged = true + } + + override fun onLowMemory() { + + } + + override fun onTrimMemory(level: Int) { + + } + + @OnLifecycleEvent(Lifecycle.Event.ON_STOP) + fun onAppMovedToBackground() { + Log.d("_______", "App in background $currentActivity action ${currentActivity?.intent?.action} extas ${currentActivity?.intent?.extras} data ${currentActivity?.intent?.data} cat ${currentActivity?.intent?.categories}") + } + + @OnLifecycleEvent(Lifecycle.Event.ON_START) + fun onAppMovedToForeground() { + Log.d("_______", "App in foreground $currentActivity action ${currentActivity?.intent?.action} extas ${currentActivity?.intent?.extras} data ${currentActivity?.intent?.data} cat ${currentActivity?.intent?.categories}") + } + } From af884b5a70bfb60a5661b69e94a2a10006e5f41c Mon Sep 17 00:00:00 2001 From: Elizaveta Nevostrueva Date: Tue, 11 May 2021 18:35:38 +0300 Subject: [PATCH 2/4] Started trackvisit p2 implementation --- .../java/cloud/mindbox/mobile_sdk/Mindbox.kt | 32 +++++--- .../mobile_sdk/managers/LifecycleManager.kt | 73 +++++++++++++------ .../mindbox/mobile_sdk/models/InitData.kt | 13 +++- 3 files changed, 85 insertions(+), 33 deletions(-) diff --git a/sdk/src/main/java/cloud/mindbox/mobile_sdk/Mindbox.kt b/sdk/src/main/java/cloud/mindbox/mobile_sdk/Mindbox.kt index 4596745a9..8e3eb7219 100644 --- a/sdk/src/main/java/cloud/mindbox/mobile_sdk/Mindbox.kt +++ b/sdk/src/main/java/cloud/mindbox/mobile_sdk/Mindbox.kt @@ -1,5 +1,6 @@ package cloud.mindbox.mobile_sdk +import android.app.Activity import android.app.Application import android.content.Context import androidx.lifecycle.ProcessLifecycleOwner @@ -19,6 +20,11 @@ import java.util.concurrent.TimeUnit object Mindbox { + /** + * Used for determination app open from push + */ + const val IS_OPENED_FROM_PUSH_BUNDLE_KEY = "isOpenedFromPush" + private const val OPERATION_NAME_REGEX = "^[A-Za-z0-9-\\.]{1,249}\$" private val mindboxJob = Job() @@ -162,6 +168,8 @@ object Mindbox { * * @param context used to initialize the main tools * @param configuration contains the data that is needed to connect to the Mindbox + * + * @throws IllegalStateException */ fun init( context: Context, @@ -191,15 +199,12 @@ object Mindbox { updateAppInfo(context) MindboxEventManager.sendEventsIfExist(context) } - sendTrackVisitEvent(context, configuration.endpointId) } // Handle back app in foreground (context.applicationContext as? Application)?.apply { if (!Mindbox::lifecycleManager.isInitialized) { - lifecycleManager = LifecycleManager { - sendTrackVisitEvent(context, configuration.endpointId) - } + lifecycleManager = LifecycleManager(context as? Activity) } else { unregisterComponentCallbacks(lifecycleManager) unregisterActivityLifecycleCallbacks(lifecycleManager) @@ -321,14 +326,22 @@ object Mindbox { }.logOnException() } - private fun sendTrackVisitEvent(context: Context, endpointId: String) { + internal fun sendTrackVisitEvent( + context: Context, + @TrackVisitSource source: String? = null, + requestUrl: String? = null + ) = runCatching { + val applicationContext = context.applicationContext + val endpointId = DbManager.getConfigurations()?.endpointId ?: return val trackVisitData = TrackVisitData( ianaTimeZone = TimeZone.getDefault().id, - endpointId = endpointId + endpointId = endpointId, + source = source, + requestUrl = requestUrl ) - MindboxEventManager.appStarted(context, trackVisitData) - } + MindboxEventManager.appStarted(applicationContext, trackVisitData) + }.logOnException() private fun deliverDeviceUuid(deviceUuid: String) { Executors.newSingleThreadScheduledExecutor().schedule({ @@ -347,4 +360,5 @@ object Mindbox { } }, 1, TimeUnit.SECONDS) } -} \ No newline at end of file + +} diff --git a/sdk/src/main/java/cloud/mindbox/mobile_sdk/managers/LifecycleManager.kt b/sdk/src/main/java/cloud/mindbox/mobile_sdk/managers/LifecycleManager.kt index 731b667e6..74c863bcd 100644 --- a/sdk/src/main/java/cloud/mindbox/mobile_sdk/managers/LifecycleManager.kt +++ b/sdk/src/main/java/cloud/mindbox/mobile_sdk/managers/LifecycleManager.kt @@ -3,37 +3,45 @@ package cloud.mindbox.mobile_sdk.managers import android.app.Activity import android.app.Application import android.content.ComponentCallbacks2 +import android.content.Intent import android.content.res.Configuration import android.os.Bundle -import android.util.Log import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleObserver import androidx.lifecycle.OnLifecycleEvent +import cloud.mindbox.mobile_sdk.Mindbox +import cloud.mindbox.mobile_sdk.Mindbox.IS_OPENED_FROM_PUSH_BUNDLE_KEY +import cloud.mindbox.mobile_sdk.models.DIRECT +import cloud.mindbox.mobile_sdk.models.LINK +import cloud.mindbox.mobile_sdk.models.PUSH internal class LifecycleManager( - private val onAppStarted: () -> Unit + private var currentActivity: Activity? ) : Application.ActivityLifecycleCallbacks, ComponentCallbacks2, LifecycleObserver { - var currentActivity: Activity? = null + companion object { + + private const val SCHEMA_HTTP = "http" + private const val SCHEMA_HTTPS = "https" + + } private var isConfigurationChanged = false + private var isAppInBackground = true override fun onActivityCreated(activity: Activity, p1: Bundle?) { - Log.d("______", "created cur $currentActivity act $activity") + setActivityIfNeeded(activity) } override fun onActivityStarted(activity: Activity) { - Log.d("______", "cur $currentActivity act $activity action ${activity.intent.action} extas ${activity.intent.extras} data ${activity.intent.data} cat ${activity.intent.categories} schema ${activity.intent.scheme}") -activity.intent.scheme - - when { - isConfigurationChanged -> isConfigurationChanged = false - currentActivity?.javaClass?.name == activity.javaClass.name -> { - Log.d("______", "app started") - onAppStarted() - } - else -> currentActivity = activity + if (isConfigurationChanged || isAppInBackground) { + isConfigurationChanged = false + isAppInBackground = false + return } + + sendTrackVisit(activity) + currentActivity = activity } override fun onActivityResumed(activity: Activity) { @@ -45,10 +53,7 @@ activity.intent.scheme } override fun onActivityStopped(activity: Activity) { - if (currentActivity == null) { - currentActivity = activity - } - Log.d("______", "stopped cur $currentActivity act $activity action ${activity.intent.action} extas ${activity.intent.extras} data ${activity.intent.data} cat ${activity.intent.categories}") + setActivityIfNeeded(activity) } override fun onActivitySaveInstanceState(activity: Activity, p1: Bundle) { @@ -60,7 +65,6 @@ activity.intent.scheme } override fun onConfigurationChanged(newConfig: Configuration) { - Log.d("______", "onConfigurationChanged") isConfigurationChanged = true } @@ -73,13 +77,36 @@ activity.intent.scheme } @OnLifecycleEvent(Lifecycle.Event.ON_STOP) - fun onAppMovedToBackground() { - Log.d("_______", "App in background $currentActivity action ${currentActivity?.intent?.action} extas ${currentActivity?.intent?.extras} data ${currentActivity?.intent?.data} cat ${currentActivity?.intent?.categories}") + private fun onAppMovedToBackground() { + isConfigurationChanged = false + isAppInBackground = true } @OnLifecycleEvent(Lifecycle.Event.ON_START) - fun onAppMovedToForeground() { - Log.d("_______", "App in foreground $currentActivity action ${currentActivity?.intent?.action} extas ${currentActivity?.intent?.extras} data ${currentActivity?.intent?.data} cat ${currentActivity?.intent?.categories}") + private fun onAppMovedToForeground() { + currentActivity?.let(::sendTrackVisit) + } + + private fun setActivityIfNeeded(activity: Activity) { + if (currentActivity == null) { + currentActivity = activity + } + } + + private fun sendTrackVisit(activity: Activity) { + val intent = activity.intent + val source = source(intent) + val requestUrl = if (source == LINK) intent?.data?.toString() else null + + if (currentActivity?.javaClass?.name == activity.javaClass.name || source != DIRECT) { + Mindbox.sendTrackVisitEvent(activity, source, requestUrl) + } + } + + private fun source(intent: Intent?) = when { + intent?.scheme == SCHEMA_HTTP || intent?.scheme == SCHEMA_HTTPS -> LINK + intent?.extras?.getBoolean(IS_OPENED_FROM_PUSH_BUNDLE_KEY) == true -> PUSH + else -> DIRECT } } diff --git a/sdk/src/main/java/cloud/mindbox/mobile_sdk/models/InitData.kt b/sdk/src/main/java/cloud/mindbox/mobile_sdk/models/InitData.kt index 17d8e5c5d..7cdf1f63f 100644 --- a/sdk/src/main/java/cloud/mindbox/mobile_sdk/models/InitData.kt +++ b/sdk/src/main/java/cloud/mindbox/mobile_sdk/models/InitData.kt @@ -1,7 +1,13 @@ package cloud.mindbox.mobile_sdk.models +import androidx.annotation.StringDef + private const val INIT_DATA_VERSION = 0 +internal const val DIRECT = "direct" +internal const val LINK = "link" +internal const val PUSH = "push" + internal data class InitData( val token: String, val isTokenAvailable: Boolean, @@ -28,5 +34,10 @@ internal data class TrackClickData( internal data class TrackVisitData( val ianaTimeZone: String, - val endpointId: String + val endpointId: String, + @TrackVisitSource val source: String? = null, + val requestUrl: String? = null ) + +@StringDef(DIRECT, LINK, PUSH) +internal annotation class TrackVisitSource From 061056b686c6da5d44f0567889fd394891b0ade7 Mon Sep 17 00:00:00 2001 From: Elizaveta Nevostrueva Date: Wed, 12 May 2021 14:45:01 +0300 Subject: [PATCH 3/4] Implemented showing error for incorrect context, handling back to activity and improvements logic for source determination --- sdk/build.gradle | 1 + .../java/cloud/mindbox/mobile_sdk/Mindbox.kt | 55 ++++++++----- .../mobile_sdk/managers/LifecycleManager.kt | 82 ++++++++++--------- .../managers/MindboxEventManager.kt | 12 ++- 4 files changed, 85 insertions(+), 65 deletions(-) diff --git a/sdk/build.gradle b/sdk/build.gradle index 940caa1f5..e91771119 100644 --- a/sdk/build.gradle +++ b/sdk/build.gradle @@ -142,6 +142,7 @@ dependencies { // dex implementation "androidx.multidex:multidex:2.0.1" + // Handle app lifecycle implementation "androidx.lifecycle:lifecycle-process:2.3.1" } \ No newline at end of file diff --git a/sdk/src/main/java/cloud/mindbox/mobile_sdk/Mindbox.kt b/sdk/src/main/java/cloud/mindbox/mobile_sdk/Mindbox.kt index 7f65b09fd..b4dfa469a 100644 --- a/sdk/src/main/java/cloud/mindbox/mobile_sdk/Mindbox.kt +++ b/sdk/src/main/java/cloud/mindbox/mobile_sdk/Mindbox.kt @@ -3,6 +3,7 @@ package cloud.mindbox.mobile_sdk import android.app.Activity import android.app.Application import android.content.Context +import androidx.lifecycle.Lifecycle.State.RESUMED import androidx.lifecycle.ProcessLifecycleOwner import cloud.mindbox.mobile_sdk.logger.Level import cloud.mindbox.mobile_sdk.logger.MindboxLogger @@ -169,8 +170,6 @@ object Mindbox { * * @param context used to initialize the main tools * @param configuration contains the data that is needed to connect to the Mindbox - * - * @throws IllegalStateException */ fun init( context: Context, @@ -196,6 +195,7 @@ object Mindbox { mindboxScope.launch { if (MindboxPreferences.isFirstInitialize) { firstInitialization(context, configuration) + sendTrackVisitEvent(context) } else { updateAppInfo(context) MindboxEventManager.sendEventsIfExist(context) @@ -204,16 +204,33 @@ object Mindbox { // Handle back app in foreground (context.applicationContext as? Application)?.apply { + val applicationLifecycle = ProcessLifecycleOwner.get().lifecycle + if (!Mindbox::lifecycleManager.isInitialized) { - lifecycleManager = LifecycleManager(context as? Activity) + val activity = context as? Activity + if (applicationLifecycle.currentState == RESUMED && activity == null) { + MindboxLogger.e( + this@Mindbox, + "Incorrect context type for calling init in this place" + ) + } + + lifecycleManager = LifecycleManager( + currentActivityName = activity?.javaClass?.name, + currentIntent = activity?.intent, + onTrackVisitReady = { source, requestUrl -> + runBlocking(Dispatchers.IO) { + sendTrackVisitEvent(context, source, requestUrl) + } + } + ) } else { - unregisterComponentCallbacks(lifecycleManager) unregisterActivityLifecycleCallbacks(lifecycleManager) - ProcessLifecycleOwner.get().lifecycle.removeObserver(lifecycleManager) + applicationLifecycle.removeObserver(lifecycleManager) } - registerComponentCallbacks(lifecycleManager) + registerActivityLifecycleCallbacks(lifecycleManager) - ProcessLifecycleOwner.get().lifecycle.addObserver(lifecycleManager) + applicationLifecycle.addObserver(lifecycleManager) } }.returnOnException { } } @@ -328,23 +345,21 @@ object Mindbox { }.logOnException() } - internal fun sendTrackVisitEvent( + private fun sendTrackVisitEvent( context: Context, @TrackVisitSource source: String? = null, requestUrl: String? = null ) = runCatching { - runBlocking(Dispatchers.IO) { - val applicationContext = context.applicationContext - val endpointId = DbManager.getConfigurations()?.endpointId ?: return@runBlocking - val trackVisitData = TrackVisitData( - ianaTimeZone = TimeZone.getDefault().id, - endpointId = endpointId, - source = source, - requestUrl = requestUrl - ) - - MindboxEventManager.appStarted(applicationContext, trackVisitData) - } + val applicationContext = context.applicationContext + val endpointId = DbManager.getConfigurations()?.endpointId ?: return + val trackVisitData = TrackVisitData( + ianaTimeZone = TimeZone.getDefault().id, + endpointId = endpointId, + source = source, + requestUrl = requestUrl + ) + + MindboxEventManager.appStarted(applicationContext, trackVisitData) }.logOnException() private fun deliverDeviceUuid(deviceUuid: String) { diff --git a/sdk/src/main/java/cloud/mindbox/mobile_sdk/managers/LifecycleManager.kt b/sdk/src/main/java/cloud/mindbox/mobile_sdk/managers/LifecycleManager.kt index 74c863bcd..ee28ecab9 100644 --- a/sdk/src/main/java/cloud/mindbox/mobile_sdk/managers/LifecycleManager.kt +++ b/sdk/src/main/java/cloud/mindbox/mobile_sdk/managers/LifecycleManager.kt @@ -2,46 +2,55 @@ package cloud.mindbox.mobile_sdk.managers import android.app.Activity import android.app.Application -import android.content.ComponentCallbacks2 import android.content.Intent -import android.content.res.Configuration import android.os.Bundle import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleObserver import androidx.lifecycle.OnLifecycleEvent -import cloud.mindbox.mobile_sdk.Mindbox import cloud.mindbox.mobile_sdk.Mindbox.IS_OPENED_FROM_PUSH_BUNDLE_KEY +import cloud.mindbox.mobile_sdk.logger.MindboxLogger import cloud.mindbox.mobile_sdk.models.DIRECT import cloud.mindbox.mobile_sdk.models.LINK import cloud.mindbox.mobile_sdk.models.PUSH internal class LifecycleManager( - private var currentActivity: Activity? -) : Application.ActivityLifecycleCallbacks, ComponentCallbacks2, LifecycleObserver { + private var currentActivityName: String?, + private var currentIntent: Intent?, + private var onTrackVisitReady: (source: String, requestUrl: String?) -> Unit +) : Application.ActivityLifecycleCallbacks, LifecycleObserver { companion object { private const val SCHEMA_HTTP = "http" private const val SCHEMA_HTTPS = "https" + private const val MAX_INTENT_HASHES_SIZE = 50 } - private var isConfigurationChanged = false private var isAppInBackground = true + private var isIntentChanged = true + private val intentHashes = mutableListOf() override fun onActivityCreated(activity: Activity, p1: Bundle?) { - setActivityIfNeeded(activity) + } override fun onActivityStarted(activity: Activity) { - if (isConfigurationChanged || isAppInBackground) { - isConfigurationChanged = false + val areActivitiesEqual = currentActivityName == activity.javaClass.name + val intent = activity.intent + isIntentChanged = if (currentIntent != intent) { + updateActivityParameters(activity) + intent?.hashCode()?.let(::updateHashesList) ?: true + } else { + false + } + + if (isAppInBackground || !isIntentChanged) { isAppInBackground = false return } - sendTrackVisit(activity) - currentActivity = activity + sendTrackVisit(activity.intent, areActivitiesEqual) } override fun onActivityResumed(activity: Activity) { @@ -53,7 +62,9 @@ internal class LifecycleManager( } override fun onActivityStopped(activity: Activity) { - setActivityIfNeeded(activity) + if (currentIntent == null || currentActivityName == null) { + updateActivityParameters(activity) + } } override fun onActivitySaveInstanceState(activity: Activity, p1: Bundle) { @@ -64,42 +75,27 @@ internal class LifecycleManager( } - override fun onConfigurationChanged(newConfig: Configuration) { - isConfigurationChanged = true - } - - override fun onLowMemory() { - - } - - override fun onTrimMemory(level: Int) { - - } - @OnLifecycleEvent(Lifecycle.Event.ON_STOP) private fun onAppMovedToBackground() { - isConfigurationChanged = false isAppInBackground = true } @OnLifecycleEvent(Lifecycle.Event.ON_START) - private fun onAppMovedToForeground() { - currentActivity?.let(::sendTrackVisit) - } + private fun onAppMovedToForeground() = currentIntent?.let(::sendTrackVisit) - private fun setActivityIfNeeded(activity: Activity) { - if (currentActivity == null) { - currentActivity = activity - } + private fun updateActivityParameters(activity: Activity) { + currentActivityName = activity.javaClass.name + currentIntent = activity.intent } - private fun sendTrackVisit(activity: Activity) { - val intent = activity.intent - val source = source(intent) - val requestUrl = if (source == LINK) intent?.data?.toString() else null + private fun sendTrackVisit(intent: Intent, areActivitiesEqual: Boolean = true) { + val source = if (isIntentChanged) source(intent) else DIRECT + + if (areActivitiesEqual || source != DIRECT) { + val requestUrl = if (source == LINK) intent.data?.toString() else null + onTrackVisitReady.invoke(source, requestUrl) - if (currentActivity?.javaClass?.name == activity.javaClass.name || source != DIRECT) { - Mindbox.sendTrackVisitEvent(activity, source, requestUrl) + MindboxLogger.d(this, "Track visit event with source $source and url $requestUrl") } } @@ -109,4 +105,14 @@ internal class LifecycleManager( else -> DIRECT } + private fun updateHashesList(code: Int) = if (!intentHashes.contains(code)) { + if (intentHashes.size >= MAX_INTENT_HASHES_SIZE) { + intentHashes.removeAt(0) + } + intentHashes.add(code) + true + } else { + false + } + } diff --git a/sdk/src/main/java/cloud/mindbox/mobile_sdk/managers/MindboxEventManager.kt b/sdk/src/main/java/cloud/mindbox/mobile_sdk/managers/MindboxEventManager.kt index 7687c2485..e781df537 100644 --- a/sdk/src/main/java/cloud/mindbox/mobile_sdk/managers/MindboxEventManager.kt +++ b/sdk/src/main/java/cloud/mindbox/mobile_sdk/managers/MindboxEventManager.kt @@ -68,14 +68,12 @@ internal object MindboxEventManager { fun appStarted(context: Context, trackVisitData: TrackVisitData) { runCatching { - runBlocking(Dispatchers.IO) { - DbManager.addEventToQueue( - context, Event( - eventType = EventType.TrackVisit, - body = gson.toJson(trackVisitData) - ) + DbManager.addEventToQueue( + context, Event( + eventType = EventType.TrackVisit, + body = gson.toJson(trackVisitData) ) - } + ) }.logOnException() } From d6d99c30614272fff0f4816db4c0b2be7163ff95 Mon Sep 17 00:00:00 2001 From: Elizaveta Nevostrueva Date: Thu, 13 May 2021 18:08:25 +0300 Subject: [PATCH 4/4] Added runCatching --- .../java/cloud/mindbox/mobile_sdk/Mindbox.kt | 6 +- .../mobile_sdk/managers/LifecycleManager.kt | 76 ++++++++++--------- .../managers/SharedPreferencesManager.kt | 24 ++++-- 3 files changed, 62 insertions(+), 44 deletions(-) diff --git a/sdk/src/main/java/cloud/mindbox/mobile_sdk/Mindbox.kt b/sdk/src/main/java/cloud/mindbox/mobile_sdk/Mindbox.kt index b4dfa469a..87ffc2806 100644 --- a/sdk/src/main/java/cloud/mindbox/mobile_sdk/Mindbox.kt +++ b/sdk/src/main/java/cloud/mindbox/mobile_sdk/Mindbox.kt @@ -64,9 +64,9 @@ object Mindbox { /** * Returns date of FMS token saving */ - fun getFmsTokenSaveDate(): String = - runCatching { return MindboxPreferences.firebaseTokenSaveDate } - .returnOnException { "" } + fun getFmsTokenSaveDate(): String = runCatching { + return MindboxPreferences.firebaseTokenSaveDate + }.returnOnException { "" } /** * Returns SDK version diff --git a/sdk/src/main/java/cloud/mindbox/mobile_sdk/managers/LifecycleManager.kt b/sdk/src/main/java/cloud/mindbox/mobile_sdk/managers/LifecycleManager.kt index ee28ecab9..224eb1f74 100644 --- a/sdk/src/main/java/cloud/mindbox/mobile_sdk/managers/LifecycleManager.kt +++ b/sdk/src/main/java/cloud/mindbox/mobile_sdk/managers/LifecycleManager.kt @@ -8,15 +8,17 @@ import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleObserver import androidx.lifecycle.OnLifecycleEvent import cloud.mindbox.mobile_sdk.Mindbox.IS_OPENED_FROM_PUSH_BUNDLE_KEY +import cloud.mindbox.mobile_sdk.logOnException import cloud.mindbox.mobile_sdk.logger.MindboxLogger import cloud.mindbox.mobile_sdk.models.DIRECT import cloud.mindbox.mobile_sdk.models.LINK import cloud.mindbox.mobile_sdk.models.PUSH +import cloud.mindbox.mobile_sdk.returnOnException internal class LifecycleManager( private var currentActivityName: String?, private var currentIntent: Intent?, - private var onTrackVisitReady: (source: String, requestUrl: String?) -> Unit + private var onTrackVisitReady: (source: String?, requestUrl: String?) -> Unit ) : Application.ActivityLifecycleCallbacks, LifecycleObserver { companion object { @@ -36,21 +38,23 @@ internal class LifecycleManager( } override fun onActivityStarted(activity: Activity) { - val areActivitiesEqual = currentActivityName == activity.javaClass.name - val intent = activity.intent - isIntentChanged = if (currentIntent != intent) { - updateActivityParameters(activity) - intent?.hashCode()?.let(::updateHashesList) ?: true - } else { - false - } - - if (isAppInBackground || !isIntentChanged) { - isAppInBackground = false - return - } - - sendTrackVisit(activity.intent, areActivitiesEqual) + runCatching { + val areActivitiesEqual = currentActivityName == activity.javaClass.name + val intent = activity.intent + isIntentChanged = if (currentIntent != intent) { + updateActivityParameters(activity) + intent?.hashCode()?.let(::updateHashesList) ?: true + } else { + false + } + + if (isAppInBackground || !isIntentChanged) { + isAppInBackground = false + return + } + + sendTrackVisit(activity.intent, areActivitiesEqual) + }.logOnException() } override fun onActivityResumed(activity: Activity) { @@ -83,12 +87,12 @@ internal class LifecycleManager( @OnLifecycleEvent(Lifecycle.Event.ON_START) private fun onAppMovedToForeground() = currentIntent?.let(::sendTrackVisit) - private fun updateActivityParameters(activity: Activity) { + private fun updateActivityParameters(activity: Activity) = runCatching { currentActivityName = activity.javaClass.name currentIntent = activity.intent - } + }.logOnException() - private fun sendTrackVisit(intent: Intent, areActivitiesEqual: Boolean = true) { + private fun sendTrackVisit(intent: Intent, areActivitiesEqual: Boolean = true) = runCatching { val source = if (isIntentChanged) source(intent) else DIRECT if (areActivitiesEqual || source != DIRECT) { @@ -97,22 +101,26 @@ internal class LifecycleManager( MindboxLogger.d(this, "Track visit event with source $source and url $requestUrl") } - } - - private fun source(intent: Intent?) = when { - intent?.scheme == SCHEMA_HTTP || intent?.scheme == SCHEMA_HTTPS -> LINK - intent?.extras?.getBoolean(IS_OPENED_FROM_PUSH_BUNDLE_KEY) == true -> PUSH - else -> DIRECT - } + }.logOnException() - private fun updateHashesList(code: Int) = if (!intentHashes.contains(code)) { - if (intentHashes.size >= MAX_INTENT_HASHES_SIZE) { - intentHashes.removeAt(0) + private fun source(intent: Intent?) = runCatching { + when { + intent?.scheme == SCHEMA_HTTP || intent?.scheme == SCHEMA_HTTPS -> LINK + intent?.extras?.getBoolean(IS_OPENED_FROM_PUSH_BUNDLE_KEY) == true -> PUSH + else -> DIRECT } - intentHashes.add(code) - true - } else { - false - } + }.returnOnException { null } + + private fun updateHashesList(code: Int) = runCatching { + if (!intentHashes.contains(code)) { + if (intentHashes.size >= MAX_INTENT_HASHES_SIZE) { + intentHashes.removeAt(0) + } + intentHashes.add(code) + true + } else { + false + } + }.returnOnException { true } } diff --git a/sdk/src/main/java/cloud/mindbox/mobile_sdk/managers/SharedPreferencesManager.kt b/sdk/src/main/java/cloud/mindbox/mobile_sdk/managers/SharedPreferencesManager.kt index dd5b20d94..8061ea2ff 100644 --- a/sdk/src/main/java/cloud/mindbox/mobile_sdk/managers/SharedPreferencesManager.kt +++ b/sdk/src/main/java/cloud/mindbox/mobile_sdk/managers/SharedPreferencesManager.kt @@ -3,6 +3,8 @@ package cloud.mindbox.mobile_sdk.managers import android.app.Application import android.content.Context import android.content.SharedPreferences +import cloud.mindbox.mobile_sdk.logOnException +import cloud.mindbox.mobile_sdk.returnOnException internal object SharedPreferencesManager { @@ -39,7 +41,7 @@ internal object SharedPreferencesManager { fun put( key: String, value: String? - ) = preferences.edit().putString(key, value).apply() + ) = runCatching { preferences.edit().putString(key, value).apply() }.logOnException() /** * Saves [Boolean] into the Preferences. @@ -50,7 +52,7 @@ internal object SharedPreferencesManager { fun put( key: String, value: Boolean - ) = preferences.edit().putBoolean(key, value).apply() + ) = runCatching { preferences.edit().putBoolean(key, value).apply() }.logOnException() /** * Saves [Int] into the Preferences. @@ -61,7 +63,7 @@ internal object SharedPreferencesManager { fun put( key: String, value: Int - ) = preferences.edit().putInt(key, value).apply() + ) = runCatching { preferences.edit().putInt(key, value).apply() }.logOnException() /** * Used to retrieve [String] object from the Preferences. @@ -73,7 +75,9 @@ internal object SharedPreferencesManager { fun getString( key: String, defaultValue: String? = null - ): String? = preferences.getString(key, defaultValue) + ): String? = runCatching { + preferences.getString(key, defaultValue) + }.returnOnException { defaultValue } /** * Used to retrieve [Boolean] object from the Preferences. @@ -85,7 +89,9 @@ internal object SharedPreferencesManager { fun getBoolean( key: String, defaultValue: Boolean = false - ): Boolean = preferences.getBoolean(key, defaultValue) + ): Boolean = runCatching { + preferences.getBoolean(key, defaultValue) + }.returnOnException { defaultValue } /** * Used to retrieve [Int] object from the Preferences. @@ -97,8 +103,12 @@ internal object SharedPreferencesManager { fun getInt( key: String, defaultValue: Int = DEFAULT_INT_VALUE - ): Int = preferences.getInt(key, defaultValue) + ): Int = runCatching { + preferences.getInt(key, defaultValue) + }.returnOnException { defaultValue } - internal fun deleteAll() = preferences.edit().clear().apply() + internal fun deleteAll() = runCatching { + preferences.edit().clear().apply() + }.exceptionOrNull() }