From 9ceae0d4dbc6af088f94ac5e7e507003a33cdbf7 Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Wed, 6 May 2026 13:55:01 +0200 Subject: [PATCH 1/9] Add experimental AndroidAnrV2Enabled option --- src/Sentry.Unity/SentryUnityOptions.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Sentry.Unity/SentryUnityOptions.cs b/src/Sentry.Unity/SentryUnityOptions.cs index 76235352a..3c726f424 100644 --- a/src/Sentry.Unity/SentryUnityOptions.cs +++ b/src/Sentry.Unity/SentryUnityOptions.cs @@ -214,6 +214,16 @@ public sealed class SentryUnityOptions : SentryOptions /// public NativeInitializationType AndroidNativeInitializationType { get; set; } = NativeInitializationType.Runtime; + /// + /// (Experimental) Enables ANR detection on Android through the native (sentry-java) SDK. + /// On API ≥ 30 this uses Android's ApplicationExitInfo to report ANRs detected by the OS + /// in prior runs (ANR v2). On API < 30, sentry-java falls back to its in-process watchdog, + /// which runs alongside the Unity SDK's C# ANR watchdog. The C# watchdog continues to run on all + /// API levels. + /// + /// This option is experimental and may change without notice. + public bool AndroidAnrV2Enabled { get; set; } = false; + /// /// Whether the SDK should add the NDK integration for Android /// From c8715f931820ebc109c2ed3de309c9b1d30ffaae Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Wed, 6 May 2026 15:36:35 +0200 Subject: [PATCH 2/9] Wire AndroidAnrV2Enabled into runtime SentryAndroid init --- src/Sentry.Unity.Android/SentryJava.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Sentry.Unity.Android/SentryJava.cs b/src/Sentry.Unity.Android/SentryJava.cs index 918acc746..c02a04779 100644 --- a/src/Sentry.Unity.Android/SentryJava.cs +++ b/src/Sentry.Unity.Android/SentryJava.cs @@ -148,7 +148,7 @@ public void Init(SentryUnityOptions options) androidOptions.Call("setAttachScreenshot", false); androidOptions.Call("setEnableAutoSessionTracking", false); androidOptions.Call("setEnableActivityLifecycleBreadcrumbs", false); - androidOptions.Call("setAnrEnabled", false); + androidOptions.Call("setAnrEnabled", options.AndroidAnrV2Enabled); androidOptions.Call("setEnableScopePersistence", false); // Disable user interaction tracking to prevent conflicts with VR platforms (e.g., Oculus InputHooks) androidOptions.Call("setEnableUserInteractionBreadcrumbs", false); From 6070435b888c5a90449a61b6e4a1176e3eb2a85a Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Wed, 6 May 2026 15:37:57 +0200 Subject: [PATCH 3/9] Test: AndroidAnrV2Enabled flows into AndroidManifest --- .../AndroidManifestConfigurationTests.cs | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/Sentry.Unity.Editor.Tests/Android/AndroidManifestConfigurationTests.cs b/test/Sentry.Unity.Editor.Tests/Android/AndroidManifestConfigurationTests.cs index e8cb9a54c..c0daab6a3 100644 --- a/test/Sentry.Unity.Editor.Tests/Android/AndroidManifestConfigurationTests.cs +++ b/test/Sentry.Unity.Editor.Tests/Android/AndroidManifestConfigurationTests.cs @@ -150,6 +150,32 @@ public void ModifyManifest_UnityOptions_AndroidNativeSupportEnabled_InitTypeBuil StringAssert.Contains($"", manifest); } + [Test] + public void ModifyManifest_AndroidAnrV2Enabled_True_WritesAnrEnableTrue() + { + _fixture.SentryUnityOptions!.AndroidAnrV2Enabled = true; + var sut = _fixture.GetSut(); + + var manifest = WithAndroidManifest(basePath => sut.ModifyManifest(basePath)); + + StringAssert.Contains( + "", + manifest); + } + + [Test] + public void ModifyManifest_AndroidAnrV2Enabled_False_WritesAnrEnableFalse() + { + _fixture.SentryUnityOptions!.AndroidAnrV2Enabled = false; + var sut = _fixture.GetSut(); + + var manifest = WithAndroidManifest(basePath => sut.ModifyManifest(basePath)); + + StringAssert.Contains( + "", + manifest); + } + [Test] public void ModifyManifest_ManifestHasDsn() { From 12afea90f9803158d741968e6edfd1f62cfb496e Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Wed, 6 May 2026 15:39:09 +0200 Subject: [PATCH 4/9] Wire AndroidAnrV2Enabled into AndroidManifest writer --- src/Sentry.Unity.Editor/Android/AndroidManifestConfiguration.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Sentry.Unity.Editor/Android/AndroidManifestConfiguration.cs b/src/Sentry.Unity.Editor/Android/AndroidManifestConfiguration.cs index 1c90cacb6..fd95ce23b 100644 --- a/src/Sentry.Unity.Editor/Android/AndroidManifestConfiguration.cs +++ b/src/Sentry.Unity.Editor/Android/AndroidManifestConfiguration.cs @@ -218,7 +218,7 @@ internal void ModifyManifest(string basePath) androidManifest.SetAutoTraceIdGeneration(false); androidManifest.SetAutoSessionTracking(false); androidManifest.SetAutoAppLifecycleBreadcrumbs(false); - androidManifest.SetAnr(false); + androidManifest.SetAnr(_options.AndroidAnrV2Enabled); androidManifest.SetPersistentScopeObserver(false); // Disable user interaction tracking to prevent conflicts with VR platforms (e.g., Oculus InputHooks) androidManifest.SetEnableUserInteractionBreadcrumbs(false); From 2322464a6513b5853976b0db086309db41841f24 Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Wed, 6 May 2026 15:40:47 +0200 Subject: [PATCH 5/9] Changelog: experimental AndroidAnrV2Enabled option --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 40aebeb17..159c440d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Features + +- Added experimental `AndroidAnrV2Enabled` option to enable ANR detection on Android through the native SDK. On Android API ≥ 30 this uses `ApplicationExitInfo` to report OS-detected ANRs from prior runs ([sentry-java ANR v2](https://docs.sentry.io/platforms/android/configuration/app-not-respond/)). Defaults to `false`; opt in via the `OptionsConfiguration.Configure(options)` callback. ([#TBD](https://github.com/getsentry/sentry-unity/pull/TBD)) + ### Fixes - The SDK no longer sends screenshot attachments for events that were dropped during processing (e.g., by `BeforeSend` or sampling) ([#2661](https://github.com/getsentry/sentry-unity/pull/2661)) From 4e76042949b9339f782643e10af26a8c72e390bb Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Wed, 6 May 2026 15:43:42 +0200 Subject: [PATCH 6/9] Move setAnrEnabled out of locked-down options block --- src/Sentry.Unity.Android/SentryJava.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Sentry.Unity.Android/SentryJava.cs b/src/Sentry.Unity.Android/SentryJava.cs index c02a04779..b4614e2f9 100644 --- a/src/Sentry.Unity.Android/SentryJava.cs +++ b/src/Sentry.Unity.Android/SentryJava.cs @@ -139,6 +139,7 @@ public void Init(SentryUnityOptions options) androidOptions.Call("setEnableNdk", options.NdkIntegrationEnabled); androidOptions.Call("setEnableScopeSync", options.NdkScopeSyncEnabled); androidOptions.Call("setNativeSdkName", "sentry.native.android.unity"); + androidOptions.Call("setAnrEnabled", options.AndroidAnrV2Enabled); // Options that are not to be set by the user // We're disabling some integrations as to not duplicate event or because the SDK relies on the .NET SDK @@ -148,7 +149,6 @@ public void Init(SentryUnityOptions options) androidOptions.Call("setAttachScreenshot", false); androidOptions.Call("setEnableAutoSessionTracking", false); androidOptions.Call("setEnableActivityLifecycleBreadcrumbs", false); - androidOptions.Call("setAnrEnabled", options.AndroidAnrV2Enabled); androidOptions.Call("setEnableScopePersistence", false); // Disable user interaction tracking to prevent conflicts with VR platforms (e.g., Oculus InputHooks) androidOptions.Call("setEnableUserInteractionBreadcrumbs", false); From e1fc67cee5d65391c38e0c66770c705687a66d62 Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Fri, 8 May 2026 08:48:28 +0200 Subject: [PATCH 7/9] v2 & friends --- src/Sentry.Unity.Android/SentryJava.cs | 5 +++- .../Android/AndroidManifestConfiguration.cs | 6 +++- src/Sentry.Unity/SentryUnityOptions.cs | 17 +++++++++++ .../AndroidManifestConfigurationTests.cs | 29 ++++++++++++++----- 4 files changed, 47 insertions(+), 10 deletions(-) diff --git a/src/Sentry.Unity.Android/SentryJava.cs b/src/Sentry.Unity.Android/SentryJava.cs index b4614e2f9..af9326735 100644 --- a/src/Sentry.Unity.Android/SentryJava.cs +++ b/src/Sentry.Unity.Android/SentryJava.cs @@ -139,7 +139,11 @@ public void Init(SentryUnityOptions options) androidOptions.Call("setEnableNdk", options.NdkIntegrationEnabled); androidOptions.Call("setEnableScopeSync", options.NdkScopeSyncEnabled); androidOptions.Call("setNativeSdkName", "sentry.native.android.unity"); + androidOptions.Call("setAnrEnabled", options.AndroidAnrV2Enabled); + androidOptions.Call("setEnableScopePersistence", options.AndroidAnrV2Enabled); + androidOptions.Call("setReportHistoricalAnrs", options.AndroidAnrV2Enabled && options.AndroidReportHistoricalAnrs); + androidOptions.Call("setAttachAnrThreadDump", options.AndroidAnrV2Enabled && options.AndroidAttachAnrThreadDump); // Options that are not to be set by the user // We're disabling some integrations as to not duplicate event or because the SDK relies on the .NET SDK @@ -149,7 +153,6 @@ public void Init(SentryUnityOptions options) androidOptions.Call("setAttachScreenshot", false); androidOptions.Call("setEnableAutoSessionTracking", false); androidOptions.Call("setEnableActivityLifecycleBreadcrumbs", false); - androidOptions.Call("setEnableScopePersistence", false); // Disable user interaction tracking to prevent conflicts with VR platforms (e.g., Oculus InputHooks) androidOptions.Call("setEnableUserInteractionBreadcrumbs", false); androidOptions.Call("setEnableUserInteractionTracing", false); diff --git a/src/Sentry.Unity.Editor/Android/AndroidManifestConfiguration.cs b/src/Sentry.Unity.Editor/Android/AndroidManifestConfiguration.cs index fd95ce23b..5e21f9827 100644 --- a/src/Sentry.Unity.Editor/Android/AndroidManifestConfiguration.cs +++ b/src/Sentry.Unity.Editor/Android/AndroidManifestConfiguration.cs @@ -219,7 +219,8 @@ internal void ModifyManifest(string basePath) androidManifest.SetAutoSessionTracking(false); androidManifest.SetAutoAppLifecycleBreadcrumbs(false); androidManifest.SetAnr(_options.AndroidAnrV2Enabled); - androidManifest.SetPersistentScopeObserver(false); + androidManifest.SetPersistentScopeObserver(_options.AndroidAnrV2Enabled); + androidManifest.SetAttachAnrThreadDump(_options.AndroidAnrV2Enabled && _options.AndroidAttachAnrThreadDump); // Disable user interaction tracking to prevent conflicts with VR platforms (e.g., Oculus InputHooks) androidManifest.SetEnableUserInteractionBreadcrumbs(false); androidManifest.SetEnableUserInteractionTracing(false); @@ -495,6 +496,9 @@ internal void SetAnr(bool enableAnr) internal void SetPersistentScopeObserver(bool enableScopePersistence) => SetMetaData($"{SentryPrefix}.enable-scope-persistence", enableScopePersistence.ToString()); + internal void SetAttachAnrThreadDump(bool attachAnrThreadDump) + => SetMetaData($"{SentryPrefix}.anr.attach-thread-dumps", attachAnrThreadDump.ToString()); + internal void SetNdkEnabled(bool enableNdk) => SetMetaData($"{SentryPrefix}.ndk.enable", enableNdk.ToString()); diff --git a/src/Sentry.Unity/SentryUnityOptions.cs b/src/Sentry.Unity/SentryUnityOptions.cs index 3c726f424..a5ee92b11 100644 --- a/src/Sentry.Unity/SentryUnityOptions.cs +++ b/src/Sentry.Unity/SentryUnityOptions.cs @@ -224,6 +224,23 @@ public sealed class SentryUnityOptions : SentryOptions /// This option is experimental and may change without notice. public bool AndroidAnrV2Enabled { get; set; } = false; + /// + /// (Experimental) When ANR v2 is enabled, controls whether sentry-java reports historical ANRs + /// recorded by the OS (ApplicationExitInfo) from prior runs. Has no effect when + /// is false. + /// + /// + /// Runtime-only. There is no AndroidManifest meta-data tag for this option, so it is only + /// applied when is . + /// + public bool AndroidReportHistoricalAnrs { get; set; } = true; + + /// + /// (Experimental) When ANR v2 is enabled, controls whether sentry-java attaches a thread dump + /// to ANR events. Has no effect when is false. + /// + public bool AndroidAttachAnrThreadDump { get; set; } = true; + /// /// Whether the SDK should add the NDK integration for Android /// diff --git a/test/Sentry.Unity.Editor.Tests/Android/AndroidManifestConfigurationTests.cs b/test/Sentry.Unity.Editor.Tests/Android/AndroidManifestConfigurationTests.cs index c0daab6a3..5e973a46d 100644 --- a/test/Sentry.Unity.Editor.Tests/Android/AndroidManifestConfigurationTests.cs +++ b/test/Sentry.Unity.Editor.Tests/Android/AndroidManifestConfigurationTests.cs @@ -151,29 +151,42 @@ public void ModifyManifest_UnityOptions_AndroidNativeSupportEnabled_InitTypeBuil } [Test] - public void ModifyManifest_AndroidAnrV2Enabled_True_WritesAnrEnableTrue() + public void ModifyManifest_AndroidAnrV2Enabled_True_WritesAnrV2MetadataEnabled() { _fixture.SentryUnityOptions!.AndroidAnrV2Enabled = true; var sut = _fixture.GetSut(); var manifest = WithAndroidManifest(basePath => sut.ModifyManifest(basePath)); - StringAssert.Contains( - "", - manifest); + StringAssert.Contains("", manifest); + StringAssert.Contains("", manifest); + StringAssert.Contains("", manifest); } [Test] - public void ModifyManifest_AndroidAnrV2Enabled_False_WritesAnrEnableFalse() + public void ModifyManifest_AndroidAnrV2Enabled_False_WritesAnrV2MetadataDisabled() { _fixture.SentryUnityOptions!.AndroidAnrV2Enabled = false; var sut = _fixture.GetSut(); var manifest = WithAndroidManifest(basePath => sut.ModifyManifest(basePath)); - StringAssert.Contains( - "", - manifest); + StringAssert.Contains("", manifest); + StringAssert.Contains("", manifest); + StringAssert.Contains("", manifest); + } + + [Test] + public void ModifyManifest_AndroidAttachAnrThreadDumpFalse_OverridesUmbrella() + { + _fixture.SentryUnityOptions!.AndroidAnrV2Enabled = true; + _fixture.SentryUnityOptions!.AndroidAttachAnrThreadDump = false; + var sut = _fixture.GetSut(); + + var manifest = WithAndroidManifest(basePath => sut.ModifyManifest(basePath)); + + StringAssert.Contains("", manifest); + StringAssert.Contains("", manifest); } [Test] From 0e153c33078496d17f541d9f3b4d4858df27f07e Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Fri, 8 May 2026 09:33:24 +0200 Subject: [PATCH 8/9] not experimental --- src/Sentry.Unity/SentryUnityOptions.cs | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/Sentry.Unity/SentryUnityOptions.cs b/src/Sentry.Unity/SentryUnityOptions.cs index a5ee92b11..4a7b9c506 100644 --- a/src/Sentry.Unity/SentryUnityOptions.cs +++ b/src/Sentry.Unity/SentryUnityOptions.cs @@ -215,18 +215,21 @@ public sealed class SentryUnityOptions : SentryOptions public NativeInitializationType AndroidNativeInitializationType { get; set; } = NativeInitializationType.Runtime; /// - /// (Experimental) Enables ANR detection on Android through the native (sentry-java) SDK. + /// Enables ANR detection on Android through the native (sentry-java) SDK. /// On API ≥ 30 this uses Android's ApplicationExitInfo to report ANRs detected by the OS - /// in prior runs (ANR v2). On API < 30, sentry-java falls back to its in-process watchdog, - /// which runs alongside the Unity SDK's C# ANR watchdog. The C# watchdog continues to run on all - /// API levels. + /// in prior runs (ANR v2). On API < 30, sentry-java falls back to its in-process watchdog. + /// The Unity SDK's C# ANR watchdog continues to run on all API levels. /// - /// This option is experimental and may change without notice. + /// + /// The Java and C# watchdogs observe different threads and are complementary: the Java watchdog + /// monitors the Android UI (Looper) main thread, while the C# watchdog monitors the Unity engine + /// main thread (the player loop). A hang that blocks both threads can produce one event from each. + /// public bool AndroidAnrV2Enabled { get; set; } = false; /// - /// (Experimental) When ANR v2 is enabled, controls whether sentry-java reports historical ANRs - /// recorded by the OS (ApplicationExitInfo) from prior runs. Has no effect when + /// When ANR v2 is enabled, controls whether sentry-java reports historical ANRs recorded by the + /// OS (ApplicationExitInfo) from prior runs. Has no effect when /// is false. /// /// @@ -236,8 +239,8 @@ public sealed class SentryUnityOptions : SentryOptions public bool AndroidReportHistoricalAnrs { get; set; } = true; /// - /// (Experimental) When ANR v2 is enabled, controls whether sentry-java attaches a thread dump - /// to ANR events. Has no effect when is false. + /// When ANR v2 is enabled, controls whether sentry-java attaches a thread dump to ANR events. + /// Has no effect when is false. /// public bool AndroidAttachAnrThreadDump { get; set; } = true; From 790b9fb04aac5354cf09ac0de9780dc3b26adc48 Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Fri, 8 May 2026 10:46:28 +0200 Subject: [PATCH 9/9] updated changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 11e981b6b..443d4d446 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ ### Features -- Added `AndroidNativeAnrEnabled` (default `false`) to enable ANR detection through the native (sentry-java) SDK, monitoring the Android UI (Looper) main thread. On API ≥ 30 this uses [ANR v2](https://docs.sentry.io/platforms/android/configuration/app-not-respond/) via `ApplicationExitInfo` to report OS-detected ANRs from prior runs; on API < 30 it falls back to an in-process watchdog. Complementary to the Unity SDK's C# watchdog, which monitors the Unity player loop. ([#TBD](https://github.com/getsentry/sentry-unity/pull/TBD)) +- Added `AndroidNativeAnrEnabled` (default `false`) to enable ANR detection through the native (sentry-java) SDK, monitoring the Android UI (Looper) main thread. On API ≥ 30 this uses [ANR v2](https://docs.sentry.io/platforms/android/configuration/app-not-respond/) via `ApplicationExitInfo` to report OS-detected ANRs from prior runs; on API < 30 it falls back to an in-process watchdog. Complementary to the Unity SDK's C# watchdog, which monitors the Unity player loop. ([#2671](https://github.com/getsentry/sentry-unity/pull/2671)) ### Dependencies