Summary
Xamarin.AndroidX.Navigation.Compose ships with the navigator classes bound (ComposeNavigator, DialogNavigator, their Destination types and *DestinationBuilder types) but none of the user-facing @Composable entry points are reachable from C#.
Specifically, the following *Kt wrapper classes are bound as empty containers — class declarations exist but they have zero static methods:
AndroidX.Navigation.Compose.NavHostKt — should expose NavHost(navController, startDestination, modifier, ...) { … }
AndroidX.Navigation.Compose.NavHostControllerKt — should expose rememberNavController(vararg navigators: Navigator<…>): NavHostController
AndroidX.Navigation.Compose.NavGraphBuilderKt — should expose NavGraphBuilder.composable(route, arguments, deepLinks, content) and NavGraphBuilder.dialog(…)
AndroidX.Navigation.Compose.DialogHostKt — should expose DialogHost(dialogNavigator)
AndroidX.Navigation.Compose.NavBackStackEntryProviderKt — should expose NavBackStackEntry.LocalOwnersProvider(saveableStateHolder, content)
This makes the entire navigation surface unusable without raw JNI: there is no way to build a nav graph, render a NavHost, or call composable("route") from bound API alone.
Library / NuGet
Verified state today (commit eb2f50b)
The PublicAPI.Unshipped.txt is 3,479 bytes total. Every Kt class binds as just:
AndroidX.Navigation.Compose.NavHostKt
override AndroidX.Navigation.Compose.NavHostKt.JniPeerMembers.get -> Java.Interop.JniPeerMembers!
Compare to what the Kotlin source actually exposes (e.g. https://developer.android.com/reference/kotlin/androidx/navigation/compose/package-summary):
| Method |
Class |
Status |
NavHost(NavHostController, String, …) { … } |
NavHostKt |
missing |
NavHost(NavHostController, NavGraph, …) |
NavHostKt |
missing |
rememberNavController(vararg Navigator<…>) |
NavHostControllerKt |
missing |
NavGraphBuilder.composable(String, …) |
NavGraphBuilderKt |
missing |
NavGraphBuilder.dialog(String, …) |
NavGraphBuilderKt |
missing |
NavGraphBuilder.navigation(String, String, …) |
NavGraphBuilderKt |
missing |
NavBackStackEntry.LocalOwnersProvider(…) |
NavBackStackEntryProviderKt |
missing |
DialogHost(DialogNavigator) |
DialogHostKt |
missing |
All of these have @Composable annotations. The empty-*Kt-wrapper pattern affects them even though they are not all hash-mangled — for example, androidx.compose.ui.res.PainterResources_androidKt.painterResource(Int, Composer, Int): Painter has no @JvmInline value class parameters yet is also dropped from its wrapper (see the companion Painter issue). The root cause is therefore unlikely to be only dotnet/java-interop#1440; there appears to be a separate binder rule dropping @Composable statics from *Kt wrappers in this Compose surface area.
Metadata.xml today
source/androidx.navigation/navigation-compose-android/Transforms/Metadata.xml contains only two managedReturn adjustments for createDestination. There are no <remove-node> entries that would explain why all the @Composable statics are dropped.
Reproduction / evidence
compose-net could not bind navigation at all via the binding. The compose-net tracking issue jonathanpeppers/compose-net#60 confirms this gap end-to-end. (No hand-written JNI bridge has been attempted in compose-net yet — the binding shape was inspected and found empty.)
Suggested fix
Investigate why the @Composable statics on NavHostKt, NavHostControllerKt, NavGraphBuilderKt, NavBackStackEntryProviderKt, and DialogHostKt are dropped — there is no Metadata.xml customization removing them, so the binder pipeline itself is filtering them out. Likely related to the @Composable annotation plus return type / receiver type metadata; possibly the same root cause as the painterResource drop (see the companion Painter issue).
If specific overloads must be reintroduced via add-node, that is acceptable as a tactical fix, but the underlying binder behaviour should be investigated since this also affects a large surface in material3 and the other Compose libraries.
Cross-references
- compose-net tracking: jonathanpeppers/compose-net#60
- Master inline-class blocker: dotnet/java-interop#1440 — relevant to some overloads with inline-class parameters (e.g.
Modifier, Dp) but the consistently empty *Kt wrappers across this binding suggest the root cause is a separate filter dropping @Composable statics independently of name mangling.
Summary
Xamarin.AndroidX.Navigation.Composeships with the navigator classes bound (ComposeNavigator,DialogNavigator, theirDestinationtypes and*DestinationBuildertypes) but none of the user-facing@Composableentry points are reachable from C#.Specifically, the following
*Ktwrapper classes are bound as empty containers — class declarations exist but they have zero static methods:AndroidX.Navigation.Compose.NavHostKt— should exposeNavHost(navController, startDestination, modifier, ...) { … }AndroidX.Navigation.Compose.NavHostControllerKt— should exposerememberNavController(vararg navigators: Navigator<…>): NavHostControllerAndroidX.Navigation.Compose.NavGraphBuilderKt— should exposeNavGraphBuilder.composable(route, arguments, deepLinks, content)andNavGraphBuilder.dialog(…)AndroidX.Navigation.Compose.DialogHostKt— should exposeDialogHost(dialogNavigator)AndroidX.Navigation.Compose.NavBackStackEntryProviderKt— should exposeNavBackStackEntry.LocalOwnersProvider(saveableStateHolder, content)This makes the entire navigation surface unusable without raw JNI: there is no way to build a nav graph, render a
NavHost, or callcomposable("route")from bound API alone.Library / NuGet
androidx.navigation:navigation-compose-androidXamarin.AndroidX.Navigation.Compose.Android(+ facadeXamarin.AndroidX.Navigation.Compose)source/androidx.navigation/navigation-compose-android/Verified state today (commit eb2f50b)
The
PublicAPI.Unshipped.txtis 3,479 bytes total. EveryKtclass binds as just:Compare to what the Kotlin source actually exposes (e.g. https://developer.android.com/reference/kotlin/androidx/navigation/compose/package-summary):
NavHost(NavHostController, String, …) { … }NavHostKtNavHost(NavHostController, NavGraph, …)NavHostKtrememberNavController(vararg Navigator<…>)NavHostControllerKtNavGraphBuilder.composable(String, …)NavGraphBuilderKtNavGraphBuilder.dialog(String, …)NavGraphBuilderKtNavGraphBuilder.navigation(String, String, …)NavGraphBuilderKtNavBackStackEntry.LocalOwnersProvider(…)NavBackStackEntryProviderKtDialogHost(DialogNavigator)DialogHostKtAll of these have
@Composableannotations. The empty-*Kt-wrapper pattern affects them even though they are not all hash-mangled — for example,androidx.compose.ui.res.PainterResources_androidKt.painterResource(Int, Composer, Int): Painterhas no@JvmInline value classparameters yet is also dropped from its wrapper (see the companion Painter issue). The root cause is therefore unlikely to be only dotnet/java-interop#1440; there appears to be a separate binder rule dropping@Composablestatics from*Ktwrappers in this Compose surface area.Metadata.xml today
source/androidx.navigation/navigation-compose-android/Transforms/Metadata.xmlcontains only twomanagedReturnadjustments forcreateDestination. There are no<remove-node>entries that would explain why all the@Composablestatics are dropped.Reproduction / evidence
compose-netcould not bind navigation at all via the binding. The compose-net tracking issue jonathanpeppers/compose-net#60 confirms this gap end-to-end. (No hand-written JNI bridge has been attempted in compose-net yet — the binding shape was inspected and found empty.)Suggested fix
Investigate why the
@Composablestatics onNavHostKt,NavHostControllerKt,NavGraphBuilderKt,NavBackStackEntryProviderKt, andDialogHostKtare dropped — there is no Metadata.xml customization removing them, so the binder pipeline itself is filtering them out. Likely related to the@Composableannotation plus return type / receiver type metadata; possibly the same root cause as thepainterResourcedrop (see the companion Painter issue).If specific overloads must be reintroduced via
add-node, that is acceptable as a tactical fix, but the underlying binder behaviour should be investigated since this also affects a large surface in material3 and the other Compose libraries.Cross-references
Modifier,Dp) but the consistently empty*Ktwrappers across this binding suggest the root cause is a separate filter dropping@Composablestatics independently of name mangling.