microg/GmsCore · error · UnsupportedOperationException

onDestroyView not allowed on MapViewDelegate

Error message

onDestroyView not allowed on MapViewDelegate

What it means

MapViewDelegate.onDestroyView() is another intentionally unsupported lifecycle hook: view teardown is owned by MapView/container, not the delegate. Any invocation throws UnsupportedOperationException unconditionally. Lifecycle must be driven through MapView's onDestroy (or onDestroyView on the owning view), never directly on this delegate.

Source

Thrown at play-services-maps/src/main/java/org/microg/gms/maps/MapViewDelegate.java:65

            container.removeAllViews();
            container.addView(view);
        } catch (RemoteException e) {
            throw new RuntimeRemoteException(e);
        }
    }

    @Override
    public void onDestroy() {
        try {
            delegate.onDestroy();
        } catch (RemoteException e) {
            throw new RuntimeRemoteException(e);
        }
    }

    @Override
    public void onDestroyView() {
        throw new UnsupportedOperationException("onDestroyView not allowed on MapViewDelegate");
    }

    public void onEnterAmbient(Bundle bundle) {
        try {
            Bundle temp = new Bundle();
            MapsBundleHelper.transfer(bundle, temp);
            delegate.onEnterAmbient(temp);
            MapsBundleHelper.transfer(temp, bundle);
        } catch (RemoteException e) {
            throw new RuntimeRemoteException(e);
        }
    }

    public void onExitAmbient() {
        try {
            delegate.onExitAmbient();
        } catch (RemoteException e) {
            throw new RuntimeRemoteException(e);

View on GitHub (pinned to 157c9d86ac)

Solutions

  1. Call mapView.onDestroy() (or the owner's view destruction) instead of delegate.onDestroyView().
  2. Remove onDestroyView forwarding from your Fragment; let MapView handle its own teardown.
  3. Only forward the lifecycle callbacks MapView exposes publicly.
  4. If using MapFragment/SupportMapFragment, rely on the fragment lifecycle rather than touching delegates at all.

Example fix

// before
@Override
public void onDestroyView() {
    delegate.onDestroyView(); // always throws
}
// after
@Override
public void onDestroyView() {
    mapView.onDestroy();
}
Defensive patterns

Strategy: type-guard

Type guard

public static boolean supportsDestroyView(LifecycleDelegate d) {
    return !(d instanceof MapViewDelegate);
}

Try / catch

try {
    delegate.onDestroyView();
} catch (UnsupportedOperationException e) {
    mapView.onDestroy(); // correct teardown path
}

Prevention

When it happens

Trigger: Calling mapViewDelegate.onDestroyView() directly, or a Fragment/ custom view whose onDestroyView() forwards to the delegate instead of mapView.onDestroy().

Common situations: Fragment-based map embedding with hand-rolled lifecycle forwarding, code copied from Google Maps internal usage, or generic lifecycle-dispatch frameworks that enumerate all LifecycleDelegate methods.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of microg/GmsCore@157c9d86ac (2026-09-06). Data as JSON: /api/errors/e9c7bc52961acbae. Report an issue: GitHub.