From b77da1ac78e88e28a4efb2e507e4eb70e85bf55f Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Fri, 13 Feb 2026 17:12:43 +0100 Subject: [PATCH 01/13] First iteration --- modules/app-runner | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/app-runner b/modules/app-runner index 0f3a63a67..210bbebe2 160000 --- a/modules/app-runner +++ b/modules/app-runner @@ -1 +1 @@ -Subproject commit 0f3a63a67aeead62b004e1d1548ffe47dc630fb6 +Subproject commit 210bbebe2563bbec1e41b52d9221a3cea20a65c7 From 7937962ee42f9deadbefbf5d1d30b75c7ca3fbba Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Mon, 16 Feb 2026 11:35:33 +0100 Subject: [PATCH 02/13] strictmode workaround --- test/IntegrationTest/Integration.Tests.ps1 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/IntegrationTest/Integration.Tests.ps1 b/test/IntegrationTest/Integration.Tests.ps1 index a07a897bc..39f401954 100644 --- a/test/IntegrationTest/Integration.Tests.ps1 +++ b/test/IntegrationTest/Integration.Tests.ps1 @@ -9,6 +9,9 @@ Set-StrictMode -Version latest $ErrorActionPreference = "Stop" +$global:DebugPreference = "Continue" + +. $PSScriptRoot/../Scripts.Integration.Test/common.ps1 # Import app-runner modules . $PSScriptRoot/../../modules/app-runner/import-modules.ps1 From e3592ca014118987ffd51ff6f59fbce364f52b13 Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Mon, 16 Feb 2026 14:27:58 +0100 Subject: [PATCH 03/13] . --- test/IntegrationTest/Integration.Tests.ps1 | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/IntegrationTest/Integration.Tests.ps1 b/test/IntegrationTest/Integration.Tests.ps1 index 39f401954..6a7a9cc0e 100644 --- a/test/IntegrationTest/Integration.Tests.ps1 +++ b/test/IntegrationTest/Integration.Tests.ps1 @@ -11,8 +11,6 @@ Set-StrictMode -Version latest $ErrorActionPreference = "Stop" $global:DebugPreference = "Continue" -. $PSScriptRoot/../Scripts.Integration.Test/common.ps1 - # Import app-runner modules . $PSScriptRoot/../../modules/app-runner/import-modules.ps1 From 4926cab5214d4dbd5a1a05c1b228aec5a6fea89c Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Mon, 16 Feb 2026 15:37:06 +0100 Subject: [PATCH 04/13] Debug log level --- test/IntegrationTest/Integration.Tests.ps1 | 1 - 1 file changed, 1 deletion(-) diff --git a/test/IntegrationTest/Integration.Tests.ps1 b/test/IntegrationTest/Integration.Tests.ps1 index 6a7a9cc0e..a07a897bc 100644 --- a/test/IntegrationTest/Integration.Tests.ps1 +++ b/test/IntegrationTest/Integration.Tests.ps1 @@ -9,7 +9,6 @@ Set-StrictMode -Version latest $ErrorActionPreference = "Stop" -$global:DebugPreference = "Continue" # Import app-runner modules . $PSScriptRoot/../../modules/app-runner/import-modules.ps1 From bbd7784b9c75a44944f8d8286a90a1112abdf3cd Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Mon, 16 Feb 2026 16:33:36 +0100 Subject: [PATCH 05/13] fallback to activity --- test/IntegrationTest/Integration.Tests.ps1 | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/test/IntegrationTest/Integration.Tests.ps1 b/test/IntegrationTest/Integration.Tests.ps1 index a07a897bc..8fb361e3e 100644 --- a/test/IntegrationTest/Integration.Tests.ps1 +++ b/test/IntegrationTest/Integration.Tests.ps1 @@ -30,7 +30,20 @@ BeforeAll { Write-Host "Running $Action..." $extras = @("-e", "test", $Action) - $runResult = Invoke-DeviceApp -ExecutablePath $script:AndroidComponent -Arguments $extras + + try { + $runResult = Invoke-DeviceApp -ExecutablePath $script:AndroidComponent -Arguments $extras + } + catch { + if ($_.Exception.Message -match "Activity class .* does not exist" -or $_.Exception.Message -match "Error type 3") { + Write-Host "Activity not found, trying fallback: $($script:FallbackAndroidComponent)" + $script:AndroidComponent = $script:FallbackAndroidComponent + $runResult = Invoke-DeviceApp -ExecutablePath $script:AndroidComponent -Arguments $extras + } + else { + throw + } + } # Save result to JSON file $runResult | ConvertTo-Json -Depth 5 | Out-File -FilePath (Get-OutputFilePath "${Action}-result.json") From 56bccd435a4eee73012180eb4170831a73ecb1ab Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Tue, 17 Feb 2026 10:15:34 +0100 Subject: [PATCH 06/13] Drop stripping level for older than 6 --- test/Scripts.Integration.Test/Editor/Builder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Scripts.Integration.Test/Editor/Builder.cs b/test/Scripts.Integration.Test/Editor/Builder.cs index c3f395e67..bb2ae779c 100644 --- a/test/Scripts.Integration.Test/Editor/Builder.cs +++ b/test/Scripts.Integration.Test/Editor/Builder.cs @@ -37,7 +37,7 @@ public static void BuildIl2CPPPlayer(BuildTarget target, BuildTargetGroup group, #endif Debug.Log("Builder: Configuring code stripping level"); -#if UNITY_2022_1_OR_NEWER +#if UNITY_6000_0_OR_NEWER PlayerSettings.SetManagedStrippingLevel(NamedBuildTarget.FromBuildTargetGroup(group), ManagedStrippingLevel.High); #else PlayerSettings.SetManagedStrippingLevel(NamedBuildTarget.FromBuildTargetGroup(group), ManagedStrippingLevel.Low); From a2fc02ce70b4ee8dcd5493cb2c89a06244108aef Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Thu, 19 Feb 2026 14:24:40 +0100 Subject: [PATCH 07/13] Mark crash-capture skipped tests as Skipped instead of silently passing --- test/IntegrationTest/CommonTestCases.ps1 | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/test/IntegrationTest/CommonTestCases.ps1 b/test/IntegrationTest/CommonTestCases.ps1 index b38fb675e..581a32d60 100644 --- a/test/IntegrationTest/CommonTestCases.ps1 +++ b/test/IntegrationTest/CommonTestCases.ps1 @@ -53,6 +53,11 @@ $CommonTestCases = @( @{ Name = "Contains user information"; TestBlock = { param($TestSetup, $TestType, $SentryEvent, $RunResult) + if ($TestType -eq "crash-capture") { + Set-ItResult -Skipped -Because "user context may not survive native crashes" + return + } + $SentryEvent.user | Should -Not -BeNullOrEmpty $SentryEvent.user.username | Should -Be "TestUser" $SentryEvent.user.email | Should -Be "user-mail@test.abc" @@ -62,6 +67,11 @@ $CommonTestCases = @( @{ Name = "Contains breadcrumbs"; TestBlock = { param($TestSetup, $TestType, $SentryEvent, $RunResult) + if ($TestType -eq "crash-capture") { + Set-ItResult -Skipped -Because "breadcrumbs may not survive native crashes" + return + } + $SentryEvent.breadcrumbs | Should -Not -BeNullOrEmpty $SentryEvent.breadcrumbs.values | Should -Not -BeNullOrEmpty } @@ -69,6 +79,11 @@ $CommonTestCases = @( @{ Name = "Contains expected breadcrumbs"; TestBlock = { param($TestSetup, $TestType, $SentryEvent, $RunResult) + if ($TestType -eq "crash-capture") { + Set-ItResult -Skipped -Because "breadcrumbs may not survive native crashes" + return + } + $SentryEvent.breadcrumbs.values | Should -Not -BeNullOrEmpty $SentryEvent.breadcrumbs.values | Where-Object { $_.message -eq "Integration test started" } | Should -Not -BeNullOrEmpty $SentryEvent.breadcrumbs.values | Where-Object { $_.message -eq "Context configuration finished" } | Should -Not -BeNullOrEmpty @@ -85,7 +100,7 @@ $CommonTestCases = @( param($TestSetup, $TestType, $SentryEvent, $RunResult) if ($TestType -eq "crash-capture") { - Set-ItResult -Skipped -Because "app context is not synced to sentry-native on Android" + Set-ItResult -Skipped -Because "app context may not be available for native crashes" return } @@ -106,6 +121,11 @@ $CommonTestCases = @( @{ Name = "Contains Unity context"; TestBlock = { param($TestSetup, $TestType, $SentryEvent, $RunResult) + if ($TestType -eq "crash-capture") { + Set-ItResult -Skipped -Because "Unity context may not be synchronized to NDK for native crashes" + return + } + $SentryEvent.contexts.unity | Should -Not -BeNullOrEmpty } } From ddc3965b588ed09a0c78861a8467763817799442 Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Thu, 19 Feb 2026 14:51:59 +0100 Subject: [PATCH 08/13] Extending the tests of scope sync to the crash tests --- test/IntegrationTest/CommonTestCases.ps1 | 25 ------------------------ 1 file changed, 25 deletions(-) diff --git a/test/IntegrationTest/CommonTestCases.ps1 b/test/IntegrationTest/CommonTestCases.ps1 index 581a32d60..682471972 100644 --- a/test/IntegrationTest/CommonTestCases.ps1 +++ b/test/IntegrationTest/CommonTestCases.ps1 @@ -53,11 +53,6 @@ $CommonTestCases = @( @{ Name = "Contains user information"; TestBlock = { param($TestSetup, $TestType, $SentryEvent, $RunResult) - if ($TestType -eq "crash-capture") { - Set-ItResult -Skipped -Because "user context may not survive native crashes" - return - } - $SentryEvent.user | Should -Not -BeNullOrEmpty $SentryEvent.user.username | Should -Be "TestUser" $SentryEvent.user.email | Should -Be "user-mail@test.abc" @@ -67,11 +62,6 @@ $CommonTestCases = @( @{ Name = "Contains breadcrumbs"; TestBlock = { param($TestSetup, $TestType, $SentryEvent, $RunResult) - if ($TestType -eq "crash-capture") { - Set-ItResult -Skipped -Because "breadcrumbs may not survive native crashes" - return - } - $SentryEvent.breadcrumbs | Should -Not -BeNullOrEmpty $SentryEvent.breadcrumbs.values | Should -Not -BeNullOrEmpty } @@ -79,11 +69,6 @@ $CommonTestCases = @( @{ Name = "Contains expected breadcrumbs"; TestBlock = { param($TestSetup, $TestType, $SentryEvent, $RunResult) - if ($TestType -eq "crash-capture") { - Set-ItResult -Skipped -Because "breadcrumbs may not survive native crashes" - return - } - $SentryEvent.breadcrumbs.values | Should -Not -BeNullOrEmpty $SentryEvent.breadcrumbs.values | Where-Object { $_.message -eq "Integration test started" } | Should -Not -BeNullOrEmpty $SentryEvent.breadcrumbs.values | Where-Object { $_.message -eq "Context configuration finished" } | Should -Not -BeNullOrEmpty @@ -99,11 +84,6 @@ $CommonTestCases = @( @{ Name = "Contains app context"; TestBlock = { param($TestSetup, $TestType, $SentryEvent, $RunResult) - if ($TestType -eq "crash-capture") { - Set-ItResult -Skipped -Because "app context may not be available for native crashes" - return - } - $SentryEvent.contexts.app | Should -Not -BeNullOrEmpty } } @@ -121,11 +101,6 @@ $CommonTestCases = @( @{ Name = "Contains Unity context"; TestBlock = { param($TestSetup, $TestType, $SentryEvent, $RunResult) - if ($TestType -eq "crash-capture") { - Set-ItResult -Skipped -Because "Unity context may not be synchronized to NDK for native crashes" - return - } - $SentryEvent.contexts.unity | Should -Not -BeNullOrEmpty } } From 92727f5c4143aa1b05516fdf24fc76fbce053b13 Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Thu, 19 Feb 2026 15:33:20 +0100 Subject: [PATCH 09/13] Skip app context assertion for crash-capture on Android --- test/IntegrationTest/CommonTestCases.ps1 | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/IntegrationTest/CommonTestCases.ps1 b/test/IntegrationTest/CommonTestCases.ps1 index 682471972..b38fb675e 100644 --- a/test/IntegrationTest/CommonTestCases.ps1 +++ b/test/IntegrationTest/CommonTestCases.ps1 @@ -84,6 +84,11 @@ $CommonTestCases = @( @{ Name = "Contains app context"; TestBlock = { param($TestSetup, $TestType, $SentryEvent, $RunResult) + if ($TestType -eq "crash-capture") { + Set-ItResult -Skipped -Because "app context is not synced to sentry-native on Android" + return + } + $SentryEvent.contexts.app | Should -Not -BeNullOrEmpty } } From a2cdbe664f412b846e486d19ea1c9de72d592c12 Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Thu, 19 Feb 2026 15:55:26 +0100 Subject: [PATCH 10/13] Propagating app context --- src/Sentry.Unity.Android/NativeContextWriter.cs | 7 ++++--- src/Sentry.Unity.Android/SentryJava.cs | 9 +++++++++ test/IntegrationTest/CommonTestCases.ps1 | 6 ------ test/Sentry.Unity.Android.Tests/TestSentryJava.cs | 2 ++ 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/Sentry.Unity.Android/NativeContextWriter.cs b/src/Sentry.Unity.Android/NativeContextWriter.cs index 7a4162145..9f688adc3 100644 --- a/src/Sentry.Unity.Android/NativeContextWriter.cs +++ b/src/Sentry.Unity.Android/NativeContextWriter.cs @@ -47,10 +47,9 @@ protected override void WriteScope( string? UnityRenderingThreadingMode ) { - // We're only setting the missing contexts, the rest is configured by sentry-java. We could also sync - // the "unity" context, but it doesn't seem so useful and the effort to do is larger because there's no - // class for it in Java - not sure how we could add a generic context object in Java... _sentryJava.WriteScope( + AppStartTime, + AppBuildType, GpuId, GpuName, GpuVendorName, @@ -67,6 +66,8 @@ protected override void WriteScope( GpuMultiThreadedRendering, GpuGraphicsShaderLevel); + CWUtil.WriteApp(AppStartTime, AppBuildType); + CWUtil.WriteGpu( GpuId, GpuName, diff --git a/src/Sentry.Unity.Android/SentryJava.cs b/src/Sentry.Unity.Android/SentryJava.cs index 883bdc2aa..91e7055b3 100644 --- a/src/Sentry.Unity.Android/SentryJava.cs +++ b/src/Sentry.Unity.Android/SentryJava.cs @@ -15,6 +15,8 @@ internal interface ISentryJava public bool? CrashedLastRun(); public void Close(); public void WriteScope( + string? AppStartTime, + string? AppBuildType, int? GpuId, string? GpuName, string? GpuVendorName, @@ -212,6 +214,8 @@ public void Init(SentryUnityOptions options) } public void WriteScope( + string? AppStartTime, + string? AppBuildType, int? GpuId, string? GpuName, string? GpuVendorName, @@ -230,6 +234,10 @@ public void WriteScope( { RunJniSafe(() => { + using var app = new AndroidJavaObject("io.sentry.protocol.App"); + app.SetIfNotNull("appStartTime", AppStartTime); + app.SetIfNotNull("buildType", AppBuildType); + using var gpu = new AndroidJavaObject("io.sentry.protocol.Gpu"); gpu.SetIfNotNull("name", GpuName); gpu.SetIfNotNull("id", GpuId); @@ -244,6 +252,7 @@ public void WriteScope( sentry.CallStatic("configureScope", new ScopeCallback(scope => { using var contexts = scope.Call("getContexts"); + contexts.Call("setApp", app); contexts.Call("setGpu", gpu); })); }); diff --git a/test/IntegrationTest/CommonTestCases.ps1 b/test/IntegrationTest/CommonTestCases.ps1 index b38fb675e..c34656851 100644 --- a/test/IntegrationTest/CommonTestCases.ps1 +++ b/test/IntegrationTest/CommonTestCases.ps1 @@ -83,12 +83,6 @@ $CommonTestCases = @( } @{ Name = "Contains app context"; TestBlock = { param($TestSetup, $TestType, $SentryEvent, $RunResult) - - if ($TestType -eq "crash-capture") { - Set-ItResult -Skipped -Because "app context is not synced to sentry-native on Android" - return - } - $SentryEvent.contexts.app | Should -Not -BeNullOrEmpty } } diff --git a/test/Sentry.Unity.Android.Tests/TestSentryJava.cs b/test/Sentry.Unity.Android.Tests/TestSentryJava.cs index a5c44e1bb..08dbe299c 100644 --- a/test/Sentry.Unity.Android.Tests/TestSentryJava.cs +++ b/test/Sentry.Unity.Android.Tests/TestSentryJava.cs @@ -22,6 +22,8 @@ public void Init(SentryUnityOptions options) { } public void Close() { } public void WriteScope( + string? AppStartTime, + string? AppBuildType, int? GpuId, string? GpuName, string? GpuVendorName, From 5bd85c814866536092a61fd47ef57ce1af23f8ed Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Thu, 19 Feb 2026 16:01:35 +0100 Subject: [PATCH 11/13] Updated CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f26f14ea3..494de7b67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - The SDK now also uses `.sentry-native` as a subdirectory for native support on desktop platforms. It now also falls back to `Application.persistentDataPath` instead of the current working directory. Note: `crashedLastRun` may report `false` for the first time after upgrading. ([#2547](https://github.com/getsentry/sentry-unity/pull/2547)) - The currently experimental Metrics are now opt-in by default ([#2546](https://github.com/getsentry/sentry-unity/pull/2546)) +- When targeting Android, the SDK now syncs `AppStartTime` and `AppBuildType` to the native layer ([#2557](https://github.com/getsentry/sentry-unity/pull/2557)) - When targeting Switch, the SDK will no longer cause the build to fail when native libraries are missing but log a warning instead ([#2541](https://github.com/getsentry/sentry-unity/pull/2541)) - The SDK no longer wrongly disables the org slug field based on assumed the auth-tolken type ([#2537](https://github.com/getsentry/sentry-unity/pull/2537)) From 7de94ab6cc6b4606b7a08cd40dc5789f4437bc6b Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Thu, 19 Feb 2026 17:07:46 +0100 Subject: [PATCH 12/13] Activity detection instead of try-catch --- test/IntegrationTest/Integration.Tests.ps1 | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/test/IntegrationTest/Integration.Tests.ps1 b/test/IntegrationTest/Integration.Tests.ps1 index 8fb361e3e..a07a897bc 100644 --- a/test/IntegrationTest/Integration.Tests.ps1 +++ b/test/IntegrationTest/Integration.Tests.ps1 @@ -30,20 +30,7 @@ BeforeAll { Write-Host "Running $Action..." $extras = @("-e", "test", $Action) - - try { - $runResult = Invoke-DeviceApp -ExecutablePath $script:AndroidComponent -Arguments $extras - } - catch { - if ($_.Exception.Message -match "Activity class .* does not exist" -or $_.Exception.Message -match "Error type 3") { - Write-Host "Activity not found, trying fallback: $($script:FallbackAndroidComponent)" - $script:AndroidComponent = $script:FallbackAndroidComponent - $runResult = Invoke-DeviceApp -ExecutablePath $script:AndroidComponent -Arguments $extras - } - else { - throw - } - } + $runResult = Invoke-DeviceApp -ExecutablePath $script:AndroidComponent -Arguments $extras # Save result to JSON file $runResult | ConvertTo-Json -Depth 5 | Out-File -FilePath (Get-OutputFilePath "${Action}-result.json") From 893e5fdd0211d8560a3450e545c98377a8375a65 Mon Sep 17 00:00:00 2001 From: bitsandfoxes Date: Wed, 25 Feb 2026 11:58:08 +0100 Subject: [PATCH 13/13] fixed app start time passing --- src/Sentry.Unity.Android/SentryJava.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Sentry.Unity.Android/SentryJava.cs b/src/Sentry.Unity.Android/SentryJava.cs index 91e7055b3..ca74d7668 100644 --- a/src/Sentry.Unity.Android/SentryJava.cs +++ b/src/Sentry.Unity.Android/SentryJava.cs @@ -235,7 +235,12 @@ public void WriteScope( RunJniSafe(() => { using var app = new AndroidJavaObject("io.sentry.protocol.App"); - app.SetIfNotNull("appStartTime", AppStartTime); + if (AppStartTime is not null) + { + var epochMs = DateTimeOffset.Parse(AppStartTime).ToUnixTimeMilliseconds(); + using var date = new AndroidJavaObject("java.util.Date", epochMs); + app.Set("appStartTime", date); + } app.SetIfNotNull("buildType", AppBuildType); using var gpu = new AndroidJavaObject("io.sentry.protocol.Gpu");