@devioarts/capacitor-mdns 0.0.3 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/CHANGELOG.md +110 -0
  2. package/DevioartsCapacitorMdns.podspec +3 -3
  3. package/Package.swift +1 -1
  4. package/README.md +272 -101
  5. package/android/build.gradle +3 -9
  6. package/android/src/main/AndroidManifest.xml +2 -0
  7. package/android/src/main/java/com/devioarts/capacitor/mdns/AndroidNsdBackend.kt +145 -0
  8. package/android/src/main/java/com/devioarts/capacitor/mdns/MdnsOptions.kt +32 -0
  9. package/android/src/main/java/com/devioarts/capacitor/mdns/MdnsValidation.kt +26 -0
  10. package/android/src/main/java/com/devioarts/capacitor/mdns/NsdBackend.kt +59 -0
  11. package/android/src/main/java/com/devioarts/capacitor/mdns/mDNS.kt +496 -175
  12. package/android/src/main/java/com/devioarts/capacitor/mdns/mDNSPlugin.kt +85 -49
  13. package/dist/docs.json +313 -15
  14. package/dist/esm/definitions.d.ts +89 -16
  15. package/dist/esm/definitions.js.map +1 -1
  16. package/dist/esm/index.js +22 -1
  17. package/dist/esm/index.js.map +1 -1
  18. package/dist/esm/web.d.ts +8 -1
  19. package/dist/esm/web.js +35 -3
  20. package/dist/esm/web.js.map +1 -1
  21. package/dist/plugin.cjs.js +57 -4
  22. package/dist/plugin.cjs.js.map +1 -1
  23. package/dist/plugin.js +57 -4
  24. package/dist/plugin.js.map +1 -1
  25. package/docs/electron.md +91 -0
  26. package/docs/platform-setup.md +58 -0
  27. package/docs/playground.md +50 -0
  28. package/docs/runtime-behavior.md +80 -0
  29. package/electron/dist/plugin-settings.js +22 -0
  30. package/electron/dist/plugin-settings.js.map +1 -0
  31. package/electron/dist/plugin.cjs.js +774 -0
  32. package/electron/dist/plugin.cjs.js.map +1 -0
  33. package/electron/global.d.ts +2 -0
  34. package/electron/mdns-bridge.cjs +33 -4
  35. package/electron/mdns.ts +628 -107
  36. package/electron/rollup.config.mjs +22 -0
  37. package/electron/src/index.ts +2 -0
  38. package/electron/src/plugin-settings.ts +19 -0
  39. package/electron/tsconfig.json +21 -0
  40. package/electron/types-public/index.d.ts +47 -0
  41. package/ios/Sources/mDNSPlugin/mDNS.swift +481 -124
  42. package/ios/Sources/mDNSPlugin/mDNSPlugin.swift +85 -23
  43. package/ios/Tests/mDNSPluginTests/BridgeTests.swift +46 -0
  44. package/ios/Tests/mDNSPluginTests/MDNSTests.swift +490 -0
  45. package/package.json +55 -20
  46. package/ios/Tests/mDNSPluginTests/mDNSPluginTests.swift +0 -15
