Skip to main content

DevHostBridge

Namespace: BlazorNative.Core

A full in-process mock of IMobileBridge for local development and tests — runs as a normal .NET app (no NativeAOT publish), with an in-memory key/value + secret store, route history, real-network HTTP passthrough, and settable status properties so every capability's denial-as-data paths are drivable headless.

public sealed class DevHostBridge : IMobileBridge, System.IDisposable

Inheritance ObjectDevHostBridge
Implements IMobileBridge, IDisposable
Attributes NullableContextAttribute, NullableAttribute

Properties

ClipboardSnapshot

Snapshot of the in-memory clipboard — useful in tests.

public string ClipboardSnapshot { get; }

Property Value

String

GeolocationStatus

The status the next DevHostBridge.GetCurrentPositionAsync(CancellationToken) returns (default GeolocationStatus.Granted). Set it to drive a denial / restriction / unavailable / error path headless.

public GeolocationStatus GeolocationStatus { get; set; }

Property Value

GeolocationStatus

GeolocationPosition

The fix returned when DevHostBridge.GeolocationStatus is Granted (Amsterdam by default). Ignored for every non-Granted status.

public GeolocationPosition GeolocationPosition { get; set; }

Property Value

GeolocationPosition

NotificationStatus

The status the next notification op returns (default NotificationStatus.Granted). Set it to drive a denial / restriction / error path headless.

public NotificationStatus NotificationStatus { get; set; }

Property Value

NotificationStatus

Notifications

The notifications recorded by DevHostBridge.ShowNotificationAsync(NotificationSpec, CancellationToken) / DevHostBridge.ScheduleNotificationAsync(NotificationSpec, CancellationToken) and not yet cancelled — useful in tests to assert schedule/show/cancel bookkeeping headless.

public IReadOnlyList<NotificationSpec> Notifications { get; }

Property Value

IReadOnlyList<NotificationSpec>

BiometricAuthResult

The status the next DevHostBridge.AuthenticateAsync(String, CancellationToken) returns AND the gate the pairing (DevHostBridge.GetSecretWithAuthAsync(String, String, CancellationToken)) checks: an auth-bound secret is released only when this is BiometricStatus.Authenticated, else the read is SecureStorageStatus.AuthFailed. Default Authenticated. Set it to drive a failed / cancelled / locked-out / no-hardware path headless.

public BiometricStatus BiometricAuthResult { get; set; }

Property Value

BiometricStatus

SecretSnapshot

Snapshot of the in-memory secret store — useful in tests.

public IReadOnlyDictionary<string, (string Value, bool RequireAuth)> SecretSnapshot { get; }

Property Value

IReadOnlyDictionary<String, (String, Boolean)>

CameraCaptureResult

The status the next DevHostBridge.CapturePhotoAsync(CaptureOptions, CancellationToken) returns (default CameraStatus.Captured) AND what DevHostBridge.CheckCameraAvailabilityAsync(CancellationToken) reports (Unavailable → Unavailable, else Captured = "present + usable"). Set it to drive a cancel / denied / unavailable / error path headless.

public CameraStatus CameraCaptureResult { get; set; }

Property Value

CameraStatus

CameraCapturedPath

The file:// path a Captured result returns (default the canned fixture). Settable so a test can point the composition at another path.

public string? CameraCapturedPath { get; set; }

Property Value

String

CameraCapturedWidth

