.NET MAUI mobile SDK for Honua Server -- offline-first field data collection with GeoPackage storage, gRPC transport, dynamic forms, and background sync.
Current mobile SDK roadmap coordination is tracked from honua-server#811 and the mobile SDK roadmap. The current source-backed mobile feature map is in docs/features/README.md.
| Layer | Status | Run on | Coverage |
|---|---|---|---|
| Unit | ✅ | every PR | Across 5 .NET projects (SDK, Offline, Field, FieldCollection, MAUI) |
| Integration (in-process loopback) | ✅ | every PR | Honua.Mobile.ServerIntegration.Tests (SdkServerIntegrationTests, OfflineServerIntegrationTests, FieldCollectionServerIntegrationTests) against a real ASP.NET Core loopback server; the same project also hosts the LiveHonuaServerFixtureOptionsTests harness-config tests |
| Smoke | ✅ | every PR | Honua.Mobile.Smoke.Tests (quality-gates job) |
| Embed DOM | ✅ | every PR | jsdom suites under src/Honua.Embed/tests/ |
| Live server (Docker image) | ✅ | every PR via Live Server Integration workflow (hard gate; vendored seed at tests/seed/mobile-offline-demo-v1.sql) |
LiveHonuaServerInteractionTests (incl. unary + server-streaming live gRPC); Testcontainers spins up honuaio/honua-server:nightly + PostGIS, vendored seed loaded into postgres before the live server starts |
| Cloud acceptance (staging) | 🟡 | manual workflow_dispatch |
DisconnectedFieldWorkflowAcceptanceTests; production promotion blocked on honua-server#965 |
| Physical device | 🟡 | deferred to GA | AR/VR field workflow tracked under honua-mobile#23 (closed, follow-ups in docs/guides/native-scene-anchoring-requirements.md); emulator/simulator platform smoke covers part of the surface |
Exact test counts are intentionally not pinned here (they drift every PR); the authoritative numbers are the per-project totals reported by each CI run.
See docs/guides/validation-strategy.md for the per-capability coverage matrix, known gaps, and which CI workflow runs which bucket.
| Package | Purpose |
|---|---|
| Honua.Mobile.Sdk | Transport, auth, gRPC-first client, REST fallback, routing, and SDK scene metadata adapter |
| Honua.Mobile.Offline | GeoPackage storage, sync queue, map area download, conflict resolution |
| Honua.Mobile.Maui | MAUI service registration, DI extensions, native display boundaries, native scene anchoring, and device location orchestration |
| @honua/embed | Framework-agnostic <honua-map> and <honua-scene> web components for ISV embeds |
// In MauiProgram.cs
using Honua.Mobile.Maui;
using Honua.Mobile.Offline.GeoPackage;
using Honua.Mobile.Offline.Sync;
using Honua.Mobile.Sdk;
builder.Services
.AddHonuaMobilePlatformAuth()
.AddHonuaMobileSdk(new HonuaMobileClientOptions
{
BaseUri = new Uri("https://your-honua-server.com"),
GrpcEndpoint = new Uri("https://your-honua-server.com"),
PreferGrpcForFeatureQueries = true,
})
.AddHonuaRouting()
.AddHonuaScenes()
.AddHonuaApiOfflineUploader()
.AddHonuaMobileFieldCollection()
.AddHonuaGeoPackageOfflineSync(
new GeoPackageSyncStoreOptions
{
DatabasePath = Path.Combine(FileSystem.Current.AppDataDirectory, "honua-offline.gpkg"),
},
new OfflineSyncEngineOptions
{
ConflictStrategy = SyncConflictStrategy.ClientWins,
BatchSize = 50,
})
.AddHonuaMapAreaDownload()
.AddHonuaBackgroundSync();After sign-in or bootstrap, store the API key or bearer token with IAuthTokenProvider.StoreTokenAsync(...);
the platform auth registration persists it in iOS Keychain or Android secure storage.
GeoPackage-backed offline storage with queue-based sync:
- GeoPackage storage -- standards-compliant
.gpkgfiles (interoperable with QGIS, ArcGIS) - Sync queue -- queued edits with claim/lease semantics to prevent duplicate processing
- Conflict resolution -- ClientWins, ServerWins, or ManualReview strategies
- Background sync -- connectivity-aware with periodic timer and semaphore gating
- Map area download -- offline basemap packages with path traversal protection
- Delta sync -- replica-based incremental downloads with cursor persistence
- Cache governance -- per-layer TTL eviction and R-tree-backed bbox lookups for replicated features
- SDK-owned contracts --
Honua.Sdk.Fieldowns form schemas, validation, calculated fields, duplicate detection, and record workflow - Mobile capture adapters -- local media paths stay mobile-owned and convert to portable SDK attachment metadata before sync
- Validation and workflow DI --
AddHonuaMobileFieldCollection()registers a mobile adapter over SDK field services
gRPC-first with automatic REST fallback:
var request = new QueryFeaturesRequest
{
ServiceId = serviceId,
LayerId = layerId,
Where = "1=1",
OutFields = new[] { "*" },
};
using var features = await client.QueryFeaturesAsync(request);
await foreach (var page in client.QueryFeaturesStreamAsync(request))
{
using (page)
{
ProcessFeaturePage(page.RootElement);
}
}Transport security enforced -- API keys and bearer tokens are never sent over HTTP
unless AllowInsecureTransportForDevelopment is explicitly set.
Experimental GeoServices-compatible NAServer client for directions, service areas, closest facility, and route optimization:
var route = await client.Routing.GetDirectionsAsync(
RoutingLocation.FromLatitudeLongitude(21.3069, -157.8583, "Start"),
RoutingLocation.FromLatitudeLongitude(21.2810, -157.8037, "Finish"));
var optimized = await client.Routing.Route()
.From(currentLocation)
.Via(jobSite)
.To(depot)
.WithTraffic()
.AvoidTolls()
.ExecuteAsync();
var reachable = await client.Routing.GetServiceAreaAsync(depot, TimeSpan.FromMinutes(30));Scene discovery resolves server-managed 3D Tiles and terrain URLs before a renderer loads them:
using Honua.Sdk.Abstractions.Scenes;
var scene = await client.Scenes.ResolveSceneAsync(
"downtown-honolulu",
new HonuaSceneResolveRequest
{
RequiredCapabilities = new[] { HonuaSceneCapabilities.ThreeDimensionalTiles },
});
var tilesetUrl = scene.TilesetUrl;
var terrainUrl = scene.TerrainUrl;src/
Honua.Embed/ Embeddable map web component package
tests/ Web component DOM behavior tests
Honua.Mobile.Sdk/ Core mobile client
Honua.Mobile.Offline/ GeoPackage sync engine
Honua.Mobile.Maui/ MAUI platform integration, native display, location, and scene anchoring
apps/
Honua.Mobile.App/ Reference MAUI application
tests/
Honua.Mobile.Sdk.Tests/ HTTP client, transport security, gRPC translation, routing, scenes
Honua.Mobile.FieldCollection.Tests/ FieldCollection auth, sync, storage, diagnostics
Honua.Mobile.ServerIntegration.Tests/ Loopback and opt-in live Honua image integration surface
Honua.Mobile.Offline.Tests/ Sync engine, conflicts, map download, GeoPackage
Honua.Mobile.Maui.Tests/ MAUI integration helpers, map annotations, native display, location, scene anchoring
Honua.Mobile.Smoke.Tests/ End-to-end smoke paths and optional live Honua query
proto/
honua/v1/ gRPC protocol definitions
Fresh checkouts need access to the private Honua GitHub Packages feed for
Honua.Sdk.* packages. Use a GitHub token that can read packages in the
honua-io organization:
gh auth refresh -s read:packages
export HONUA_GITHUB_PACKAGES_USER="$(gh api user --jq .login)"
export HONUA_GITHUB_PACKAGES_TOKEN="$(gh auth token)"Then run the local validation baseline:
scripts/validate-local.shThe script restores, builds, runs .NET tests and smoke tests, verifies format
for the core source projects, and runs the @honua/embed npm build/tests. It
uses a temporary NuGet config for HONUA_GITHUB_PACKAGES_TOKEN and removes it
on exit. Without those environment variables it falls back to any existing
NuGet credentials already configured for the github-honua source.
Equivalent manual commands:
dotnet restore Honua.Mobile.sln
dotnet build Honua.Mobile.sln
dotnet test Honua.Mobile.sln
dotnet test tests/Honua.Mobile.Smoke.Tests/Honua.Mobile.Smoke.Tests.csproj
npm ci --prefix src/Honua.Embed
npm run build --prefix src/Honua.Embed
npm test --prefix src/Honua.EmbedBuilding Android targets requires a configured Android SDK. The library projects
(Sdk, Field, Offline, Maui) target net10.0 and build on any platform
without the MAUI workload.
The server integration project starts a real ASP.NET Core loopback server and
exercises the implemented SDK, offline, FieldCollection auth, and mobile
exception-reporting HTTP paths without requiring external infrastructure. It
also includes opt-in live Honua image tests that use Testcontainers or a
pre-started Honua URL when HONUA_MOBILE_LIVE_SERVER_TESTS=1 is set; see
docs/guides/offline-sync.md.
The smoke test project can also run an optional live Honua query when
HONUA_MOBILE_SMOKE_BASE_URL, HONUA_MOBILE_SMOKE_SERVICE_ID,
HONUA_MOBILE_SMOKE_LAYER_ID, and optionally HONUA_MOBILE_SMOKE_API_KEY are
set.
Release workflow, branch-protection, package metadata, Dependabot, Trivy, and platform smoke guardrails for honua-server #826 are documented in Repo Scaffolding Gates.
The Live Server Integration workflow
(.github/workflows/live-server-integration.yml) runs
LiveHonuaServerInteractionTests against a Docker-hosted Honua server stack
on every PR and on pushes to main. See
Disconnected Field Workflow Harness
for scope, triggers, and the seed-SQL gap.
Production-ready foundation for offline sync, forms, and gRPC transport. .NET test coverage across SDK, Field, FieldCollection, server integration, Offline, MAUI, and Smoke projects, plus DOM tests for the embeddable map package.
- Getting Started -- installation, tutorial, and developer checklist
- Guides -- in-depth guides for offline sync, security, camera, performance, and more
- SDK Contract Stability Roadmap -- exit criteria for moving Honua.Sdk.* from alpha to beta to stable
- API Reference -- core SDK API documentation