Repository navigation
Register the Android wrapper before launch - #9
Conversation
Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Stale comment
Deep review: Register the Android wrapper before launch
The approach is the right one for 7.x crash recovery.
BugseeInitProviderisinitOrder="100"andautoLaunch/handleRespawnAutoLaunchrun in thatonCreate. A siblingContentProvideratinitOrder="200"callingBugsee.setWrappermatches Bugsee's own NDK extension (BugseeNdkInitProvider) and the documented custom-extension pattern. C# no longer callingsetWrapperis correct: a JNIAndroidJavaProxycannot exist before the engine is up. I checked plugin 4.0.8:removeExtensionInitProvidersonly drops the knownBugsee*InitProviderFQNs (NDK, OkHttp, Feedback, …), soUnityWrapperProvideris not stripped.
Bugsee.Launchstill depends on the new Java type being in the APK (refineContextis a fallbackinstall()as well as a context fill). That makes packaging and minify keep-rules load-bearing.Overall risk: Medium
Merge recommendation: Request changesMust fix
- P1 — Commit PluginImporter
.metafiles forUnityWrapperProvider.javaandAndroidManifest.xml(same shape asUnityManagedException.java.meta). Without them a UPM git install can omit the class and/or the provider, so either the process crashes on the manifest entry orBugsee.Launchthrows.- P2 — Mark the provider
android:directBootAware="true"so it still runs in the same Direct Boot window asBugseeInitProvider.- P2 — Keep
com.bugsee.unity.UnityWrapper.refineContext(and the class) from R8. Minify currently breaks the C# JNI call onLaunch.Also worth doing
- P3
getWrapperBuild()is hardcoded"unknown". iOS and the old C#BugseeWrapperProxyboth publishedBugseePackageVersion.Build. Pass build throughrefineContext.- The new source test looks for
initOrderin a Java comment and never opensAndroidManifest.xml, so it cannot catch a droppedandroid:initOrder="200".I decompiled
bugsee-android:7.3.0and gradle plugin4.0.8for init order, wrapper defaults, and the strip list.dotnetis not in this environment; I did not runRegistrationSourceTests.What looks good
initOrder200 vs core 100 is the correct ordering for respawn recovery.refineContext→install()is a real fallback if the provider did not run.exported="false", package-private helper + public provider, and avoiding theBugsee*InitProviderFQN are all sound.- App
setReportHandler/setLifecycleEventsListenerstay on the C# proxies; the Java stubs completing immediately match the oldBugseeWrapperProxyand are appropriate before the engine is up.Sent by Cursor Automation: Bugsee code review
Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Deep review: Register the Android wrapper before launch
3cb678d addresses the previous packaging / Direct Boot / R8 findings. The 7.x crash-recovery shape is still right: BugseeInitProvider is initOrder="100" and runs autoLaunch / handleRespawnAutoLaunch in onCreate; a sibling provider at 200 calling Bugsee.setWrapper matches BugseeNdkInitProvider. Plugin 4.0.8 ExtensionSpec.fromInitProviderFqn only consolidates the known com.bugsee.library.Bugsee*InitProvider FQNs, so com.bugsee.unity.UnityWrapperProvider is left in the merged manifest. C# only calling refineContext is correct — a JNI AndroidJavaProxy cannot exist before the engine is up.
I re-checked Bugsee.setWrapper (stores the instance on BugseeEnvironment and is safe before core init), getSecureRectangles ({1,0} takes the same empty-wrapper path as the interface default null; it does not wipe addSecureRectangle areas), and the new PluginImporter .meta files against UnityManagedException.java.meta.
No remaining P0–P2. Two P3s below.
Overall risk: Low
Merge recommendation: Approve
Prior findings (now addressed)
- P1 PluginImporter
.metafor the Java + manifest — shipped, Android-only, overridable. - P2
android:directBootAware="true"— shipped. - P2 R8 keep for
UnityWrapper.refineContext—Plugins/Android/bugsee-unity-wrapper.proguard(Unity picks up*.proguardfrom that folder).
Residual (non-blocking)
- P3
getWrapperBuild()is still hardcoded"unknown"after Launch. iOS and the old C#BugseeWrapperProxypublishedBugseePackageVersion.Build. Android 7.3.0J0copies type/version/build into$$WRAPPER. - P3
RegistrationSourceTestsstill looks forinitOrderin a Java comment and never opensAndroidManifest.xml. - Leftover:
_wrapperContextRefined = trueis still set before the JNI call. Harmless if packaging/minify stay correct; a thrownrefineContextstill suppresses retry.
I decompiled bugsee-android:7.3.0 and gradle plugin 4.0.8 for init order, setWrapper, secure-rect merge, and the strip list. dotnet is not in this environment; I did not run RegistrationSourceTests.
What looks good
initOrder200 vs core 100, plus Direct Boot, matches NDK and is the correct ordering for respawn recovery.refineContext→install()is a real fallback if the provider did not run.exported="false", package-private helper + public provider, and avoiding theBugsee*InitProviderFQN are all sound.- App
setReportHandler/setLifecycleEventsListenerstay on the C# proxies; the Java stubs completing immediately match the oldBugseeWrapperProxyand are appropriate before the engine is up.
Sent by Cursor Automation: Bugsee code review
| @Override | ||
| public String getWrapperBuild() { | ||
| return "unknown"; |
There was a problem hiding this comment.
Severity: P3 Low
Problem: getWrapperBuild() is hardcoded "unknown". refineContext updates wrapperVersion but has no build argument, so this stays "unknown" for the life of the process — including after Bugsee.Launch.
Impact: Android 7.3.0 copies getWrapperType / getWrapperVersion / getWrapperBuild into the $$WRAPPER session option. iOS (_bugsee_ensure_wrapper(Version, Build)) and the old C# BugseeWrapperProxy both published BugseePackageVersion.Build ("dev" today). Android reports will disagree with iOS on wrapper identity.
Scenario: Launch on device, then any report/crash. Session metadata shows wrapper version 0.1.0 and build unknown. Same app on iOS shows build dev.
Fix: Add a wrapperBuild field (default "unknown"), pass BugseePackageVersion.Build as a sixth refineContext argument, and return it from getWrapperBuild(). Extend the proguard keep signature to match.
| string java = File.ReadAllText(RepoFile("Plugins/Android/UnityWrapperProvider.java")); | ||
| Assert.That(Regex.IsMatch(java, @"class\s+Bugsee[A-Za-z0-9_]+InitProvider\b"), Is.False); | ||
| Assert.That(java, Does.Contain("class UnityWrapperProvider")); | ||
| Assert.That(java, Does.Contain("initOrder")); |
There was a problem hiding this comment.
Severity: P3 Low
Problem: This assertion is satisfied by the // initOrder 200 comment in UnityWrapperProvider.java. The load-bearing values are on the provider element in Plugins/Android/AndroidManifest.xml (android:initOrder="200", android:directBootAware="true"). The test never opens that file.
Impact: Dropping or lowering android:initOrder (so this provider runs after BugseeInitProvider at 100) still passes CI, and crash recovery can assemble a session without wrapperType=unity. Same for losing directBootAware.
Scenario: Someone removes the comment as noise, or changes the manifest to 100 / omits directBootAware, and leaves the Java class name alone. Provider_class_name_survives_the_gradle_plugin_strip stays green.
Fix: Read AndroidManifest.xml and assert android:initOrder="200", android:directBootAware="true", and the provider FQN. Keep the Bugsee*InitProvider name check on the Java source.


Summary
UnityWrapperProvideratinitOrder200 callssetWrapperbefore the SDK launches. The class name is not stripped by the Gradle plugin.refineContext, which installs the same instance if the provider has not run yet.Test plan
DOTNET_ROLL_FORWARD=LatestMajor dotnet test Tests~/WrapperPolicy/Bugsee.WrapperPolicy.Tests.csproj --filter RegistrationSourceTestsMade with Cursor