@cappitolian/network-discovery 0.0.7 → 0.0.9

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.
@@ -3,7 +3,6 @@ package com.cappitolian.plugins.networkdiscovery;
3
3
  import android.content.Context;
4
4
  import android.net.nsd.NsdManager;
5
5
  import android.net.nsd.NsdServiceInfo;
6
- import android.net.wifi.WifiManager;
7
6
  import android.util.Log;
8
7
 
9
8
  import com.getcapacitor.JSObject;
@@ -12,13 +11,13 @@ import com.getcapacitor.Plugin;
12
11
  import org.json.JSONArray;
13
12
 
14
13
  import java.net.InetAddress;
15
- import java.util.Map;
16
14
  import java.util.Iterator;
15
+ import java.util.Map;
17
16
 
18
17
  public class NetworkDiscovery {
18
+
19
19
  private static final String TAG = "NetworkDiscovery";
20
20
  private NsdManager nsdManager;
21
- private WifiManager.MulticastLock multicastLock;
22
21
  private NsdManager.RegistrationListener registrationListener;
23
22
  private NsdManager.DiscoveryListener discoveryListener;
24
23
  private NsdServiceInfo serviceInfo;
@@ -27,14 +26,6 @@ public class NetworkDiscovery {
27
26
  public NetworkDiscovery(Plugin plugin, Context context) {
28
27
  this.plugin = plugin;
29
28
  this.nsdManager = (NsdManager) context.getSystemService(Context.NSD_SERVICE);
30
-
31
- // Configuración del MulticastLock
32
- // Es vital para que Android responda a las peticiones mDNS de iOS
33
- WifiManager wifi = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
34
- if (wifi != null) {
35
- this.multicastLock = wifi.createMulticastLock("ssspos_discovery_lock");
36
- this.multicastLock.setReferenceCounted(true);
37
- }
38
29
  }
39
30
 
40
31
  public void startAdvertising(
@@ -44,12 +35,17 @@ public class NetworkDiscovery {
44
35
  JSObject txtRecord,
45
36
  AdvertisingCallback callback
46
37
  ) {
47
- // 1. Adquirir el lock antes de publicar
48
- acquireMulticastLock();
49
-
38
+ // Normalizar service type (agregar punto final si no lo tiene)
39
+ String normalizedServiceType = serviceType.endsWith(".") ? serviceType : serviceType + ".";
40
+
41
+ Log.d(TAG, "📡 Android: Starting advertising");
42
+ Log.d(TAG, " Service name: " + serviceName);
43
+ Log.d(TAG, " Service type (normalized): " + normalizedServiceType);
44
+ Log.d(TAG, " Port: " + port);
45
+
50
46
  serviceInfo = new NsdServiceInfo();
51
47
  serviceInfo.setServiceName(serviceName);
52
- serviceInfo.setServiceType(serviceType);
48
+ serviceInfo.setServiceType(normalizedServiceType);
53
49
  serviceInfo.setPort(port);
54
50
 
55
51
  // Agregar TXT records
@@ -60,6 +56,7 @@ public class NetworkDiscovery {
60
56
  try {
61
57
  String value = txtRecord.getString(key);
62
58
  serviceInfo.setAttribute(key, value);
59
+ Log.d(TAG, " TXT Record: " + key + " = " + value);
63
60
  } catch (Exception e) {
64
61
  Log.e(TAG, "Error setting attribute: " + key, e);
65
62
  }
@@ -69,26 +66,27 @@ public class NetworkDiscovery {
69
66
  registrationListener = new NsdManager.RegistrationListener() {
70
67
  @Override
71
68
  public void onRegistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {
72
- Log.e(TAG, "Service registration failed: " + errorCode);
73
- releaseMulticastLock(); // Liberar si falla
69
+ Log.e(TAG, "❌ Android: Service registration FAILED");
70
+ Log.e(TAG, " Error code: " + errorCode);
74
71
  callback.onError("Registration failed with error code: " + errorCode);
75
72
  }
76
73
 
77
74
  @Override
78
75
  public void onUnregistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {
79
- Log.e(TAG, "Service unregistration failed: " + errorCode);
76
+ Log.e(TAG, "❌ Android: Service unregistration FAILED");
77
+ Log.e(TAG, " Error code: " + errorCode);
80
78
  }
81
79
 
82
80
  @Override
83
81
  public void onServiceRegistered(NsdServiceInfo serviceInfo) {
84
- Log.d(TAG, "Service registered: " + serviceInfo.getServiceName());
82
+ Log.d(TAG, "✅ Android: Service registered successfully");
83
+ Log.d(TAG, " Service name: " + serviceInfo.getServiceName());
85
84
  callback.onSuccess();
86
85
  }
87
86
 
88
87
  @Override
89
88
  public void onServiceUnregistered(NsdServiceInfo serviceInfo) {
90
- Log.d(TAG, "Service unregistered");
91
- releaseMulticastLock();
89
+ Log.d(TAG, "⛔ Android: Service unregistered");
92
90
  }
93
91
  };
94
92
 
@@ -98,62 +96,76 @@ public class NetworkDiscovery {
98
96
  public void stopAdvertising(StopCallback callback) {
99
97
  if (registrationListener != null) {
100
98
  try {
99
+ Log.d(TAG, "⛔ Android: Stopping advertising");
101
100
  nsdManager.unregisterService(registrationListener);
102
101
  registrationListener = null;
103
- // El lock se libera en el callback onServiceUnregistered
104
102
  callback.onSuccess();
105
103
  } catch (Exception e) {
106
- releaseMulticastLock();
104
+ Log.e(TAG, "❌ Android: Error stopping advertising", e);
107
105
  callback.onError("Error stopping advertising: " + e.getMessage());
108
106
  }
109
107
  } else {
108
+ Log.w(TAG, "⚠️ Android: No active advertising to stop");
110
109
  callback.onError("No active advertising to stop");
111
110
  }
112
111
  }
113
112
 
114
113
  public void startDiscovery(String serviceType, DiscoveryCallback callback) {
115
- // También es recomendable adquirir el lock durante el discovery
116
- acquireMulticastLock();
117
-
114
+ // Normalizar service type
115
+ String normalizedServiceType = serviceType.endsWith(".") ? serviceType : serviceType + ".";
116
+
117
+ Log.d(TAG, "🔍 Android: Starting discovery");
118
+ Log.d(TAG, " Service type (normalized): " + normalizedServiceType);
119
+
118
120
  discoveryListener = new NsdManager.DiscoveryListener() {
119
121
  @Override
120
122
  public void onStartDiscoveryFailed(String serviceType, int errorCode) {
121
- Log.e(TAG, "Discovery start failed: " + errorCode);
123
+ Log.e(TAG, "❌ Android: Discovery start FAILED");
124
+ Log.e(TAG, " Service type: " + serviceType);
125
+ Log.e(TAG, " Error code: " + errorCode);
122
126
  nsdManager.stopServiceDiscovery(this);
123
- releaseMulticastLock();
124
127
  callback.onError("Discovery failed with error code: " + errorCode);
125
128
  }
126
129
 
127
130
  @Override
128
131
  public void onStopDiscoveryFailed(String serviceType, int errorCode) {
129
- Log.e(TAG, "Discovery stop failed: " + errorCode);
132
+ Log.e(TAG, "❌ Android: Discovery stop FAILED");
133
+ Log.e(TAG, " Error code: " + errorCode);
130
134
  }
131
135
 
132
136
  @Override
133
137
  public void onDiscoveryStarted(String serviceType) {
134
- Log.d(TAG, "Service discovery started");
138
+ Log.d(TAG, "✅ Android: Service discovery STARTED");
139
+ Log.d(TAG, " Service type: " + serviceType);
135
140
  callback.onDiscoveryStarted();
136
141
  }
137
142
 
138
143
  @Override
139
144
  public void onDiscoveryStopped(String serviceType) {
140
- Log.d(TAG, "Service discovery stopped");
141
- releaseMulticastLock();
145
+ Log.d(TAG, "⛔ Android: Service discovery STOPPED");
142
146
  }
143
147
 
144
148
  @Override
145
149
  public void onServiceFound(NsdServiceInfo service) {
146
- Log.d(TAG, "Service found: " + service.getServiceName());
150
+ Log.d(TAG, " Android: Service FOUND!");
151
+ Log.d(TAG, " Name: " + service.getServiceName());
152
+ Log.d(TAG, " Type: " + service.getServiceType());
147
153
 
148
154
  nsdManager.resolveService(service, new NsdManager.ResolveListener() {
149
155
  @Override
150
156
  public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
151
- Log.e(TAG, "Resolve failed: " + errorCode);
157
+ Log.e(TAG, " Android: Resolve FAILED");
158
+ Log.e(TAG, " Service: " + serviceInfo.getServiceName());
159
+ Log.e(TAG, " Error code: " + errorCode);
152
160
  }
153
161
 
154
162
  @Override
155
163
  public void onServiceResolved(NsdServiceInfo serviceInfo) {
156
- Log.d(TAG, "Service resolved: " + serviceInfo);
164
+ Log.d(TAG, " Android: Service RESOLVED");
165
+ Log.d(TAG, " Name: " + serviceInfo.getServiceName());
166
+ Log.d(TAG, " Host: " + (serviceInfo.getHost() != null ? serviceInfo.getHost().getHostAddress() : "null"));
167
+ Log.d(TAG, " Port: " + serviceInfo.getPort());
168
+
157
169
  JSObject serviceData = buildServiceObject(serviceInfo);
158
170
  callback.onServiceFound(serviceData);
159
171
  }
@@ -162,65 +174,55 @@ public class NetworkDiscovery {
162
174
 
163
175
  @Override
164
176
  public void onServiceLost(NsdServiceInfo service) {
165
- Log.d(TAG, "Service lost: " + service.getServiceName());
177
+ Log.d(TAG, " Android: Service LOST");
178
+ Log.d(TAG, " Name: " + service.getServiceName());
179
+
166
180
  JSObject serviceData = new JSObject();
167
181
  serviceData.put("serviceName", service.getServiceName());
168
182
  serviceData.put("serviceType", service.getServiceType());
183
+
169
184
  callback.onServiceLost(serviceData);
170
185
  }
171
186
  };
172
187
 
173
- nsdManager.discoverServices(serviceType, NsdManager.PROTOCOL_DNS_SD, discoveryListener);
188
+ nsdManager.discoverServices(normalizedServiceType, NsdManager.PROTOCOL_DNS_SD, discoveryListener);
174
189
  }
175
190
 
176
191
  public void stopDiscovery(StopCallback callback) {
177
192
  if (discoveryListener != null) {
178
193
  try {
194
+ Log.d(TAG, "⛔ Android: Stopping discovery");
179
195
  nsdManager.stopServiceDiscovery(discoveryListener);
180
196
  discoveryListener = null;
181
197
  callback.onSuccess();
182
198
  } catch (Exception e) {
183
- releaseMulticastLock();
199
+ Log.e(TAG, "❌ Android: Error stopping discovery", e);
184
200
  callback.onError("Error stopping discovery: " + e.getMessage());
185
201
  }
186
202
  } else {
203
+ Log.w(TAG, "⚠️ Android: No active discovery to stop");
187
204
  callback.onError("No active discovery to stop");
188
205
  }
189
206
  }
190
207
 
191
- private void acquireMulticastLock() {
192
- if (multicastLock != null && !multicastLock.isHeld()) {
193
- multicastLock.acquire();
194
- Log.d(TAG, "MulticastLock acquired");
195
- }
196
- }
197
-
198
- private void releaseMulticastLock() {
199
- if (multicastLock != null && multicastLock.isHeld()) {
200
- multicastLock.release();
201
- Log.d(TAG, "MulticastLock released");
202
- }
203
- }
204
-
205
208
  private JSObject buildServiceObject(NsdServiceInfo serviceInfo) {
206
209
  JSObject serviceData = new JSObject();
207
210
  serviceData.put("serviceName", serviceInfo.getServiceName());
208
211
  serviceData.put("serviceType", serviceInfo.getServiceType());
212
+ serviceData.put("domain", "local.");
209
213
  serviceData.put("hostName", serviceInfo.getHost() != null ? serviceInfo.getHost().getHostName() : "");
210
214
  serviceData.put("port", serviceInfo.getPort());
211
215
 
212
- InetAddress host = serviceInfo.getHost();
213
- if (host != null) {
214
- JSONArray addresses = new JSONArray();
215
- addresses.put(host.getHostAddress());
216
- serviceData.put("addresses", addresses);
217
- }
216
+ // NO incluir addresses - Solo usar txtRecord para la IP
218
217
 
218
+ // Agregar TXT records (aquí está tu IP correcta)
219
219
  Map<String, byte[]> attributes = serviceInfo.getAttributes();
220
220
  if (attributes != null && !attributes.isEmpty()) {
221
221
  JSObject txtRecordObj = new JSObject();
222
222
  for (Map.Entry<String, byte[]> entry : attributes.entrySet()) {
223
- txtRecordObj.put(entry.getKey(), new String(entry.getValue()));
223
+ String value = new String(entry.getValue());
224
+ txtRecordObj.put(entry.getKey(), value);
225
+ Log.d(TAG, " TXT Record retrieved: " + entry.getKey() + " = " + value);
224
226
  }
225
227
  serviceData.put("txtRecord", txtRecordObj);
226
228
  }
@@ -228,6 +230,7 @@ public class NetworkDiscovery {
228
230
  return serviceData;
229
231
  }
230
232
 
233
+ // Callbacks interfaces
231
234
  public interface AdvertisingCallback {
232
235
  void onSuccess();
233
236
  void onError(String error);
@@ -13,13 +13,22 @@ import Foundation
13
13
  port: Int,
14
14
  txtRecord: [String: String]?
15
15
  ) {
16
- netService = NetService(domain: "local.", type: serviceType, name: serviceName, port: Int32(port))
16
+ // Normalizar service type (agregar punto final si no lo tiene)
17
+ let normalizedServiceType = serviceType.hasSuffix(".") ? serviceType : serviceType + "."
18
+
19
+ print("📡 iOS: Starting advertising")
20
+ print(" Service name: \(serviceName)")
21
+ print(" Service type (normalized): \(normalizedServiceType)")
22
+ print(" Port: \(port)")
23
+
24
+ netService = NetService(domain: "local.", type: normalizedServiceType, name: serviceName, port: Int32(port))
17
25
 
18
26
  // Configurar TXT record
19
27
  if let txtRecord = txtRecord, !txtRecord.isEmpty {
20
28
  var txtData: [String: Data] = [:]
21
29
  for (key, value) in txtRecord {
22
30
  txtData[key] = value.data(using: .utf8)
31
+ print(" TXT Record: \(key) = \(value)")
23
32
  }
24
33
  let txtRecordData = NetService.data(fromTXTRecord: txtData)
25
34
  netService?.setTXTRecord(txtRecordData)
@@ -30,17 +39,26 @@ import Foundation
30
39
  }
31
40
 
32
41
  @objc public func stopAdvertising() {
42
+ print("⛔ iOS: Stopping advertising")
33
43
  netService?.stop()
34
44
  netService = nil
35
45
  }
36
46
 
37
47
  @objc public func startDiscovery(serviceType: String, domain: String = "local.") {
48
+ // ✅ Normalizar service type
49
+ let normalizedServiceType = serviceType.hasSuffix(".") ? serviceType : serviceType + "."
50
+
51
+ print("🔍 iOS: Starting discovery")
52
+ print(" Service type (normalized): \(normalizedServiceType)")
53
+ print(" Domain: \(domain)")
54
+
38
55
  netServiceBrowser = NetServiceBrowser()
39
56
  netServiceBrowser?.delegate = self
40
- netServiceBrowser?.searchForServices(ofType: serviceType, inDomain: domain)
57
+ netServiceBrowser?.searchForServices(ofType: normalizedServiceType, inDomain: domain)
41
58
  }
42
59
 
43
60
  @objc public func stopDiscovery() {
61
+ print("⛔ iOS: Stopping discovery")
44
62
  netServiceBrowser?.stop()
45
63
  netServiceBrowser = nil
46
64
  discoveredServices.removeAll()
@@ -49,39 +67,60 @@ import Foundation
49
67
 
50
68
  // MARK: - NetServiceDelegate
51
69
  extension NetworkDiscovery: NetServiceDelegate {
70
+ public func netServiceWillPublish(_ sender: NetService) {
71
+ print("🔄 iOS: Service WILL publish: \(sender.name)")
72
+ }
73
+
52
74
  public func netServiceDidPublish(_ sender: NetService) {
53
- print("Service published: \(sender.name)")
75
+ print("✅ iOS: Service published successfully")
76
+ print(" Name: \(sender.name)")
77
+ print(" Type: \(sender.type)")
78
+ print(" Port: \(sender.port)")
54
79
  delegate?.advertisingDidStart()
55
80
  }
56
81
 
57
82
  public func netService(_ sender: NetService, didNotPublish errorDict: [String : NSNumber]) {
58
- print("Service did not publish: \(errorDict)")
83
+ print("❌ iOS: Service did NOT publish")
84
+ print(" Error dict: \(errorDict)")
59
85
  let errorCode = errorDict[NetService.errorCode]?.intValue ?? -1
86
+ print(" Error code: \(errorCode)")
60
87
  delegate?.advertisingDidFail(error: "Failed to publish service. Error code: \(errorCode)")
61
88
  }
62
89
  }
63
90
 
64
91
  // MARK: - NetServiceBrowserDelegate
65
92
  extension NetworkDiscovery: NetServiceBrowserDelegate {
93
+ public func netServiceBrowserWillSearch(_ browser: NetServiceBrowser) {
94
+ print("🔄 iOS: Browser WILL search")
95
+ }
96
+
66
97
  public func netServiceBrowserDidStopSearch(_ browser: NetServiceBrowser) {
67
- print("Service discovery stopped")
98
+ print(" iOS: Browser DID stop search")
68
99
  }
69
100
 
70
101
  public func netServiceBrowser(_ browser: NetServiceBrowser, didNotSearch errorDict: [String : NSNumber]) {
71
- print("Service discovery failed: \(errorDict)")
102
+ print(" iOS: Browser did NOT search")
103
+ print(" Error dict: \(errorDict)")
72
104
  let errorCode = errorDict[NetService.errorCode]?.intValue ?? -1
105
+ print(" Error code: \(errorCode)")
73
106
  delegate?.discoveryDidFail(error: "Discovery failed. Error code: \(errorCode)")
74
107
  }
75
108
 
76
109
  public func netServiceBrowser(_ browser: NetServiceBrowser, didFind service: NetService, moreComing: Bool) {
77
- print("Service found: \(service.name)")
110
+ print(" iOS: Service FOUND!")
111
+ print(" Name: \(service.name)")
112
+ print(" Type: \(service.type)")
113
+ print(" Domain: \(service.domain)")
114
+ print(" More coming: \(moreComing)")
115
+
78
116
  discoveredServices.append(service)
79
117
  service.delegate = self
80
118
  service.resolve(withTimeout: 5.0)
81
119
  }
82
120
 
83
121
  public func netServiceBrowser(_ browser: NetServiceBrowser, didRemove service: NetService, moreComing: Bool) {
84
- print("Service lost: \(service.name)")
122
+ print(" iOS: Service LOST")
123
+ print(" Name: \(service.name)")
85
124
 
86
125
  let serviceData: [String: Any] = [
87
126
  "serviceName": service.name,
@@ -95,46 +134,33 @@ extension NetworkDiscovery: NetServiceBrowserDelegate {
95
134
  }
96
135
  }
97
136
 
137
+ public func netServiceWillResolve(_ sender: NetService) {
138
+ print("🔄 iOS: Service WILL resolve: \(sender.name)")
139
+ }
140
+
98
141
  public func netServiceDidResolveAddress(_ sender: NetService) {
99
- print("Service resolved: \(sender.name)")
100
-
101
- var addresses: [String] = []
102
-
103
- if let addressesData = sender.addresses {
104
- for addressData in addressesData {
105
- let address = addressData.withUnsafeBytes { (pointer: UnsafeRawBufferPointer) -> String? in
106
- guard let baseAddress = pointer.baseAddress else { return nil }
107
- let data = baseAddress.assumingMemoryBound(to: sockaddr.self)
108
-
109
- var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
110
- if getnameinfo(data, socklen_t(addressData.count), &hostname, socklen_t(hostname.count), nil, 0, NI_NUMERICHOST) == 0 {
111
- return String(cString: hostname)
112
- }
113
- return nil
114
- }
115
-
116
- if let addr = address {
117
- addresses.append(addr)
118
- }
119
- }
120
- }
142
+ print(" iOS: Service RESOLVED")
143
+ print(" Name: \(sender.name)")
144
+ print(" Host: \(sender.hostName ?? "nil")")
145
+ print(" Port: \(sender.port)")
121
146
 
147
+ // ✅ NO incluir addresses - Solo usar txtRecord
122
148
  var serviceData: [String: Any] = [
123
149
  "serviceName": sender.name,
124
150
  "serviceType": sender.type,
125
151
  "domain": sender.domain,
126
152
  "hostName": sender.hostName ?? "",
127
- "port": sender.port,
128
- "addresses": addresses
153
+ "port": sender.port
129
154
  ]
130
155
 
131
- // Agregar TXT record
156
+ // SOLO agregar TXT record (aquí está tu IP correcta)
132
157
  if let txtData = sender.txtRecordData() {
133
158
  let txtRecord = NetService.dictionary(fromTXTRecord: txtData)
134
159
  var txtRecordDict: [String: String] = [:]
135
160
  for (key, value) in txtRecord {
136
161
  if let strValue = String(data: value, encoding: .utf8) {
137
162
  txtRecordDict[key] = strValue
163
+ print(" TXT Record retrieved: \(key) = \(strValue)")
138
164
  }
139
165
  }
140
166
  serviceData["txtRecord"] = txtRecordDict
@@ -144,7 +170,9 @@ extension NetworkDiscovery: NetServiceBrowserDelegate {
144
170
  }
145
171
 
146
172
  public func netService(_ sender: NetService, didNotResolve errorDict: [String : NSNumber]) {
147
- print("Service did not resolve: \(errorDict)")
173
+ print("❌ iOS: Service did NOT resolve")
174
+ print(" Service: \(sender.name)")
175
+ print(" Error dict: \(errorDict)")
148
176
  }
149
177
  }
150
178
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cappitolian/network-discovery",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
4
4
  "description": "A Capacitor plugin for network service discovery using mDNS/Bonjour. Allows automatic server-client connection without manual IP configuration.",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",