EDIT: not all Android users experience it, and it doesn't happen on every startup, it occurs once in a while
Hi, this exception is from a MAUI 10.0.70 app using ArcGIS Maps SDK 300.0.0.
Many of our Android users experience this one, and it happens at app startup. Well before any IWindowManagerInvoker is expected to be disposed of.
The app initializes MapView.LocationDisplay on startup with default data source. Initialization happens at MapView.Loaded event.
android.runtime.JavaProxyThrowable: [System.ObjectDisposedException]: Cannot access disposed object with JniIdentityHashCode=48158090.
Object name: 'Android.Views.IWindowManagerInvoker'.
at Android.Views.IWindowManagerInvoker.get_DefaultDisplay + 0x0(Unknown Source)
at Esri.ArcGISRuntime.Location.AndroidCompassProvider.Android.Hardware.ISensorEventListener.OnSensorChanged + 0x0(Unknown Source)
at Android.Hardware.ISensorEventListenerInvoker.n_OnSensorChanged_Landroid_hardware_SensorEvent_ + 0x0(Unknown Source)
at crc64f261feee1d215ead.AndroidCompassProvider.n_onSensorChanged(Native Method)
at crc64f261feee1d215ead.AndroidCompassProvider.onSensorChanged(AndroidCompassProvider.java:37)
at android.hardware.SystemSensorManager$SensorEventQueue.dispatchSensorEvent(SystemSensorManager.java:1203)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.nextLegacy(MessageQueue.java:985)
at android.os.MessageQueue.next(MessageQueue.java:1094)
at android.os.Looper.loopOnce(Looper.java:222)
at android.os.Looper.loop(Looper.java:392)
at android.app.ActivityThread.main(ActivityThread.java:10346)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:638)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:972)
PS: Would it be an idea to wrap the compass provider code (and similar code) in try/catch to avoid tearing down the whole app? Or perhaps route the exception through a mechanism akin to TaskScheduler.UnobservedTaskException and possibility to use SetObserved().
Hi,
Our app initializes MapView.LocationDisplay with default data source on OnPageLoaded event. It works without issues.
This error may trigger due to the lifecycle of the app, in case of pause/resume. Claude suggest that the IWindowManagerInvoker may be cached in a .NET class field, and become garbage collected on the Java side while on the .NET side an active reference is kept, to what is then a disposed object. That could explain the JNI details in the exception. Other reasons could be improper usage of JavaCast.
Claude also identified the Android WindowManager getDefaultDisplay to be a deprecated API at Android API level 30 / Android 11 (September 2020). Please see WindowManager | API reference | Android Developers
SystemLocationDataSource on Android can malfunction because its internal AndroidCompassProvider obtains an IWindowManager from the Android application context instead of an activity context. The application context is not guaranteed to be associated with a window, so the display properties retrieved from it may not reflect the actual display/rotation of the visible activity, leading to incorrect compass alignment and/or crashes due to disposed object.
SystemLocationDataSource
└── AndroidCompassProvider (private field)
└── IWindowManager (private field)
The IWindowManager instance is used to query device display properties, which are then used to align the compass direction.
The IWindowManager is created from the Android application context. Because the application context is not guaranteed to be tied to a window, the display information it returns can be wrong. The instance should instead be created from an activity context, which is associated with an actual window and display.
Timing is critical: the replacement must be performed after SystemLocationDataSource.StartAsync() completes, because StartAsync() instantiates a new AndroidCompassProvider. The provider is set to null on StopAsync(), so the workaround must be re-applied after every restart.
Note that IWindowManager.getDisplay() is deprecated precisely because of this class of problem. The recommended approach is to migrate to the newer display APIs rather than continuing to rely on the deprecated call.
Hi @GKmieliauskas The above workaround solves the problem for our MAUI application. Verified by Sentry monitoring.
Also, ESRI support case #04216208 has been registered on this issue.