Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
added AppStartMetrics automatically unregister lifecycle callback
added foreground check to SentryAndroid.init
  • Loading branch information
stefanosiano committed Jul 12, 2024
commit 082edcbda9d9c00306e208bc2db0769a8c8d6bad
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.sentry.android.core;

import android.annotation.SuppressLint;
import android.app.Application;
import android.content.Context;
import android.os.Process;
import android.os.SystemClock;
Expand Down Expand Up @@ -135,6 +136,10 @@ public static synchronized void init(
appStartTimeSpan.setStartedAt(Process.getStartUptimeMillis());
}
}
if (context.getApplicationContext() instanceof Application) {
appStartMetrics.registerApplicationForegroundCheck(
(Application) context.getApplicationContext());
}
final @NotNull TimeSpan sdkInitTimeSpan = appStartMetrics.getSdkInitTimeSpan();
if (sdkInitTimeSpan.hasNotStarted()) {
sdkInitTimeSpan.setStartedAt(sdkInitMillis);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ public void registerApplicationForegroundCheck(final @NotNull Application applic
if (onCreateTime == null) {
appLaunchedInForeground = false;
}
application.unregisterActivityLifecycleCallbacks(instance);
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,15 @@ class SentryAndroidTest {
verify(client, times(1)).captureSession(any(), any())
}

@Test
fun `When initializing Sentry a callback is added to application by appStartMetrics`() {
val mockContext = ContextUtilsTestHelper.createMockContext(true)
SentryAndroid.init(mockContext) {
it.dsn = "https://[email protected]/123"
}
verify(mockContext.applicationContext as Application).registerActivityLifecycleCallbacks(eq(AppStartMetrics.getInstance()))
}

private fun initSentryWithForegroundImportance(
inForeground: Boolean,
optionsConfig: (SentryAndroidOptions) -> Unit = {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ import io.sentry.android.core.SentryAndroidOptions
import io.sentry.android.core.SentryShadowProcess
import org.junit.Before
import org.junit.runner.RunWith
import org.mockito.kotlin.eq
import org.mockito.kotlin.mock
import org.mockito.kotlin.never
import org.mockito.kotlin.verify
import org.robolectric.Shadows
import org.robolectric.annotation.Config
import java.util.concurrent.TimeUnit
Expand Down Expand Up @@ -201,4 +204,45 @@ class AppStartMetricsTest {
val timeSpan = AppStartMetrics.getInstance().getAppStartTimeSpanWithFallback(options)
assertFalse(timeSpan.hasStarted())
}

@Test
fun `when registerApplicationForegroundCheck, a callback is registered to application`() {
val application = mock<Application>()
AppStartMetrics.getInstance().registerApplicationForegroundCheck(application)
verify(application).registerActivityLifecycleCallbacks(eq(AppStartMetrics.getInstance()))
}

@Test
fun `when registerApplicationForegroundCheck, a job is posted on main thread to unregistered the callback`() {
val application = mock<Application>()
AppStartMetrics.getInstance().registerApplicationForegroundCheck(application)
verify(application).registerActivityLifecycleCallbacks(eq(AppStartMetrics.getInstance()))
verify(application, never()).unregisterActivityLifecycleCallbacks(eq(AppStartMetrics.getInstance()))
Shadows.shadowOf(Looper.getMainLooper()).idle()
verify(application).unregisterActivityLifecycleCallbacks(eq(AppStartMetrics.getInstance()))
}

@Test
fun `registerApplicationForegroundCheck set foreground state to false if no activity is running`() {
val application = mock<Application>()
AppStartMetrics.getInstance().isAppLaunchedInForeground = true
AppStartMetrics.getInstance().registerApplicationForegroundCheck(application)
assertTrue(AppStartMetrics.getInstance().isAppLaunchedInForeground)
// Main thread performs the check and sets the flag to false if no activity was created
Shadows.shadowOf(Looper.getMainLooper()).idle()
assertFalse(AppStartMetrics.getInstance().isAppLaunchedInForeground)
}

@Test
fun `registerApplicationForegroundCheck keeps foreground state to true if an activity is running`() {
val application = mock<Application>()
AppStartMetrics.getInstance().isAppLaunchedInForeground = true
AppStartMetrics.getInstance().registerApplicationForegroundCheck(application)
assertTrue(AppStartMetrics.getInstance().isAppLaunchedInForeground)
// An activity was created
AppStartMetrics.getInstance().onActivityCreated(mock(), null)
// Main thread performs the check and keeps the flag to true
Shadows.shadowOf(Looper.getMainLooper()).idle()
assertTrue(AppStartMetrics.getInstance().isAppLaunchedInForeground)
}
}