local_network_rwx 1.0.9 copy "local_network_rwx: ^1.0.9" to clipboard
local_network_rwx: ^1.0.9 copied to clipboard

PlatformiOS

Check and request the iOS Local Network permission reliably: triggers the system dialog via NWBrowser and reports whether access was granted or denied. No-op on other platforms.

Local Network RWX #

Check and request the iOS Local Network permission from Flutter.

Pub Version

On iOS 14+, apps must be granted Local Network access before they can discover or communicate with devices via UDP broadcast, mDNS/Bonjour, or multicast. Apple provides no direct API to query the permission state. The standard permission_handler package does not support this permission.

This plugin uses NWBrowser with debounced state handling to trigger the system dialog and reliably detect whether the user granted or denied access.

On non-iOS platforms all methods return granted / no-op.

Caution

Multicast Networking Entitlement Required

Your app must have the com.apple.developer.networking.multicast entitlement before any of this will work. Apple does not grant it automatically — you must request it at:

https://developer.apple.com/contact/request/networking-multicast

Without this entitlement, NWBrowser and Bonjour discovery will silently fail and the Local Network permission dialog will never appear.

Warning

Testing — Use TestFlight, Not Xcode

When an app is launched from Xcode or the IDE, iOS automatically grants Local Network permission without showing the system dialog. You will not see the permission prompt and requestPermission() will always return granted.

To test the actual permission flow (dialog appearance, deny handling, Settings toggle), you must install the app via TestFlight or ad-hoc distribution.

Tip

How to verify the entitlement is active

Go to Settings → [Your App] on the device. If the Multicast Networking entitlement is correctly provisioned, you will see a "Local Network" toggle row. If that row is missing, your app does not have the entitlement yet — request it from Apple before proceeding.


iOS Settings showing the Local Network toggle

Setup #

1. Add the dependency #

dependencies:
  local_network_rwx: ^1.0.0

2. Configure Info.plist #

Add these entries to ios/Runner/Info.plist:

<key>NSLocalNetworkUsageDescription</key>
<string>This app needs local network access to discover devices on your Wi-Fi network.</string>
<key>NSBonjourServices</key>
<array>
    <string>_yourservice._tcp</string>
</array>

Both entries are required:

  • NSLocalNetworkUsageDescription — the user-facing explanation shown in the system permission dialog. Without it, iOS will not prompt the user at all.
  • NSBonjourServices — the Bonjour service type you pass to requestPermission() must appear here, otherwise NWBrowser silently fails.

Usage #

import 'package:local_network_rwx/local_network_rwx.dart';

// Optional: send a UDP broadcast primer for older iOS versions (14.x, 15.x).
final broadcast = await LocalNetworkPermissionRWX.getBroadcastAddress();
await LocalNetworkPermissionRWX.sendUdpPrimer(broadcastAddress: broadcast);

// Check / request permission. Shows the system dialog on first call.
final status = await LocalNetworkPermissionRWX.requestPermission(
  serviceType: '_yourservice._tcp',
);

switch (status) {
  case LocalNetworkStatusRWX.granted:
    // Proceed with device discovery.
    break;
  case LocalNetworkStatusRWX.denied:
    // Show a dialog explaining how to enable in Settings.
    await LocalNetworkPermissionRWX.openSettings();
    break;
  case LocalNetworkStatusRWX.unknown:
    // Could not determine — try networking anyway (fail-open).
    break;
}

API #

LocalNetworkPermissionRWX.requestPermission() #

Triggers the iOS Local Network permission dialog (if not yet shown) and returns the user's decision as a LocalNetworkStatusRWX.

Parameter Type Default Description
serviceType String required Bonjour service type (e.g. _myapp._tcp)
timeoutSeconds int 30 Max seconds to wait for user response

LocalNetworkPermissionRWX.sendUdpPrimer() #

Sends a single UDP broadcast packet to prime the iOS network stack. Optional but improves reliability on some iOS versions.

LocalNetworkPermissionRWX.getBroadcastAddress() #

Returns the directed broadcast address (e.g. 192.168.1.255) for the first usable local IPv4 interface, or null.

LocalNetworkPermissionRWX.openSettings() #

Opens the iOS Settings app at the current app's settings page.

LocalNetworkStatusRWX #

Value Meaning
granted Permission granted (or non-iOS platform)
denied Permission denied (kDNSServiceErr_PolicyDenied)
unknown Could not determine (no Wi-Fi, timeout, error)

How it works #

  1. An NWBrowser is started for the given Bonjour service type
  2. iOS presents the "Allow [App] to find devices on your local network?" dialog (only on first invocation — subsequent calls detect the stored decision)
  3. The browser's stateUpdateHandler fires state transitions:
    • .ready → permission granted (1.2s debounce)
    • .failed/.waiting with kDNSServiceErr_PolicyDenied → denied (1.0s debounce)
    • Other errors → unknown (fail-open, immediate)
  4. Asymmetric debounce timing handles iOS firing states in either order

The debounce is critical because iOS always fires .ready first — even before the user has tapped Allow or Don't Allow. The 1.2s window gives time for a subsequent .failed(PolicyDenied) to cancel the premature .ready.

iOS version notes #

  • iOS 14-15: UDP primer recommended for reliable dialog triggering
  • iOS 17.x: Re-enabling permission in Settings may require device restart
  • iOS 18: Known Apple bug where in-memory and persistent state can desync (FB14321888)

Note

App restart after toggling Local Network in Settings

When the user changes the Local Network toggle in Settings → [Your App], iOS automatically kills and restarts your app. This means you do not need to handle the permission change at runtime — the app will relaunch with the updated permission state.

If you use openSettings() to send the user to Settings, avoid calling exit() beforehand. Keeping the app alive lets iOS show the "Back to [Your App]" breadcrumb in the top-left of the status bar, giving the user a clear way to navigate back. Once they toggle the permission, iOS will kill and restart the app automatically.

"In Action" on an App that relies on this library #

This library is used in the Gemma App by Gemma Design — a lighting control app that discovers and communicates with smart furniture via the local network.


Gemma App

User grants permission (green path): The user selects "Allow", then device search proceeds normally.

Download and watch — user grants permission

User denies permission, then re-enables in Settings (red path): The user doesn't grant permission, then is redirected to the app's Settings page. Permission takes effect on restart of the app.

Download and watch — user denies then re-enables

📮 Support #

💚 Funding #

License #

BSD 3-Clause. See LICENSE.


Happy Networking! 🎉

1
likes
160
points
61
downloads

Documentation

API reference

Publisher

verified publisherraoulsson.com

Weekly Downloads

Check and request the iOS Local Network permission reliably: triggers the system dialog via NWBrowser and reports whether access was granted or denied. No-op on other platforms.

Repository (GitHub)
View/report issues

License

BSD-3-Clause (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on local_network_rwx

Packages that implement local_network_rwx