Skip to content

Commit 5583fa5

Browse files
authored
throw when calling Sentry.init on Android (#3596)
* added a check in Sentry.init to check the options against the SentryAndroidOptions when using Android
1 parent 3740e7e commit 5583fa5

File tree

3 files changed

+65
-1
lines changed

3 files changed

+65
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
### Breaking Changes
66

7+
- Throw IllegalArgumentException when calling Sentry.init on Android ([#3596](https://github.com/getsentry/sentry-java/pull/3596))
78
- Change OkHttp sub-spans to span attributes ([#3556](https://github.com/getsentry/sentry-java/pull/3556))
89
- This will reduce the number of spans created by the SDK
910

sentry/src/main/java/io/sentry/Sentry.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,13 @@ public static void init(final @NotNull SentryOptions options) {
264264
@SuppressWarnings("deprecation")
265265
private static synchronized void init(
266266
final @NotNull SentryOptions options, final boolean globalHubMode) {
267+
268+
if (!options.getClass().getName().equals("io.sentry.android.core.SentryAndroidOptions")
269+
&& Platform.isAndroid()) {
270+
throw new IllegalArgumentException(
271+
"You are running Android. Please, use SentryAndroid.init. "
272+
+ options.getClass().getName());
273+
}
267274
if (isEnabled()) {
268275
options
269276
.getLogger()

sentry/src/test/java/io/sentry/SentryTest.kt

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import io.sentry.protocol.SentryId
1616
import io.sentry.protocol.SentryThread
1717
import io.sentry.test.ImmediateExecutorService
1818
import io.sentry.test.createSentryClientMock
19+
import io.sentry.test.injectForField
1920
import io.sentry.util.PlatformTestManipulator
2021
import io.sentry.util.thread.IMainThreadChecker
2122
import io.sentry.util.thread.MainThreadChecker
@@ -42,6 +43,7 @@ import kotlin.test.AfterTest
4243
import kotlin.test.BeforeTest
4344
import kotlin.test.Test
4445
import kotlin.test.assertEquals
46+
import kotlin.test.assertFails
4547
import kotlin.test.assertFalse
4648
import kotlin.test.assertIs
4749
import kotlin.test.assertNotEquals
@@ -957,12 +959,16 @@ class SentryTest {
957959

958960
@Test
959961
fun `getSpan calls returns root span if globalHubMode is enabled on Android`() {
962+
var sentryOptions: CustomAndroidOptions? = null
960963
PlatformTestManipulator.pretendIsAndroid(true)
961-
Sentry.init({
964+
Sentry.init(OptionsContainer.create(CustomAndroidOptions::class.java), {
962965
it.dsn = dsn
963966
it.enableTracing = true
964967
it.sampleRate = 1.0
968+
it.mockName()
969+
sentryOptions = it
965970
}, true)
971+
sentryOptions?.resetName()
966972

967973
val transaction = Sentry.startTransaction("name", "op-root", TransactionOptions().also { it.isBindToScope = true })
968974
transaction.startChild("op-child")
@@ -1174,6 +1180,36 @@ class SentryTest {
11741180
assertTrue(appStartOption.isProfilingEnabled)
11751181
}
11761182

1183+
@Test
1184+
fun `init on Android throws when not using SentryAndroidOptions`() {
1185+
PlatformTestManipulator.pretendIsAndroid(true)
1186+
assertFails("You are running Android. Please, use SentryAndroid.init.") {
1187+
Sentry.init {
1188+
it.dsn = dsn
1189+
}
1190+
}
1191+
PlatformTestManipulator.pretendIsAndroid(false)
1192+
}
1193+
1194+
@Test
1195+
fun `init on Android works when using SentryAndroidOptions`() {
1196+
PlatformTestManipulator.pretendIsAndroid(true)
1197+
val options = CustomAndroidOptions().also {
1198+
it.dsn = dsn
1199+
it.mockName()
1200+
}
1201+
Sentry.init(options)
1202+
options.resetName()
1203+
PlatformTestManipulator.pretendIsAndroid(false)
1204+
}
1205+
1206+
@Test
1207+
fun `init on Java works when not using SentryAndroidOptions`() {
1208+
Sentry.init {
1209+
it.dsn = dsn
1210+
}
1211+
}
1212+
11771213
@Test
11781214
fun `metrics calls scopes getMetrics`() {
11791215
val scopes = mock<IScopes>()
@@ -1260,4 +1296,24 @@ class SentryTest {
12601296
assertFalse(tempFile.exists())
12611297
return tempFile.absolutePath
12621298
}
1299+
1300+
/**
1301+
* Custom SentryOptions for Android.
1302+
* It needs to call [mockName] to change its name in io.sentry.android.core.SentryAndroidOptions.
1303+
* The name cannot be changed right away, because Sentry.init instantiates the options through reflection.
1304+
* So the name should be changed in option configuration.
1305+
* After the test, it needs to call [resetName] to reset the name back to io.sentry.SentryTest$CustomAndroidOptions,
1306+
* since it's cached internally and would break subsequent tests otherwise.
1307+
*/
1308+
private class CustomAndroidOptions : SentryOptions() {
1309+
init {
1310+
resetName()
1311+
}
1312+
fun mockName() {
1313+
javaClass.injectForField("name", "io.sentry.android.core.SentryAndroidOptions")
1314+
}
1315+
fun resetName() {
1316+
javaClass.injectForField("name", "io.sentry.SentryTest\$CustomAndroidOptions")
1317+
}
1318+
}
12631319
}

0 commit comments

Comments
 (0)