Options and limits
The plugin reads all NearbyOptions values once at startup. Set them in the configure delegate of
AddNearbyConnectivity(...), shown in Register the plugin.
A change after startup has no effect.
The presence is the one value that can change later, through
SetPresence. The Presence option is its initial value.
NearbyOptions.Android exists on every target, so shared code compiles without #if. On other
platforms it has no effect.
Options
| Member | Platform | Default | Description |
|---|---|---|---|
ServiceId |
Both | None. Required. | The identifier that both devices must share. Only devices with the same ServiceId find each other. 1 to 15 characters: ASCII lowercase letters, digits, and hyphens. At least one letter. No hyphen at the start, at the end, or next to another hyphen. On iOS, it is also the service type that the system advertises. See Set up Android and iOS. Startup validation throws if the value is not set or is invalid. |
Presence |
Both | DeviceInfo.Name, empty info |
The data that other devices see before a connection exists. It has a DisplayName of at most 63 UTF-8 bytes and at most 57 bytes of opaque Info. The option sets the initial value only. See Show a presence before connecting. Public and unverified. The plugin broadcasts it unencrypted, and any device can claim any presence. |
OfferWindow |
Both | 2 minutes | The time that a connect or an inbound request waits for an answer, on both ends. At most 30 minutes. Startup validation rejects zero, negative values, and Timeout.InfiniteTimeSpan. The value travels with the request, so the peer's prompt, through NearbyConnectionRequest.ExpiresAt, and an accepted handshake expire at the same moment. When the time elapses, ConnectAsync and AcceptAsync throw NearbyConnectException with TimedOut. A request that a consent policy answers has a separate limit. See Consent policies. |
DiscoveryRefreshInterval |
Both | null, never restarts |
The interval at which discovery restarts to find which devices are still in range. The plugin removes devices that the new pass does not report again. It never removes a device that is connected or in a handshake. With the default, discovery never restarts on its own, and Discoverer.RefreshAsync restarts it on request. |
FileTransferInactivityTimeout |
Both | 10 seconds | Outbound only. If a file send makes no progress within this time, the plugin abandons the send with NearbyTransferTimeoutException. null disables the check, as it does for DiscoveryRefreshInterval. An inbound transfer that stops has no time limit: watch InboundTransfersAsync and call CancelInboundTransferAsync. |
Android.Topology |
Android | NearbyTopology.Cluster |
How devices can connect. Cluster is many-to-many. Star is one-to-many. PointToPoint is one-to-one, with the highest bandwidth. The advertising device and the discovering device must use the same value, or they never find each other. |
Android.ConnectionType |
Android | NearbyConnectionType.Balanced |
How hard the radio works after a connection opens: Balanced, HighBandwidth, or NonDisruptive. |
Android.UseLowPower |
Android | false |
When true, the plugin uses only low-power mediums such as BLE. The result is less battery use, less range, and less throughput. |
Inbound consent is not an option, because it can change at run time. Advertiser.SetConsent sets
it. See Answer an inbound request.
Limits
This table lists every fixed number that the plugin enforces. The plugin validates each one and never truncates a value silently.
| What | Limit | Where it applies |
|---|---|---|
ServiceId length |
1 to 15 characters | Startup validation throws outside this range |
NearbyPresence.DisplayName |
63 UTF-8 bytes, NearbyPresence.MaxDisplayNameBytes |
ArgumentException that names the member |
NearbyPresence.Info |
57 bytes, NearbyPresence.MaxInfoBytes |
ArgumentException that names the member |
| A bytes payload | 32 KiB, NearbyConnection.MaxBytesPayloadLength |
SendAsync(ReadOnlyMemory<byte>) throws ArgumentOutOfRangeException. A file or a stream carries more |
| A stream name | 1024 UTF-8 bytes | OpenStreamAsync throws |
OfferWindow |
30 minutes | Startup validation rejects a longer value, zero, negative values, and Timeout.InfiniteTimeSpan. The plugin clamps a value that a peer declared to the same limit on arrival. |
| Unread payloads on one connection | None. At 64, the plugin logs a warning | The plugin drops nothing and pauses nothing. See the buffer has no bound |
The 57-byte Info limit comes from the plugin's connect request frame. It is the space that remains
after the frame header, the offer window, and a 63-byte name of maximum length. Both limits come
from the frame, not from one platform, so they apply on both platforms.
An inbound file has no size limit. See Treat every payload as hostile input.
Consent policies
A consent policy controls how the plugin answers inbound connection requests.
Advertiser.SetConsent is the only way to set it, and each call replaces both the policy and the
decide callback. To answer requests yourself, see
Answer an inbound request.
| Policy | What it does |
|---|---|
Hold, the default |
Moves the device to RequestReceived with the request on device.Request, and waits |
AcceptAll |
Accepts every request for you. The device moves directly to Connected and never reports RequestReceived, so a UI that waits only for requests shows nothing |
RejectAll |
Declines every request for you |
A request that the policy answers for you does not use the offer window. It has 30 seconds to
complete its handshake. The offer window covers delivery, the decision of a person, and the
handshake, and a policy that answers removes the decision. When the 30 seconds elapse, the plugin
abandons the handshake, the device returns to Visible, and the plugin logs a warning. A request
that a person answers through AcceptAsync still has the full window that the requesting device
declared.
Connection end reasons
NearbyConnection.Closed completes with one of these four values. NearbyEndReason has ten
values. The other six describe a handshake or a change to Devices, and appear in
NearbyDeviceChange.Reason instead.
| Reason | What happened |
|---|---|
ClosedLocally |
This side called CloseAsync or DisconnectAsync |
PeerDisconnected |
The peer closed the connection, or the link was lost. Neither platform distinguishes the two |
SessionStopped |
StopAllAsync stopped the session |
AppSuspended |
The plugin stopped the session because the iOS app moved to the background |
Next
- Show a presence before connecting to change the presence at run time.
- Set up Android and iOS for the manifest and
Info.plistentries.