Skip to content

Commit 6e348f4

Browse files
chore(ttd): Fallback to activity holder if react context activity is not available (#4779)
1 parent 7fccbbe commit 6e348f4

File tree

4 files changed

+91
-2
lines changed

4 files changed

+91
-2
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
99
## Unreleased
1010

11+
### Changes
12+
13+
- Fallback to Current Activity Holder when React Context Activity is not present ([#4779](https://github.com/getsentry/sentry-react-native/pull/4779))
14+
1115
### Dependencies
1216

1317
- Bump Cocoa SDK from v8.49.1 to v8.49.2 ([#4792](https://github.com/getsentry/sentry-react-native/pull/4792))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package io.sentry.react.utils
2+
3+
import android.app.Activity
4+
import com.facebook.react.bridge.ReactApplicationContext
5+
import io.sentry.android.core.AndroidLogger
6+
import io.sentry.android.core.CurrentActivityHolder
7+
import org.junit.After
8+
import org.junit.Assert.assertNull
9+
import org.junit.Assert.assertSame
10+
import org.junit.Test
11+
import org.junit.runner.RunWith
12+
import org.junit.runners.JUnit4
13+
import org.mockito.Mockito.mock
14+
import org.mockito.kotlin.whenever
15+
16+
@RunWith(JUnit4::class)
17+
class RNSentryActivityUtilsTest {
18+
private val mockedLogger = mock(AndroidLogger::class.java)
19+
20+
@After
21+
fun clearActivityHolder() {
22+
CurrentActivityHolder.getInstance().clearActivity()
23+
}
24+
25+
@Test
26+
fun `returns react context activity`() {
27+
val mockedCurrentActivity = mock(Activity::class.java)
28+
val mockedReactContext = mock(ReactApplicationContext::class.java)
29+
whenever(mockedReactContext.currentActivity).thenReturn(mockedCurrentActivity)
30+
31+
assertSame(RNSentryActivityUtils.getCurrentActivity(mockedReactContext, mockedLogger), mockedCurrentActivity)
32+
}
33+
34+
@Test
35+
fun `returns current activity holder activity`() {
36+
val mockedCurrentActivity = mock(Activity::class.java)
37+
38+
val mockedReactContext = mock(ReactApplicationContext::class.java)
39+
whenever(mockedReactContext.currentActivity).thenReturn(null)
40+
41+
CurrentActivityHolder.getInstance().setActivity(mockedCurrentActivity)
42+
assertSame(RNSentryActivityUtils.getCurrentActivity(mockedReactContext, mockedLogger), mockedCurrentActivity)
43+
}
44+
45+
@Test
46+
fun `returns null when no activity exists`() {
47+
val mockedReactContext = mock(ReactApplicationContext::class.java)
48+
whenever(mockedReactContext.currentActivity).thenReturn(null)
49+
50+
assertNull(RNSentryActivityUtils.getCurrentActivity(mockedReactContext, mockedLogger))
51+
}
52+
}

packages/core/android/src/main/java/io/sentry/react/RNSentryOnDrawReporterManager.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import io.sentry.android.core.BuildInfoProvider;
1515
import io.sentry.android.core.SentryAndroidDateProvider;
1616
import io.sentry.android.core.internal.util.FirstDrawDoneListener;
17+
import io.sentry.react.utils.RNSentryActivityUtils;
1718
import java.util.Objects;
1819
import org.jetbrains.annotations.NotNull;
1920
import org.jetbrains.annotations.Nullable;
@@ -151,11 +152,12 @@ private void processPropsChanged() {
151152
return;
152153
}
153154

154-
@Nullable Activity activity = reactContext.getCurrentActivity();
155+
final @Nullable Activity activity =
156+
RNSentryActivityUtils.getCurrentActivity(reactContext, logger);
155157
if (activity == null) {
156158
logger.log(
157159
SentryLevel.ERROR,
158-
"[TimeToDisplay] Won't emit next frame drawn event, reactContext is null.");
160+
"[TimeToDisplay] Won't emit next frame drawn event, activity is null.");
159161
return;
160162
}
161163

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package io.sentry.react.utils;
2+
3+
import android.app.Activity;
4+
import com.facebook.react.bridge.ReactApplicationContext;
5+
import io.sentry.ILogger;
6+
import io.sentry.SentryLevel;
7+
import io.sentry.android.core.CurrentActivityHolder;
8+
import org.jetbrains.annotations.NotNull;
9+
import org.jetbrains.annotations.Nullable;
10+
11+
/** Utility class for React Native Activity related functionality. */
12+
public final class RNSentryActivityUtils {
13+
14+
private RNSentryActivityUtils() {
15+
// Prevent instantiation
16+
}
17+
18+
public static @Nullable Activity getCurrentActivity(
19+
final @NotNull ReactApplicationContext reactContext, final @NotNull ILogger logger) {
20+
final Activity activity = reactContext.getCurrentActivity();
21+
if (activity != null) {
22+
return activity;
23+
}
24+
25+
logger.log(
26+
SentryLevel.DEBUG,
27+
"[RNSentryActivityUtils] Given ReactApplicationContext has no activity attached, using"
28+
+ " CurrentActivityHolder as a fallback.");
29+
return CurrentActivityHolder.getInstance().getActivity();
30+
}
31+
}

0 commit comments

Comments
 (0)