Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions languages/kotlin.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,37 @@ On Android, the OS aggressively suspends background processes — sockets get to

For desktop JVM apps these constraints don't apply — keep the endpoint bound for the lifetime of the process and call `shutdown()` on exit.

## Local network discovery on Android

By default, iroh does not browse your local network. Endpoints learn each other's addresses through iroh's discovery service (or a ticket) and then talk over ordinary one-to-one connections, the same kind of traffic as loading a website. On Android that means the only permission you need is `INTERNET`, which every networked app already declares. There is no prompt and no extra manifest entry, and direct device-to-device connections work even when both peers sit on the same Wi-Fi.

iroh can optionally discover peers over mDNS, a broadcast technology that lets endpoints find each other on the same Wi-Fi without any outside help (`presetN0WithMdns()`, not yet in an iroh-ffi release). Android handles this differently from iOS: there is no user-facing permission prompt, but phones silently drop broadcast packets at the Wi-Fi chip to save battery, so mDNS responses never reach your app unless you ask the system to let them through. Enabling it takes three steps:

1. Declare the multicast permission in `AndroidManifest.xml`. It is granted at install time; the user is never prompted:

```xml
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
```

2. Hold a multicast lock while you want discovery to work. The lock tells the Wi-Fi driver to deliver broadcast packets instead of filtering them, at some battery cost, so release it when you no longer need to find new peers:

```kotlin
val wifi = context.getSystemService(Context.WIFI_SERVICE) as WifiManager
val multicastLock = wifi.createMulticastLock("iroh-mdns").apply { acquire() }
// ... bind and use the endpoint ...
multicastLock.release()
```

3. Bind your endpoint with the mDNS preset instead of `presetN0()`:

```kotlin
val ep = Endpoint.bind(
EndpointOptions(preset = presetN0WithMdns(), alpns = listOf(ALPN)),
)
```

Desktop JVM apps need none of this: mDNS works there without any special permissions or locks.

## Building from source

For Android, an unsupported host, or to hack on the bindings themselves, clone iroh-ffi and generate the sources locally:
Expand Down
21 changes: 21 additions & 0 deletions languages/swift.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,27 @@ Your `.entitlements` file should now contain:
<true/>
```

## Local network discovery on iOS

By default, iroh does not browse your local network. Endpoints learn each other's addresses through iroh's discovery service (or a ticket you paste in) and then talk over ordinary one-to-one connections, the same kind of traffic as loading a website. iOS treats that as regular internet traffic even when the two devices sit on the same Wi-Fi, so direct device-to-device connections work with no extra Info.plist keys or permission prompts. We verified this on real hardware: an iPhone and a Mac on the same network held direct connections over both their local (`192.168.x.x`) and public addresses, even with the app's Local Network toggle switched off in **Settings → Privacy & Security**.

iroh can optionally discover peers over mDNS, the broadcast technology behind Bonjour, which lets endpoints find each other on the same Wi-Fi without any outside help. Because that mode genuinely browses the network, iOS gates it behind the "would like to find and connect to devices on your local network" prompt. mDNS discovery has not shipped in an iroh-ffi release yet; once it does (`presetN0WithMdns`), enabling it takes three steps:

1. Add the `NSLocalNetworkUsageDescription` key to your Info.plist with a short sentence telling the user why your app looks for nearby devices. iOS shows this text in the permission prompt.
2. Request the `com.apple.developer.networking.multicast` entitlement from Apple ([request form](https://developer.apple.com/contact/request/networking-multicast)) and add it to your app's entitlements once granted.
3. Bind your endpoint with the mDNS preset instead of `presetN0()`:

```swift
let ep = try await Endpoint.bind(options: EndpointOptions(
preset: presetN0WithMdns(),
alpns: [Data("hello-iroh/0".utf8)]
))
```

`presetN0WithMdns()` keeps everything the n0 preset configures (relays and public discovery) and layers local-network discovery on top, so peers on the same Wi-Fi can find each other even when the public lookup path is slow or unreachable.

Until you opt into mDNS, none of this applies.

## 5. Disable previews (Xcode 16 workaround)

Xcode 16's preview pipeline tries to link `SwiftUICore.framework` directly when a Swift Package is in the graph, which fails with *"product being built is not an allowed client of it"*. Until Apple ships a fix, turn previews off for the app target:
Expand Down
Loading