package/CHANGELOG.md ADDED
@@ -0,0 +1,110 @@
1
+ # Changelog
2
+
3
+ ## [0.2.0] - 2026-11-07
4
+
5
+ ### Upgrade from 0.1.0
6
+
7
+ - Existing method signatures and result shapes are retained. Continuous discovery is additive,
8
+ but validation, failure reporting and overlapping discovery behavior have changed as noted below.
9
+ - iOS now declares a minimum deployment target of 15.0. Capacitor dependencies are restricted to
10
+ version 8; applications using another major version are not supported.
11
+ - Service types, instance names, TXT records and timeouts are validated more strictly. Previously
12
+ tolerated invalid inputs can now return `error: true`.
13
+ - A valid new `discover()` cancels the previous request with an error. On iOS, discovery without
14
+ a name filter now waits for the complete timeout. Check `error` before consuming results;
15
+ errors discard partial results, and a failed stop can return `publishing: true`.
16
+ - Electron applications must install `bonjour-service@~1.4.0` and rerun `npx cap-electron sync`.
17
+ Manual IPC integrations using a custom renderer origin must configure `trustedOrigins`.
18
+
19
+ ### Added
20
+
21
+ - Continuous multi-type discovery on iOS, Android and Electron through `watchServices()` and
22
+ `stopWatching()`, with `serviceFound`, `serviceLost` and `watchError` listeners. Valid replacement
23
+ calls stop previous watchers; stopping leaves advertisements and one-shot discovery independent.
24
+ Thanks to [Idrimi](https://github.com/Idrimi) for the original feature in
25
+ [PR #7](https://github.com/devioarts/capacitor-mdns/pull/7).
26
+ - Full found/lost snapshots, duplicate-type normalization, stale-callback guards, native resolve
27
+ retries, shared Android resolver scheduling and multicast locks, and Electron TTL expiry / IPC events.
28
+ - Resolved Android NSD TXT attributes, optional service hostnames, playground live service lists / errors / TXT publication and
29
+ regression tests for watcher lifecycle and both Electron integration routes.
30
+
31
+ ### Fixed
32
+
33
+ - CocoaPods source tags now use the repository's `v` prefix. npm archives include this changelog.
34
+ - Electron: a failed response to an incoming Bonjour query no longer permanently blocks later
35
+ publication, discovery or watches. Fatal transport errors still stop affected operations.
36
+ - Electron: name conflicts fail when the probe detects them, and stopping an unpublished service
37
+ no longer sends goodbye records for another publisher's name. Missing generated registration
38
+ reports the required `npx cap-electron sync` step.
39
+ - Electron: goodbye is preserved if an announcement has started but its send callback is still pending;
40
+ stopped services cannot reannounce after a late callback. Duplicate discovered addresses are removed.
41
+ - The supported `bonjour-service` range is limited to `~1.4.0` pending verification of probe cleanup
42
+ behavior in later minor versions; package, playground and installation instructions use the same range.
43
+ - Discovered addresses prefer IPv4 on all platforms while preserving native IPv6 scope suffixes.
44
+ Added regressions for packet failures, Bonjour teardown, address ordering, native bridge input
45
+ validation and Android recovery after a late unregistration confirmation.
46
+
47
+ - Android: NSD callbacks (delivered on NsdManager's internal thread) are now marshalled to the main thread before touching any state, removing data races between discovery results, the timeout, and publish completion. A publish confirmation racing the publish timeout can no longer complete the call twice.
48
+ - Android: before API 34 only one `resolveService` may be active, so concurrent resolves were silently dropped and services lost. Resolves are now queued, retried on `FAILURE_ALREADY_ACTIVE`, and individually timed out.
49
+ - Android: stopping, replacing or timing out a pending registration cancels it immediately through its listener, allowing subsequent publication. Late callbacks cannot resurrect a cancelled service. `close()` fails pending discovery.
50
+ - iOS: discovery waits for the entire requested timeout unless a named target resolves with an IP address, retaining late peers even after a failed or filtered resolve.
51
+ - iOS: the `NWBrowser` duplicate check used un-normalized type/domain, so every browse update spawned new resolvers for already known services.
52
+ - iOS: a denied Local Network permission is now reported as an error instead of an empty discovery result.
53
+ - All platforms validate service types, UTF-8 instance/TXT lengths and string-only TXT before stopping an active advertisement. Android now publishes TXT as well.
54
+
55
+ - Electron: a malformed service type (e.g. `http`, `_http._xyz.`) is now rejected with an error instead of being silently advertised/browsed as `_http._tcp.`, matching iOS and Android. An invalid type no longer stops a broadcast that is already running.
56
+ - All platforms reject invalid timeouts, clamp valid delays and use the same default broadcast name. A new valid `discover()` replaces its predecessor; errors return empty results. Dots and hyphens compare equally in name filters.
57
+ - Electron: transport errors fail pending publication, name conflicts are reported explicitly, and discovery handles late address records. Destroy ends pending discoveries and late callbacks cannot mutate completed results.
58
+ - Electron: manual IPC checks trusted top-level senders and event recipients.
59
+ - npm archives exclude local audit files while retaining SwiftPM tests. Android declares coroutines directly and lint failures block builds. iOS requires version 15, matching Capacitor 8.
60
+
61
+ ### Changed
62
+
63
+ - `bonjour-service` is declared as an optional peer dependency (needed by Electron apps only).
64
+ - Electron: `new mDNS(bonjour?, options?)` accepts an injectable Bonjour implementation and timeouts for tests.
65
+ - Android: NSD access moved behind an internal `NsdBackend` seam (`AndroidNsdBackend` in production) so the logic is unit-testable on the JVM.
66
+ - iOS: `MDNS` exposes internal factories and timers for tests.
67
+ - Removed the unused disabled Dependabot template and Android instrumentation placeholder. Playground lint uses the installed flat React configuration and ignores generated native projects.
68
+
69
+ ### Tests
70
+
71
+ - Added deterministic Electron regressions for validation, publication/stop failures, replacement, late addresses, TTL expiry, IPC trust and bridge subscriptions, plus real network discovery tests.
72
+ - Added JVM and iOS simulator regressions for callbacks, timeouts, replacement, UTF-8 validation, resolver scheduling, watcher cleanup and stale events. Removed template placeholder tests.
73
+
74
+ ## [0.1.0]
75
+
76
+ Compared with `v0.0.3`.
77
+
78
+ ### Added
79
+
80
+ - Added `getPluginPlatform()` to the public API, returning `ios`, `android`, `electron`, or `web` from the implementation that handled the call.
81
+ - Added Capacitor Electron package exports, public Electron type declarations, plugin metadata for `devioarts/capacitor-electron`, and a dedicated Electron build step.
82
+ - Added Electron IPC support for `getPluginPlatform()` and kept the manual preload bridge available through `electron/mdns-bridge.cjs`.
83
+ - Added an in-repository playground app that exercises broadcast, discovery, Electron bridge usage, logging, and runtime platform detection.
84
+ - Added focused docs for platform setup, Electron setup, playground usage, and runtime behavior.
85
+ - Added Electron end-to-end tests for publish/discover/stop behavior, platform detection, invalid input handling, and overlapping broadcast calls.
86
+ - Added GitHub issue templates, pull request template, CI workflow, a disabled Dependabot template, and funding metadata.
87
+
88
+ ### Changed
89
+
90
+ - `startBroadcast()` on iOS, Android, and Electron is now guarded by a publish timeout so native/runtime callbacks cannot leave the JavaScript promise pending forever.
91
+ - Starting a new advertisement now stops or replaces the previous active advertisement; the plugin keeps only one active broadcast at a time.
92
+ - Discovery sessions are now timeboxed and clean up native listeners, browsers, service-info callbacks, and resolvers more reliably.
93
+ - Overlapping discovery calls are serialized or safely isolated from stale callbacks, depending on platform behavior.
94
+ - Service type and name inputs are trimmed and normalized consistently across supported platforms.
95
+ - Port validation now requires values in the `1..65535` range.
96
+ - Android now declares `INTERNET` and `CHANGE_WIFI_MULTICAST_STATE` permissions in the plugin manifest for merge during `npx cap sync`.
97
+ - Package exports now expose the root plugin, Electron runtime entry points, Electron settings, the manual bridge, and `package.json`.
98
+ - Build, clean, lint, and test scripts now include the Electron runtime and e2e test pipeline.
99
+ - README setup and API documentation were regenerated and reorganized around the maintained in-repo playground and docs.
100
+
101
+ ### Fixed
102
+
103
+ - Fixed web fallback behavior so unsupported browser calls return shaped errors instead of success-like results.
104
+ - Fixed pending publish promises when iOS or Android publishing is stopped, replaced, fails, or times out.
105
+ - Fixed Android discovery cleanup and listener handling to avoid old callbacks completing a newer request.
106
+ - Fixed Android discovery failure reporting so start failures surface through the documented error shape.
107
+ - Fixed iOS discovery session handling so stale NWBrowser, NetServiceBrowser, or resolver callbacks cannot complete a newer request.
108
+ - Fixed iOS discovery failures to return an error result instead of silently completing as a clean empty search.
109
+ - Fixed TXT record normalization on iOS and Electron so discovered values are returned as strings.
110
+ - Fixed Electron broadcast stop/destroy handling to avoid orphaned Bonjour advertisers.
@@ -9,9 +9,9 @@ Pod::Spec.new do |s|
9
9
  s.license = package['license']
10
10
  s.homepage = package['repository']['url']
11
11
  s.author = package['author']
12
- s.source = { :git => package['repository']['url'], :tag => s.version.to_s }
12
+ s.source = { :git => package['repository']['url'], :tag => "v#{s.version}" }
13
13
  s.source_files = 'ios/Sources/**/*.{swift,h,m,c,cc,mm,cpp}'
14
- s.ios.deployment_target = '14.0'
15
- s.dependency 'Capacitor'
14
+ s.ios.deployment_target = '15.0'
15
+ s.dependency 'Capacitor', '~> 8.0'
16
16
  s.swift_version = '5.1'
17
17
  end
package/Package.swift CHANGED
@@ -3,7 +3,7 @@ import PackageDescription
3
3
 
4
4
  let package = Package(
5
5
  name: "DevioartsCapacitorMdns",
6
- platforms: [.iOS(.v14)],
6
+ platforms: [.iOS(.v15)],
7
7
  products: [
8
8
  .library(
9
9
  name: "DevioartsCapacitorMdns",
package/README.md CHANGED
@@ -1,9 +1,13 @@
1
1
  # @devioarts/capacitor-mdns
2
2
 
3
- mDNS plugin for Capacitor that supports Bonjour/mDNS advertisements and discovery.
3
+ mDNS plugin for Capacitor that supports Bonjour/mDNS advertisements and discovery on iOS,
4
+ Android, Electron, and a safe web fallback.
4
5
 
5
- #### Supported platforms: ✓ iOS ✓ Android ✓ Electron
6
- #### Demo (sources): [application](https://github.com/devioarts/capacitor-examples/tree/main/capacitor-mdns) or directly [file](https://github.com/devioarts/capacitor-examples/blob/main/capacitor-mdns/src/Playground.tsx)
6
+ **Supported Capacitor version: v8. iOS 15 or later is required.**
7
+
8
+ #### Supported platforms: ✓ iOS ✓ Android ✓ Electron ✓ Web fallback
9
+
10
+ The in-repository [`playground`](./playground) is the example app used during development.
7
11
 
8
12
  ## Install
9
13
 
@@ -12,85 +16,88 @@ npm install @devioarts/capacitor-mdns
12
16
  npx cap sync
13
17
  ```
14
18
 
15
- ## Android
16
- #### /android/app/src/main/AndroidManifest.xml
17
- ```xml
18
- <uses-permission android:name="android.permission.INTERNET" />
19
- ```
19
+ For Electron, also install `bonjour-service@~1.4.0` and run `npx cap-electron sync`.
20
+ See the [Electron setup](./docs/electron.md) for details.
20
21
 
21
- ## iOS
22
- #### /ios/App/App/Info.plist
23
- ```xml
24
- <key>NSLocalNetworkUsageDescription</key>
25
- <string>It is needed for the correct functioning of the application</string>
26
- <key>NSAppTransportSecurity</key>
27
- <dict>
28
- <key>NSAllowsLocalNetworking</key>
29
- <true/>
30
- </dict>
31
- <key>NSBonjourServices</key>
32
- <array>
33
- <string>_http._tcp</string>
34
- </array>
35
- ```
22
+ ## Upgrading from 0.1.0
23
+
24
+ Version 0.2.0 retains the existing method signatures and result shapes and adds continuous
25
+ discovery. It also tightens input validation, changes overlapping discovery and error handling,
26
+ and raises the declared iOS minimum to 15.0. Review the
27
+ [upgrade notes](./CHANGELOG.md#020---2026-11-07) before updating an existing application.
28
+
29
+ ## Usage
30
+
31
+ ```ts
32
+ import { mDNS } from '@devioarts/capacitor-mdns';
36
33
 
37
- ---
38
- ## ElectronJS
34
+ const runtime = await mDNS.getPluginPlatform();
39
35
 
40
- ```shell
41
- npm i bonjour-service@1.3.0
36
+ await mDNS.startBroadcast({ type: '_http._tcp.', name: 'MyService', port: 9100 });
37
+ const result = await mDNS.discover({ type: '_http._tcp.', timeout: 3000 });
38
+ await mDNS.stopBroadcast();
42
39
  ```
43
40
 
44
- > Implementation example was developed on [capacitor-electron](https://github.com/devioarts/capacitor-examples/tree/main/capacitor-electron)
45
- > base, if you run electron differently, you may need to adjust the code.
41
+ ## Continuous discovery
46
42
 
47
- #### /electron/main.ts
43
+ Thank you, [Idrimi](https://github.com/Idrimi), for contributing the original continuous discovery
44
+ feature in [PR #7](https://github.com/devioarts/capacitor-mdns/pull/7).
48
45
 
49
- ```typescript
50
- // ...
51
- import { mDNS } from '@devioarts/capacitor-mdns/electron/mdns'
52
- // ...
53
- const mdns = new mDNS();
54
- // ...
55
- app.whenReady().then(() => {
56
- //...
57
- mdns.init();
58
- //...
46
+ `watchServices()` monitors multiple service types on iOS, Android and Electron until stopped.
47
+ Register listeners before starting; a new valid call replaces the previous watch.
48
+
49
+ ```ts
50
+ const found = await mDNS.addListener('serviceFound', ({ service }) => {
51
+ console.log('Found', service.name, service.hosts, service.port);
59
52
  });
60
- /* Or you can use app.on:ready (whenReady is recomended)
61
- app.on('ready', () => {
62
- // ...
63
- mdns.init();
64
- // ...
53
+ const lost = await mDNS.addListener('serviceLost', ({ service }) => {
54
+ console.log('Lost', service.name, service.hosts, service.port);
65
55
  });
66
- */
67
-
68
- app.on('before-quit', async () => {
69
- // ...
70
- mdns.destroy();
71
- // ...
72
- })
73
- //...
74
- ```
75
- ### electron/preload.cjs
76
- ```javascript
77
- //...
78
- // THIS IS IMPORTANT FOR PLUGIN!
79
- const {createMDNSAPI} = require("@devioarts/capacitor-mdns/electron/mdns-bridge.cjs");
80
- //...
81
- // THIS IS IMPORTANT FOR PLUGIN!
82
- contextBridge.exposeInMainWorld('mDNS', createMDNSAPI({ ipcRenderer }));
83
- contextBridge.exposeInMainWorld('mdns', createMDNSAPI({ ipcRenderer })) // alias
56
+ const errors = await mDNS.addListener('watchError', (event) => {
57
+ console.error(event.type, event.errorMessage, event.watching);
58
+ });
59
+
60
+ const result = await mDNS.watchServices({
61
+ types: ['_http._tcp.', '_airplay._tcp.', '_googlecast._tcp.'],
62
+ });
63
+ // Later, including when leaving the screen:
64
+ await mDNS.stopWatching();
65
+ await Promise.all([found.remove(), lost.remove(), errors.remove()]);
84
66
  ```
85
67
 
86
- ---
68
+ Found/lost events contain the full service snapshot; `hosts` is always an array. A service
69
+ that disappears before resolving emits neither event. Browser errors stop watching and emit
70
+ `watchError` with `watching: false`; exhausted resolution retries emit it with `watching: true`.
71
+ `stopWatching()` leaves broadcasting and one-shot discovery running. Browsers do not support mDNS.
72
+
73
+ ## Platform Setup
74
+
75
+
76
+ Android requires mDNS/network permissions in `AndroidManifest.xml`; the plugin also declares them
77
+ so they are merged during sync. iOS requires local network keys in `Info.plist`.
78
+ Electron support is intended for [`devioarts/capacitor-electron`](https://github.com/devioarts/capacitor-electron)
79
+ and uses metadata exported from `@devioarts/capacitor-mdns/electron/settings`.
80
+
81
+ Detailed setup lives in:
82
+
83
+ - [iOS and Android setup](./docs/platform-setup.md)
84
+ - [Electron setup](./docs/electron.md)
85
+ - [Playground](./docs/playground.md)
86
+ - [Runtime behavior](./docs/runtime-behavior.md)
87
+
87
88
  ## API
88
89
 
89
90
  <docgen-index>
90
91
 
92
+ * [`getPluginPlatform()`](#getpluginplatform)
91
93
  * [`startBroadcast(...)`](#startbroadcast)
92
94
  * [`stopBroadcast()`](#stopbroadcast)
93
95
  * [`discover(...)`](#discover)
96
+ * [`watchServices(...)`](#watchservices)
97
+ * [`stopWatching()`](#stopwatching)
98
+ * [`addListener('serviceFound' | 'serviceLost', ...)`](#addlistenerservicefound--servicelost-)
99
+ * [`addListener('watchError', ...)`](#addlistenerwatcherror-)
100
+ * [`removeAllListeners()`](#removealllisteners)
94
101
  * [Interfaces](#interfaces)
95
102
  * [Type Aliases](#type-aliases)
96
103
 
@@ -101,6 +108,19 @@ contextBridge.exposeInMainWorld('mdns', createMDNSAPI({ ipcRenderer })) // alias
101
108
 
102
109
  Public API surface of the Capacitor mDNS plugin.
103
110
 
111
+ ### getPluginPlatform()
112
+
113
+ ```typescript
114
+ getPluginPlatform() => Promise<MdnsPluginPlatformResult>
115
+ ```
116
+
117
+ Return the platform implementation currently serving plugin calls.
118
+
119
+ **Returns:** <code>Promise&lt;<a href="#mdnspluginplatformresult">MdnsPluginPlatformResult</a>&gt;</code>
120
+
121
+ --------------------
122
+
123
+
104
124
  ### startBroadcast(...)
105
125
 
106
126
  ```typescript
@@ -148,33 +168,118 @@ Discover services of a given type and optionally filter by instance name.
148
168
  --------------------
149
169
 
150
170
 
171
+ ### watchServices(...)
172
+
173
+ ```typescript
174
+ watchServices(options: MdnsWatchOptions) => Promise<MdnsWatchResult>
175
+ ```
176
+
177
+ Continuously watch several service types. A valid call replaces the previous watch.
178
+ Register listeners before starting. Each resolved service emits `serviceFound` once;
179
+ disappearance emits `serviceLost` with its last snapshot. No loss is emitted for an
180
+ unresolved service. Watching and one-shot discovery can run together.
181
+ Thanks to Idrimi for contributing the original continuous discovery feature (PR #7).
182
+
183
+ | Param | Type |
184
+ | ------------- | ------------------------------------------------------------- |
185
+ | **`options`** | <code><a href="#mdnswatchoptions">MdnsWatchOptions</a></code> |
186
+
187
+ **Returns:** <code>Promise&lt;<a href="#mdnswatchresult">MdnsWatchResult</a>&gt;</code>
188
+
189
+ --------------------
190
+
191
+
192
+ ### stopWatching()
193
+
194
+ ```typescript
195
+ stopWatching() => Promise<MdnsWatchStopResult>
196
+ ```
197
+
198
+ Stop all watchers. No events from that watch are emitted after this resolves.
199
+
200
+ **Returns:** <code>Promise&lt;<a href="#mdnswatchstopresult">MdnsWatchStopResult</a>&gt;</code>
201
+
202
+ --------------------
203
+
204
+
205
+ ### addListener('serviceFound' | 'serviceLost', ...)
206
+
207
+ ```typescript
208
+ addListener(eventName: 'serviceFound' | 'serviceLost', handler: (event: MdnsServiceEvent) => void) => Promise<PluginListenerHandle>
209
+ ```
210
+
211
+ | Param | Type |
212
+ | --------------- | --------------------------------------------------------------------------------- |
213
+ | **`eventName`** | <code>'serviceFound' \| 'serviceLost'</code> |
214
+ | **`handler`** | <code>(event: <a href="#mdnsserviceevent">MdnsServiceEvent</a>) =&gt; void</code> |
215
+
216
+ **Returns:** <code>Promise&lt;<a href="#pluginlistenerhandle">PluginListenerHandle</a>&gt;</code>
217
+
218
+ --------------------
219
+
220
+
221
+ ### addListener('watchError', ...)
222
+
223
+ ```typescript
224
+ addListener(eventName: 'watchError', handler: (event: MdnsWatchErrorEvent) => void) => Promise<PluginListenerHandle>
225
+ ```
226
+
227
+ | Param | Type |
228
+ | --------------- | --------------------------------------------------------------------------------------- |
229
+ | **`eventName`** | <code>'watchError'</code> |
230
+ | **`handler`** | <code>(event: <a href="#mdnswatcherrorevent">MdnsWatchErrorEvent</a>) =&gt; void</code> |
231
+
232
+ **Returns:** <code>Promise&lt;<a href="#pluginlistenerhandle">PluginListenerHandle</a>&gt;</code>
233
+
234
+ --------------------
235
+
236
+
237
+ ### removeAllListeners()
238
+
239
+ ```typescript
240
+ removeAllListeners() => Promise<void>
241
+ ```
242
+
243
+ --------------------
244
+
245
+
151
246
  ### Interfaces
152
247
 
153
248
 
249
+ #### MdnsPluginPlatformResult
250
+
251
+ Result of getPluginPlatform(). Useful for validating that calls are routed
252
+ through the expected platform bridge.
253
+
254
+ | Prop | Type | Description |
255
+ | -------------- | ----------------------------------------------------------------- | -------------------------------------------------- |
256
+ | **`platform`** | <code><a href="#mdnspluginplatform">MdnsPluginPlatform</a></code> | Platform implementation that produced this result. |
257
+
258
+
154
259
  #### MdnsBroadcastResult
155
260
 
156
261
  Result of startBroadcast(). Indicates whether advertising is active
157
262
  and the final service name. On failure, `error` is true and `errorMessage`
158
263
  describes the issue.
159
264
 
160
- | Prop | Type | Description |
161
- | ------------------ | --------------------------- | -------------------------------------------------------------------- |
162
- | **`error`** | <code>boolean</code> | True if the operation failed. |
163
- | **`errorMessage`** | <code>string \| null</code> | Error description or null on success. |
164
- | **`name`** | <code>string</code> | Final (possibly uniquified) service instance name. Empty on failure. |
165
- | **`publishing`** | <code>boolean</code> | Whether the advertiser is currently active. |
265
+ | Prop | Type | Description |
266
+ | ------------------ | --------------------------- | ----------------------------------------------------------------------------- |
267
+ | **`error`** | <code>boolean</code> | True if the operation failed. |
268
+ | **`errorMessage`** | <code>string \| null</code> | Error description or null on success. |
269
+ | **`name`** | <code>string</code> | Final (possibly uniquified) service instance name. Empty on failure. |
270
+ | **`publishing`** | <code>boolean</code> | Whether an advertiser is active, or may still be active after failed cleanup. |
166
271
 
167
272
 
168
273
  #### MdnsBroadcastOptions
169
274
 
170
275
  Options for starting a Bonjour/mDNS advertisement.
171
276
 
172
- | Prop | Type | Description |
173
- | ---------- | ------------------------------------------- | --------------------------------------------- |
174
- | **`type`** | <code>string</code> | Service type (including the trailing dot). |
175
- | **`name`** | <code>string</code> | Service instance name. |
176
- | **`port`** | <code>number</code> | TCP port to advertise. |
177
- | **`txt`** | <code><a href="#mdnstxt">MdnsTxt</a></code> | Optional TXT key–value pairs (UTF-8 strings). |
277
+ | Prop | Type | Description |
278
+ | ---------- | ------------------------------------------- | ---------------------------------------------------------------------------- |
279
+ | **`type`** | <code>string</code> | Service type (including the trailing dot). |
280
+ | **`name`** | <code>string</code> | Service instance name (maximum 63 UTF-8 bytes). Defaults to `DevIOArtsMDNS`. |
281
+ | **`port`** | <code>number</code> | TCP port to advertise. |
282
+ | **`txt`** | <code><a href="#mdnstxt">MdnsTxt</a></code> | Optional TXT key–value pairs (UTF-8 strings). |
178
283
 
179
284
 
180
285
  #### MdnsStopResult
@@ -182,23 +287,23 @@ Options for starting a Bonjour/mDNS advertisement.
182
287
  Result of stopBroadcast(). Indicates whether the advertiser is active
183
288
  after the call (normally false) and includes error information.
184
289
 
185
- | Prop | Type | Description |
186
- | ------------------ | --------------------------- | ------------------------------------------------------------------- |
187
- | **`error`** | <code>boolean</code> | True if an error occurred while stopping. |
188
- | **`errorMessage`** | <code>string \| null</code> | Error description or null on success. |
189
- | **`publishing`** | <code>boolean</code> | Whether the advertiser remains active (should be false on success). |
290
+ | Prop | Type | Description |
291
+ | ------------------ | --------------------------- | --------------------------------------------------------------------------------------------- |
292
+ | **`error`** | <code>boolean</code> | True if an error occurred while stopping. |
293
+ | **`errorMessage`** | <code>string \| null</code> | Error description or null on success. |
294
+ | **`publishing`** | <code>boolean</code> | False after confirmed stop; true when stopping failed and the advertiser may still be active. |
190
295
 
191
296
 
192
297
  #### MdnsDiscoverResult
193
298
 
194
299
  Result of discover(). Contains normalized services and error information.
195
300
 
196
- | Prop | Type | Description |
197
- | ------------------- | --------------------------- | ------------------------------------------------------------------------------ |
198
- | **`error`** | <code>boolean</code> | True if discovery encountered an error (partial results may still be present). |
199
- | **`errorMessage`** | <code>string \| null</code> | Error description or null when no error occurred. |
200
- | **`servicesFound`** | <code>number</code> | Convenience count equal to services.length. |
201
- | **`services`** | <code>MdnsService[]</code> | Normalized list of discovered services. |
301
+ | Prop | Type | Description |
302
+ | ------------------- | --------------------------- | ---------------------------------------------------------------------------------------- |
303
+ | **`error`** | <code>boolean</code> | True if discovery encountered an error (partial results may still be present). |
304
+ | **`errorMessage`** | <code>string \| null</code> | Error description or null when no error occurred. |
305
+ | **`servicesFound`** | <code>number</code> | Convenience count equal to services.length. |
306
+ | **`services`** | <code>MdnsService[]</code> | Resolved services with numeric addresses. Empty on error; partial results are discarded. |
202
307
 
203
308
 
204
309
  #### MdnsService
@@ -206,31 +311,97 @@ Result of discover(). Contains normalized services and error information.
206
311
  Normalized description of a discovered Bonjour/mDNS service.
207
312
  Returned from {@link mDNSPlugin.discover}.
208
313
 
209
- | Prop | Type | Description |
210
- | ------------ | ------------------------------------------- | ----------------------------------------------------------------------------------------- |
211
- | **`name`** | <code>string</code> | Instance name of the service (may be uniqued by the OS, e.g. "My App (2)"). |
212
- | **`type`** | <code>string</code> | Full service type including the trailing dot, e.g. `"_http._tcp."`. |
213
- | **`domain`** | <code>string</code> | Service domain; typically `"local."`. |
214
- | **`port`** | <code>number</code> | TCP port the service advertises. |
215
- | **`hosts`** | <code>string[]</code> | Resolved numeric IP addresses (IPv4/IPv6). |
216
- | **`txt`** | <code><a href="#mdnstxt">MdnsTxt</a></code> | TXT dictionary (key → value). Usually present on iOS; Android NSD does not populate this. |
314
+ | Prop | Type | Description |
315
+ | -------------- | ------------------------------------------- | ------------------------------------------------------------------------------------- |
316
+ | **`name`** | <code>string</code> | Instance name of the service (may be uniqued by the OS, e.g. "My App (2)"). |
317
+ | **`type`** | <code>string</code> | Full service type including the trailing dot, e.g. `"_http._tcp."`. |
318
+ | **`domain`** | <code>string</code> | Service domain; typically `"local."`. |
319
+ | **`port`** | <code>number</code> | Port the service advertises. |
320
+ | **`hosts`** | <code>string[]</code> | Resolved numeric IP addresses, IPv4 first, then IPv6 with any available scope suffix. |
321
+ | **`hostname`** | <code>string</code> | Host name when supplied by the platform, e.g. `"my-device.local."`. |
322
+ | **`txt`** | <code><a href="#mdnstxt">MdnsTxt</a></code> | TXT dictionary (key → value). |
217
323
 
218
324
 
219
325
  #### MdnsDiscoverOptions
220
326
 
221
327
  Options for Bonjour/mDNS discovery.
222
328
 
223
- | Prop | Type | Description |
224
- | ------------- | -------------------- | ---------------------------------------------------------------- |
225
- | **`type`** | <code>string</code> | Service type (including the trailing dot). |
226
- | **`name`** | <code>string</code> | Optional instance name filter (prefix-safe). |
227
- | **`timeout`** | <code>number</code> | Discovery timeout in milliseconds. |
228
- | **`useNW`** | <code>boolean</code> | iOS-only hint to use `NWBrowser` instead of `NetServiceBrowser`. |
329
+ | Prop | Type | Description |
330
+ | ------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------- |
331
+ | **`type`** | <code>string</code> | Service type (including the trailing dot). |
332
+ | **`name`** | <code>string</code> | Optional instance name filter (prefix-safe). |
333
+ | **`timeout`** | <code>number</code> | Discovery timeout in milliseconds. Finite numbers only; fractions are truncated and the delay is clamped to 0–2147483647. |
334
+ | **`useNW`** | <code>boolean</code> | iOS-only hint to use `NWBrowser` instead of `NetServiceBrowser`. |
335
+
336
+
337
+ #### MdnsWatchResult
338
+
339
+ Native browsers have been requested; later failures are reported through `watchError`.
340
+
341
+ | Prop | Type |
342
+ | --------------------- | --------------------------- |
343
+ | **`error`** | <code>boolean</code> |
344
+ | **`errorMessage`** | <code>string \| null</code> |
345
+ | **`watchersStarted`** | <code>number</code> |
346
+
347
+
348
+ #### MdnsWatchOptions
349
+
350
+ Options for continuous discovery on iOS, Android and Electron.
351
+
352
+ | Prop | Type | Description |
353
+ | ----------- | --------------------- | ---------------------------------------------------------------------------------- |
354
+ | **`types`** | <code>string[]</code> | Nonempty list of service types. Trailing dots are optional; duplicates are merged. |
355
+
356
+
357
+ #### MdnsWatchStopResult
358
+
359
+ Stops watching independently of any active broadcast.
360
+
361
+ | Prop | Type |
362
+ | ------------------ | --------------------------- |
363
+ | **`error`** | <code>boolean</code> |
364
+ | **`errorMessage`** | <code>string \| null</code> |
365
+ | **`watching`** | <code>boolean</code> |
366
+
367
+
368
+ #### PluginListenerHandle
369
+
370
+ | Prop | Type |
371
+ | ------------ | ----------------------------------------- |
372
+ | **`remove`** | <code>() =&gt; Promise&lt;void&gt;</code> |
373
+
374
+
375
+ #### MdnsServiceEvent
376
+
377
+ Both found and lost events contain a complete service snapshot, including `hosts`.
378
+
379
+ | Prop | Type |
380
+ | ------------- | --------------------------------------------------- |
381
+ | **`service`** | <code><a href="#mdnsservice">MdnsService</a></code> |
382
+
383
+
384
+ #### MdnsWatchErrorEvent
385
+
386
+ Browser failures stop the watch; exhausted service resolution retries leave it running.
387
+
388
+ | Prop | Type |
389
+ | ------------------ | -------------------- |
390
+ | **`type`** | <code>string</code> |
391
+ | **`errorMessage`** | <code>string</code> |
392
+ | **`watching`** | <code>boolean</code> |
229
393
 
230
394
 
231
395
  ### Type Aliases
232
396
 
233
397
 
398
+ #### MdnsPluginPlatform
399
+
400
+ Runtime implementation that handled a plugin call.
401
+
402
+ <code>'ios' | 'android' | 'electron' | 'web'</code>
403
+
404
+
234
405
  #### MdnsTxt
235
406
 
236
407
  Key–value map for TXT records of a Bonjour/mDNS service.
@@ -1,8 +1,6 @@
1
1
  ext {
2
2
  junitVersion = project.hasProperty('junitVersion') ? rootProject.ext.junitVersion : '4.13.2'
3
3
  androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.7.0'
4
- androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.2.1'
5
- androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.6.1'
6
4
  }
7
5
 
8
6
  buildscript {
@@ -25,9 +23,6 @@ android {
25
23
  defaultConfig {
26
24
  minSdk = project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 23
27
25
  targetSdk = project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 36
28
- versionCode = 1
29
- versionName = "1.0"
30
- testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
31
26
  }
32
27
  buildTypes {
33
28
  release {
@@ -36,7 +31,7 @@ android {
36
31
  }
37
32
  }
38
33
  lint {
39
- abortOnError = false
34
+ abortOnError = true
40
35
  }
41
36
  compileOptions {
42
37
  sourceCompatibility JavaVersion.VERSION_21
@@ -55,10 +50,9 @@ repositories {
55
50
 
56
51
 
57
52
  dependencies {
58
- implementation fileTree(dir: 'libs', include: ['*.jar'])
53
+ implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1"
59
54
  implementation project(':capacitor-android')
60
55
  implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
61
56
  testImplementation "junit:junit:$junitVersion"
62
- androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
63
- androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
57
+ testImplementation 'org.json:json:20250517'
64
58
  }
@@ -1,2 +1,4 @@
1
1
  <manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
+ <uses-permission android:name="android.permission.INTERNET" />
3
+ <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
2
4
  </manifest>