Table of Contents

Class NearbyDevice

Namespace
Plugin.Maui.NearbyConnectivity
Assembly
Plugin.Maui.NearbyConnectivity.dll

Represents a remote device discovered by, or connected to, an INearbyConnectivity.

public sealed class NearbyDevice
Inheritance
NearbyDevice
Inherited Members

Remarks

An instance is an immutable snapshot. It describes what was true the moment it was produced and never changes afterwards. When a device's status changes, the session publishes a new instance through DeviceChanged. The instance you are already holding keeps reporting the old status. Hold a device only as long as the change that delivered it, or re-read the current one from Devices.

Equality is Id alone, so two snapshots of one device compare equal however their statuses differ.

The verbs resolve live, the data does not. ConnectAsync(CancellationToken), DisconnectAsync() and Connection look the device up in the session at the moment they are called, so acting on a stale snapshot is safe. The tap that lands a second after a row was bound still acts on what is true now. Only the properties are frozen.

Constructors

NearbyDevice(string, NearbyPresence)

Initializes a new instance of the NearbyDevice class.

public NearbyDevice(string id, NearbyPresence presence)

Parameters

id string

A unique identifier for the device, valid within the current session. Generated by this plugin, with the same shape on every platform. See Id.

presence NearbyPresence

What the remote device shows: its display name and its application-defined info, exactly as it sent them.

Remarks

For tests of code that consumes devices, such as a view model fed by a fake INearbyConnectivity. A device built here belongs to no session: Connection, Request and ConnectExpiresAt are null, and ConnectAsync(CancellationToken) and DisconnectAsync() throw InvalidOperationException. A session never acts on a device it did not produce.

Exceptions

ArgumentNullException

id or presence is null.

Properties

ConnectExpiresAt

Gets when the outbound handshake to this device stops waiting, if one is in flight.

public DateTimeOffset? ConnectExpiresAt { get; }

Property Value

DateTimeOffset?

The deadline while Status is Connecting because the local device called ConnectAsync(CancellationToken); otherwise null. The initiator-side counterpart of ExpiresAt: the local OfferWindow, clamped, measured from when the handshake began.

Remarks

Resolved against the session on every read, exactly like Request and Connection, so it reports the deadline the handshake is actually running under rather than a copy a caller recomputed and now has to keep in step. It goes null the moment the handshake settles, however it settled.

null while accepting an inbound request. That side's deadline is ExpiresAt, on the request itself.

Connection

Gets the open connection to this device, or null if there is none.

public NearbyConnection? Connection { get; }

Property Value

NearbyConnection

The live connection if one is open right now; otherwise null. Resolved on every read against the session's connection table, so it is current even when read from a snapshot taken some time ago.

Remarks

A device that is not part of a session's device set, one constructed directly in a test, always reports null rather than throwing, because "is there a connection" has a correct answer for a device with no session: no.

Id

Gets the unique identifier for this device.

public string Id { get; }

Property Value

string

An identifier unique within the current session. This is the sole basis for Equals(NearbyDevice?).

Remarks

Generated by this plugin, not by the platform. Sixteen hexadecimal characters from a cryptographically secure random source, with the same shape on Android and iOS. Neither platform's own identifier reaches this property or any other part of the public API. Google's endpoint id and Apple's peer handle stay internal.

Opaque and session-scoped. It carries no device information, is not derived from the display name or any hardware identifier, and does not survive the session: the same physical device gets a different value next time. Treat it as a handle for correlating events within one run, not as a stable device identity to persist, and not as an anonymous statistic to publish, since it does identify a device for the life of the session.

Presence

Gets what this device shows to devices in range: its display name and its application-defined info.

public NearbyPresence Presence { get; }

Property Value

NearbyPresence

The remote device's presence as it sent it. Never null. The name is at most MaxDisplayNameBytes UTF-8 bytes and may be empty; the info is empty when the peer sent none.

Remarks

Remote-chosen, untrusted input. Both members are bounded in length and rewritten in no other way, so the name may contain bidi controls or separators and the info is bytes to validate before parsing. Treat the presence as a label to filter and display by, never as an identifier or a credential. Use Id to correlate.

