From 9e6df05c91d218d6059ed95687fdff646524225b Mon Sep 17 00:00:00 2001 From: Krystof Woldrich Date: Fri, 25 Apr 2025 17:57:05 +0200 Subject: [PATCH 1/4] fix(android): Init with ApplicationContext if available --- CHANGELOG.md | 1 + .../RNSentryModuleInitWithApplicationTest.kt | 33 +++++++++++++++++++ .../src/test/java/io/sentry/react/Utils.kt | 9 +++-- .../io/sentry/react/RNSentryModuleImpl.java | 13 +++++++- 4 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 packages/core/RNSentryAndroidTester/app/src/test/java/io/sentry/react/RNSentryModuleInitWithApplicationTest.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 819f1e1a2e..b29bef0482 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ - Export `extraErrorDataIntegration` from `@sentry/core` ([#4762](https://github.com/getsentry/sentry-react-native/pull/4762)) - Remove `@sentry-internal/replay` when `includeWebReplay: false` ([#4774](https://github.com/getsentry/sentry-react-native/pull/4774)) +- Initialize Sentry Android with ApplicationContext if available ([#4779](https://github.com/getsentry/sentry-react-native/pull/4779)) ### Dependencies diff --git a/packages/core/RNSentryAndroidTester/app/src/test/java/io/sentry/react/RNSentryModuleInitWithApplicationTest.kt b/packages/core/RNSentryAndroidTester/app/src/test/java/io/sentry/react/RNSentryModuleInitWithApplicationTest.kt new file mode 100644 index 0000000000..ca8fd98926 --- /dev/null +++ b/packages/core/RNSentryAndroidTester/app/src/test/java/io/sentry/react/RNSentryModuleInitWithApplicationTest.kt @@ -0,0 +1,33 @@ +package io.sentry.react + +import android.app.Application +import android.content.Context +import com.facebook.react.bridge.ReactApplicationContext +import org.junit.Assert.assertSame +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import org.mockito.Mockito.mock +import org.mockito.kotlin.whenever +import org.robolectric.RobolectricTestRunner + +@RunWith(RobolectricTestRunner::class) +class RNSentryModuleInitWithApplicationTest { + @Test + fun `when application context is null fallback to react context`() { + val mockedReactContext = Utils.makeReactContextMock() + whenever(mockedReactContext.applicationContext).thenReturn(null) + + assertSame(RNSentryModuleImpl(mockedReactContext).applicationContext, mockedReactContext) + } + + @Test + fun `use application context if available`() { + val mockedApplicationContext = mock(Application::class.java) + val mockedReactContext = Utils.makeReactContextMock() + whenever(mockedReactContext.applicationContext).thenReturn(mockedApplicationContext) + + assertSame(RNSentryModuleImpl(mockedReactContext).applicationContext, mockedApplicationContext) + } +} diff --git a/packages/core/RNSentryAndroidTester/app/src/test/java/io/sentry/react/Utils.kt b/packages/core/RNSentryAndroidTester/app/src/test/java/io/sentry/react/Utils.kt index 989c2c0994..17782b7cfa 100644 --- a/packages/core/RNSentryAndroidTester/app/src/test/java/io/sentry/react/Utils.kt +++ b/packages/core/RNSentryAndroidTester/app/src/test/java/io/sentry/react/Utils.kt @@ -3,6 +3,7 @@ package io.sentry.react import android.content.pm.PackageInfo import android.content.pm.PackageManager import com.facebook.react.bridge.ReactApplicationContext +import com.facebook.react.bridge.ReactContext import org.mockito.ArgumentMatchers.anyInt import org.mockito.ArgumentMatchers.anyString import org.mockito.Mockito.mock @@ -10,7 +11,7 @@ import org.mockito.kotlin.whenever class Utils { companion object { - fun createRNSentryModuleWithMockedContext(): RNSentryModuleImpl { + fun makeReactContextMock(): ReactApplicationContext { val packageManager = mock(PackageManager::class.java) val packageInfo = mock(PackageInfo::class.java) @@ -18,9 +19,13 @@ class Utils { whenever(reactContext.packageManager).thenReturn(packageManager) whenever(packageManager.getPackageInfo(anyString(), anyInt())).thenReturn(packageInfo) + return reactContext + } + + fun createRNSentryModuleWithMockedContext(): RNSentryModuleImpl { RNSentryModuleImpl.lastStartTimestampMs = -1 - return RNSentryModuleImpl(reactContext) + return RNSentryModuleImpl(makeReactContextMock()) } } } diff --git a/packages/core/android/src/main/java/io/sentry/react/RNSentryModuleImpl.java b/packages/core/android/src/main/java/io/sentry/react/RNSentryModuleImpl.java index 8a6beaa024..a4ece7415f 100644 --- a/packages/core/android/src/main/java/io/sentry/react/RNSentryModuleImpl.java +++ b/packages/core/android/src/main/java/io/sentry/react/RNSentryModuleImpl.java @@ -90,6 +90,7 @@ import java.util.concurrent.CountDownLatch; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.TestOnly; public class RNSentryModuleImpl { @@ -177,12 +178,22 @@ public void initNativeReactNavigationNewFrameTracking(Promise promise) { public void initNativeSdk(final ReadableMap rnOptions, Promise promise) { SentryAndroid.init( - this.getReactApplicationContext(), + getApplicationContext(), options -> getSentryAndroidOptions(options, rnOptions, logger)); promise.resolve(true); } + @TestOnly + protected Context getApplicationContext() { + final Context context = this.getReactApplicationContext().getApplicationContext(); + if (context == null) { + logger.log(SentryLevel.ERROR, "ApplicationContext is null, using ReactApplicationContext fallback."); + return this.getReactApplicationContext(); + } + return context; + } + protected void getSentryAndroidOptions( @NotNull SentryAndroidOptions options, @NotNull ReadableMap rnOptions, ILogger logger) { @Nullable SdkVersion sdkVersion = options.getSdkVersion(); From 8b37538adc65a6cef662dff07505148c1d4bf473 Mon Sep 17 00:00:00 2001 From: Krystof Woldrich Date: Mon, 28 Apr 2025 17:30:41 +0200 Subject: [PATCH 2/4] fix lint --- .../src/main/java/io/sentry/react/RNSentryModuleImpl.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/core/android/src/main/java/io/sentry/react/RNSentryModuleImpl.java b/packages/core/android/src/main/java/io/sentry/react/RNSentryModuleImpl.java index a4ece7415f..8f6c814db6 100644 --- a/packages/core/android/src/main/java/io/sentry/react/RNSentryModuleImpl.java +++ b/packages/core/android/src/main/java/io/sentry/react/RNSentryModuleImpl.java @@ -178,8 +178,7 @@ public void initNativeReactNavigationNewFrameTracking(Promise promise) { public void initNativeSdk(final ReadableMap rnOptions, Promise promise) { SentryAndroid.init( - getApplicationContext(), - options -> getSentryAndroidOptions(options, rnOptions, logger)); + getApplicationContext(), options -> getSentryAndroidOptions(options, rnOptions, logger)); promise.resolve(true); } @@ -188,7 +187,8 @@ public void initNativeSdk(final ReadableMap rnOptions, Promise promise) { protected Context getApplicationContext() { final Context context = this.getReactApplicationContext().getApplicationContext(); if (context == null) { - logger.log(SentryLevel.ERROR, "ApplicationContext is null, using ReactApplicationContext fallback."); + logger.log( + SentryLevel.ERROR, "ApplicationContext is null, using ReactApplicationContext fallback."); return this.getReactApplicationContext(); } return context; From cc564ed0dd1d1ab97607fb9234b1d79739bae958 Mon Sep 17 00:00:00 2001 From: Krystof Woldrich Date: Mon, 28 Apr 2025 17:31:18 +0200 Subject: [PATCH 3/4] fix lint more --- .../io/sentry/react/RNSentryModuleInitWithApplicationTest.kt | 4 ---- .../app/src/test/java/io/sentry/react/Utils.kt | 1 - 2 files changed, 5 deletions(-) diff --git a/packages/core/RNSentryAndroidTester/app/src/test/java/io/sentry/react/RNSentryModuleInitWithApplicationTest.kt b/packages/core/RNSentryAndroidTester/app/src/test/java/io/sentry/react/RNSentryModuleInitWithApplicationTest.kt index ca8fd98926..7585335309 100644 --- a/packages/core/RNSentryAndroidTester/app/src/test/java/io/sentry/react/RNSentryModuleInitWithApplicationTest.kt +++ b/packages/core/RNSentryAndroidTester/app/src/test/java/io/sentry/react/RNSentryModuleInitWithApplicationTest.kt @@ -1,13 +1,9 @@ package io.sentry.react import android.app.Application -import android.content.Context -import com.facebook.react.bridge.ReactApplicationContext import org.junit.Assert.assertSame -import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -import org.junit.runners.JUnit4 import org.mockito.Mockito.mock import org.mockito.kotlin.whenever import org.robolectric.RobolectricTestRunner diff --git a/packages/core/RNSentryAndroidTester/app/src/test/java/io/sentry/react/Utils.kt b/packages/core/RNSentryAndroidTester/app/src/test/java/io/sentry/react/Utils.kt index 17782b7cfa..840e940917 100644 --- a/packages/core/RNSentryAndroidTester/app/src/test/java/io/sentry/react/Utils.kt +++ b/packages/core/RNSentryAndroidTester/app/src/test/java/io/sentry/react/Utils.kt @@ -3,7 +3,6 @@ package io.sentry.react import android.content.pm.PackageInfo import android.content.pm.PackageManager import com.facebook.react.bridge.ReactApplicationContext -import com.facebook.react.bridge.ReactContext import org.mockito.ArgumentMatchers.anyInt import org.mockito.ArgumentMatchers.anyString import org.mockito.Mockito.mock From 7181d9b30aad6d446f608feb9af150d3acb28161 Mon Sep 17 00:00:00 2001 From: Krystof Woldrich <31292499+krystofwoldrich@users.noreply.github.com> Date: Wed, 30 Apr 2025 10:41:17 +0200 Subject: [PATCH 4/4] Update CHANGELOG.md --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cb44817500..ac3d4f0e0f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,10 @@ - Fallback to Current Activity Holder when React Context Activity is not present ([#4779](https://github.com/getsentry/sentry-react-native/pull/4779)) +### Fixes + +- Initialize Sentry Android with ApplicationContext if available ([#4780](https://github.com/getsentry/sentry-react-native/pull/4780)) + ### Dependencies - Bump Cocoa SDK from v8.49.1 to v8.49.2 ([#4792](https://github.com/getsentry/sentry-react-native/pull/4792)) @@ -29,7 +33,6 @@ - Export `extraErrorDataIntegration` from `@sentry/core` ([#4762](https://github.com/getsentry/sentry-react-native/pull/4762)) - Remove `@sentry-internal/replay` when `includeWebReplay: false` ([#4774](https://github.com/getsentry/sentry-react-native/pull/4774)) -- Initialize Sentry Android with ApplicationContext if available ([#4779](https://github.com/getsentry/sentry-react-native/pull/4779)) ### Dependencies