The final dimensions / size a Captured result reports (default the fixture's). Ignored for every non-Captured status.

public int CameraCapturedWidth { get; set; }

Property Value

Int32

CameraCapturedHeight

The final dimensions / size a Captured result reports (default the fixture's). Ignored for every non-Captured status.

public int CameraCapturedHeight { get; set; }

Property Value

Int32

CameraCapturedSizeBytes

The final dimensions / size a Captured result reports (default the fixture's). Ignored for every non-Captured status.

public long CameraCapturedSizeBytes { get; set; }

Property Value

Int64

PlatformInfo

Platform info as a raw JSON string (the WASM-era sync shape). Prefer IMobileBridge.GetPlatformInfoAsync(CancellationToken) for the typed form.

public string PlatformInfo { get; }

Property Value

String

StorageSnapshot

Snapshot of current storage — useful in tests.

public IReadOnlyDictionary<string, string> StorageSnapshot { get; }

Property Value

IReadOnlyDictionary<String, String>

RouteHistory

Full navigation history.

public IReadOnlyList<string> RouteHistory { get; }

Property Value

IReadOnlyList<String>

Constructors

DevHostBridge()

public DevHostBridge()

Methods

Navigates the host to route.

public ValueTask NavigateAsync(string route, CancellationToken ct = null)

Parameters

route String

ct CancellationToken

Returns

ValueTask

GetCurrentRouteAsync(CancellationToken)

Returns the host's current route.

public ValueTask<string> GetCurrentRouteAsync(CancellationToken ct = null)

Parameters

ct CancellationToken

Returns

ValueTask<String>

ReadStorageAsync(String, CancellationToken)

Reads a plain (unencrypted) key/value entry — SharedPreferences on Android, UserDefaults on iOS. Null if the key is absent. For secrets use IMobileBridge.GetSecretAsync(String, CancellationToken).

public ValueTask<string?> ReadStorageAsync(string key, CancellationToken ct = null)

Parameters

key String

ct CancellationToken

Returns

ValueTask<String>

WriteStorageAsync(String, String, CancellationToken)

Writes a plain (unencrypted) key/value entry.

public ValueTask WriteStorageAsync(string key, string value, CancellationToken ct = null)

Parameters

key String

value String

ct CancellationToken

Returns

ValueTask

DeleteStorageAsync(String, CancellationToken)

Deletes a plain key/value entry (a no-op if absent).

public ValueTask DeleteStorageAsync(string key, CancellationToken ct = null)

Parameters

key String

ct CancellationToken

Returns

ValueTask

FetchAsync(BridgeHttpRequest, CancellationToken)

Performs an HTTP request through the host, which owns TLS, proxying and permissions. Prefer the HttpClient registered by AddBlazorNativeHttp(), which routes through this.

public async ValueTask<BridgeHttpResponse> FetchAsync(BridgeHttpRequest request, CancellationToken ct = null)

Parameters

request BridgeHttpRequest

ct CancellationToken

Returns

ValueTask<BridgeHttpResponse>

Remarks:

The response is delivered once, complete: the host buffers the whole body and completes the call with a single BridgeHttpResponse whose BridgeHttpResponse.Body is UTF-8 text. There is no incremental delivery path, so streaming protocols (SSE, chunked-read, long-poll) degrade to polling and binary bodies are unsupported.

ClipboardReadAsync(CancellationToken)

Reads the system clipboard's text (empty if none). A host that predates this slot raises NotSupportedException.

public ValueTask<string> ClipboardReadAsync(CancellationToken ct = null)

Parameters

ct CancellationToken

Returns

ValueTask<String>

ClipboardWriteAsync(String, CancellationToken)

Writes text to the system clipboard.

public ValueTask ClipboardWriteAsync(string text, CancellationToken ct = null)

Parameters

text String

ct CancellationToken

Returns

ValueTask

ShareAsync(String, CancellationToken)

Presents the OS share sheet with text.

public ValueTask ShareAsync(string text, CancellationToken ct = null)

Parameters

text String

ct CancellationToken

Returns

ValueTask

GetCurrentPositionAsync(CancellationToken)

Requests-then-fetches the current position in one call: the whole permission dance runs host-side, and the terminal outcome is always a GeolocationResult — a denial is DATA, never an exception or a hang. The token abandons a never-completing call (e.g. the app killed during the prompt) as a cancel, never a leak.

public ValueTask<GeolocationResult> GetCurrentPositionAsync(CancellationToken ct = null)

Parameters

ct CancellationToken

Returns

ValueTask<GeolocationResult>

CheckGeolocationPermissionAsync(CancellationToken)

Reads the current geolocation permission WITHOUT prompting — for a UI that wants to show state before offering to locate.

public ValueTask<GeolocationStatus> CheckGeolocationPermissionAsync(CancellationToken ct = null)

Parameters

ct CancellationToken

Returns

ValueTask<GeolocationStatus>

ScheduleNotificationAsync(NotificationSpec, CancellationToken)

Schedules a local notification to fire at NotificationSpec.When. The outcome is a NotificationStatus — a denial is DATA, never a throw.

public ValueTask<NotificationStatus> ScheduleNotificationAsync(NotificationSpec spec, CancellationToken ct = null)

Parameters

spec NotificationSpec

ct CancellationToken

Returns

ValueTask<NotificationStatus>

ShowNotificationAsync(NotificationSpec, CancellationToken)

Shows a local notification immediately.

public ValueTask<NotificationStatus> ShowNotificationAsync(NotificationSpec spec, CancellationToken ct = null)

Parameters

spec NotificationSpec

ct CancellationToken

Returns

ValueTask<NotificationStatus>

CancelNotificationAsync(Int32, CancellationToken)

Cancels a scheduled/shown notification by its NotificationSpec.Id.

public ValueTask<NotificationStatus> CancelNotificationAsync(int id, CancellationToken ct = null)

Parameters

id Int32

ct CancellationToken

Returns

ValueTask<NotificationStatus>

RequestNotificationPermissionAsync(CancellationToken)

Requests notification permission (may prompt).

public ValueTask<NotificationStatus> RequestNotificationPermissionAsync(CancellationToken ct = null)

Parameters

ct CancellationToken

Returns

ValueTask<NotificationStatus>

CheckNotificationPermissionAsync(CancellationToken)

Reads notification permission WITHOUT prompting.

public ValueTask<NotificationStatus> CheckNotificationPermissionAsync(CancellationToken ct = null)

Parameters

ct CancellationToken

Returns

ValueTask<NotificationStatus>

AuthenticateAsync(String, CancellationToken)

Shows an OS biometric prompt with reason and returns a BiometricStatus — failure / cancellation / lockout / no-hardware are all DATA, never a throw.

public ValueTask<BiometricStatus> AuthenticateAsync(string reason, CancellationToken ct = null)

Parameters

reason String

ct CancellationToken

Returns

ValueTask<BiometricStatus>

IsBiometricAvailableAsync(CancellationToken)

Checks biometric availability WITHOUT prompting; BiometricStatus.Authenticated means "present + enrolled + ready".

public ValueTask<BiometricStatus> IsBiometricAvailableAsync(CancellationToken ct = null)

Parameters

ct CancellationToken

Returns

ValueTask<BiometricStatus>

SetSecretAsync(String, String, Boolean, CancellationToken)

Writes an encrypted-at-rest secret. When requireAuth is true the secret is bound to biometric auth at the OS-key level, so it can only be read back by IMobileBridge.GetSecretWithAuthAsync(String, String, CancellationToken). Values over SecretResult.MaxValueBytes are rejected with a status, never crash.

public ValueTask<SecureStorageStatus> SetSecretAsync(string key, string value, bool requireAuth, CancellationToken ct = null)

Parameters

key String

value String

requireAuth Boolean

ct CancellationToken

Returns

ValueTask<SecureStorageStatus>

GetSecretAsync(String, CancellationToken)

Reads a secret that is NOT auth-bound. The value rides SecretResult.Value only on SecureStorageStatus.Ok.

public ValueTask<SecretResult> GetSecretAsync(string key, CancellationToken ct = null)

Parameters

key String

ct CancellationToken

Returns

ValueTask<SecretResult>

GetSecretWithAuthAsync(String, String, CancellationToken)

Reads an auth-bound secret, presenting a biometric prompt with reason. The OS itself refuses the plaintext without a fresh auth.

public ValueTask<SecretResult> GetSecretWithAuthAsync(string key, string reason, CancellationToken ct = null)

Parameters

key String

reason String

ct CancellationToken

Returns

ValueTask<SecretResult>

DeleteSecretAsync(String, CancellationToken)

Deletes a secret (a no-op if absent).

public ValueTask<SecureStorageStatus> DeleteSecretAsync(string key, CancellationToken ct = null)

Parameters

key String

ct CancellationToken

Returns

ValueTask<SecureStorageStatus>

CapturePhotoAsync(CaptureOptions, CancellationToken)

Captures a photo through the system camera. The image crosses back as a file:// PATH in PhotoResult (the bytes stay on disk), which is a valid BnImage.Src. A cancel / denied / no-camera outcome is a CameraStatus value, never a throw. Use options to bound the file size; the app owns the temp file after return.

public ValueTask<PhotoResult> CapturePhotoAsync(CaptureOptions options, CancellationToken ct = null)

Parameters

options CaptureOptions

ct CancellationToken

Returns

ValueTask<PhotoResult>

CheckCameraAvailabilityAsync(CancellationToken)

Checks camera availability WITHOUT prompting or launching the UI; CameraStatus.Captured means "present + usable", CameraStatus.Unavailable means no camera.

public ValueTask<CameraStatus> CheckCameraAvailabilityAsync(CancellationToken ct = null)

Parameters

ct CancellationToken

Returns

ValueTask<CameraStatus>

GetPlatformInfoAsync(CancellationToken)

Returns typed PlatformInfo for the running platform.

public ValueTask<PlatformInfo> GetPlatformInfoAsync(CancellationToken ct = null)

Parameters

ct CancellationToken

Returns

ValueTask<PlatformInfo>

InjectEvent(String, String)

Inject a native event programmatically — use from tests or DevTools UI.

public void InjectEvent(string name, string? payload = null)

Parameters

name String

payload String?

Dispose()

public void Dispose()

Events

NativeEvents

Raised when the native host pushes an event into .NET — a lifecycle callback, a notification tap-through, and the like.

public event Action<NativeEvent>? NativeEvents;