Request

Gets the inbound connection request outstanding from this device, if one is.

public NearbyConnectionRequest? Request { get; }

Property Value

NearbyConnectionRequest

The request while Status is RequestReceived, otherwise null. Its ExpiresAt, ExpiresIn and Expired carry the offer's deadline in the shapes a view needs, from the one object that owns it.

Remarks

Resolved against the session on every read, exactly like Connection, so a row bound to a snapshot taken earlier still answers the current request.

Status

Gets where this device sits in its lifecycle, as of this snapshot.

public NearbyDeviceStatus Status { get; init; }

Property Value

NearbyDeviceStatus

One of the NearbyDeviceStatus values. The default is Visible. Set it when building a device for a test.

Methods

ConnectAsync(CancellationToken)

Opens a connection to this device, or returns the one already open.

public Task<NearbyConnection> ConnectAsync(CancellationToken cancellationToken = default)

Parameters

cancellationToken CancellationToken

A token to stop waiting for the handshake.

Returns

Task<NearbyConnection>

The established connection, the same instance Connection returns.

Examples

try
{
    var connection = await device.ConnectAsync(cancellationToken);
    await connection.SendAsync(Encoding.UTF8.GetBytes("hello"), cancellationToken);
}
catch (NearbyConnectException ex) when (ex.Reason is NearbyConnectFailure.TimedOut)
{
    Status = $"{device.Presence.DisplayName} did not answer.";
}

Remarks

The device is resolved in the session by Id as the call is made, so a snapshot that has since gone stale still connects to the right device, or fails because the session no longer knows it.

Convergent. If a connection is already open it is returned; if a handshake is already in flight this joins it; if the device has already sent a request of its own, that request is accepted. Connecting twice is not an error.

Exceptions

InvalidOperationException

This device did not come from a session's device set, so it has nothing to act through.

NearbyConnectException

The handshake did not produce a connection. Branch on Reason: DeviceUnknown when the device is no longer known to the session, TimedOut when OfferWindow elapsed, or Failed otherwise.

OperationCanceledException

cancellationToken was canceled.

DisconnectAsync()

Closes the connection to this device. Does nothing if there is none.

public Task DisconnectAsync()

Returns

Task

A task that completes once the connection is released.

Remarks

Resolved live by Id for the same reason ConnectAsync(CancellationToken) is. Closes the connection for every holder, not just this caller — see CloseAsync().

Exceptions

InvalidOperationException

This device did not come from a session's device set, so it has nothing to act through.

Equals(NearbyDevice?)

Determines whether the specified device is the same device as this one.

public bool Equals(NearbyDevice? other)

Parameters

other NearbyDevice

The device to compare with the current device.

Returns

bool

true if other has the same Id; otherwise, false.

Remarks

Compares Id only. Two snapshots of a device that merely changed status are still the same device.

Equals(object?)

Determines whether the specified object is equal to the current object.

public override bool Equals(object? obj)

Parameters

obj object

The object to compare with the current object.

Returns

bool

true if the specified object is equal to the current object; otherwise, false.

GetHashCode()

Returns the hash code for this device.

public override int GetHashCode()

Returns

int

A 32-bit signed integer hash code derived from Id alone.

ToString()

Returns a string that represents the current device.

public override string ToString()

Returns

string

A string containing the device's display name, identifier, and status, intended for diagnostic output rather than parsing. The name is omitted when the peer sent none.

Operators

operator ==(NearbyDevice?, NearbyDevice?)

Determines whether two devices are the same device.

public static bool operator ==(NearbyDevice? left, NearbyDevice? right)

Parameters

left NearbyDevice

The first device.

right NearbyDevice

The second device.

Returns

bool

true when both are null, or both have the same Id.

operator !=(NearbyDevice?, NearbyDevice?)

Determines whether two devices are different devices.

public static bool operator !=(NearbyDevice? left, NearbyDevice? right)

Parameters

left NearbyDevice

The first device.

right NearbyDevice

The second device.

Returns

bool

true when they do not have the same Id.

See Also