@cappitolian/network-discovery 0.0.12 → 0.0.14

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.
@@ -1,217 +1,158 @@
1
- package com.cappitolian.plugins.networkdiscovery;
2
-
3
- import android.content.Context;
4
- import android.net.nsd.NsdManager;
5
- import android.net.nsd.NsdServiceInfo;
6
- import android.util.Log;
7
-
8
- import com.getcapacitor.JSObject;
9
- import com.getcapacitor.Plugin;
10
-
11
- import org.json.JSONArray;
12
- import org.json.JSONException;
13
-
14
- import java.net.InetAddress;
15
- import java.util.Map;
16
- import java.util.Iterator;
17
-
18
- public class NetworkDiscovery {
19
- private static final String TAG = "NetworkDiscovery";
20
- private NsdManager nsdManager;
21
- private NsdManager.RegistrationListener registrationListener;
22
- private NsdManager.DiscoveryListener discoveryListener;
23
- private NsdServiceInfo serviceInfo;
24
- private Plugin plugin;
25
-
26
- public NetworkDiscovery(Plugin plugin, Context context) {
27
- this.plugin = plugin;
28
- this.nsdManager = (NsdManager) context.getSystemService(Context.NSD_SERVICE);
29
- }
30
-
31
- public void startAdvertising(
32
- String serviceName,
33
- String serviceType,
34
- int port,
35
- JSObject txtRecord,
36
- AdvertisingCallback callback
37
- ) {
38
- serviceInfo = new NsdServiceInfo();
39
- serviceInfo.setServiceName(serviceName);
40
- serviceInfo.setServiceType(serviceType);
41
- serviceInfo.setPort(port);
42
-
43
- // Agregar TXT records
44
- if (txtRecord != null) {
45
- Iterator<String> keys = txtRecord.keys();
46
- while (keys.hasNext()) {
47
- String key = keys.next();
48
- try {
49
- String value = txtRecord.getString(key);
50
- serviceInfo.setAttribute(key, value);
51
- } catch (Exception e) {
52
- Log.e(TAG, "Error setting attribute: " + key, e);
53
- }
54
- }
55
- }
56
-
57
- registrationListener = new NsdManager.RegistrationListener() {
58
- @Override
59
- public void onRegistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {
60
- Log.e(TAG, "Service registration failed: " + errorCode);
61
- callback.onError("Registration failed with error code: " + errorCode);
62
- }
63
-
64
- @Override
65
- public void onUnregistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {
66
- Log.e(TAG, "Service unregistration failed: " + errorCode);
67
- }
68
-
69
- @Override
70
- public void onServiceRegistered(NsdServiceInfo serviceInfo) {
71
- Log.d(TAG, "Service registered: " + serviceInfo.getServiceName());
72
- callback.onSuccess();
73
- }
74
-
75
- @Override
76
- public void onServiceUnregistered(NsdServiceInfo serviceInfo) {
77
- Log.d(TAG, "Service unregistered");
78
- }
79
- };
80
-
81
- nsdManager.registerService(serviceInfo, NsdManager.PROTOCOL_DNS_SD, registrationListener);
82
- }
83
-
84
- public void stopAdvertising(StopCallback callback) {
85
- if (registrationListener != null) {
86
- try {
87
- nsdManager.unregisterService(registrationListener);
88
- registrationListener = null;
89
- callback.onSuccess();
90
- } catch (Exception e) {
91
- callback.onError("Error stopping advertising: " + e.getMessage());
92
- }
93
- } else {
94
- callback.onError("No active advertising to stop");
95
- }
96
- }
97
-
98
- public void startDiscovery(String serviceType, DiscoveryCallback callback) {
99
- discoveryListener = new NsdManager.DiscoveryListener() {
100
- @Override
101
- public void onStartDiscoveryFailed(String serviceType, int errorCode) {
102
- Log.e(TAG, "Discovery start failed: " + errorCode);
103
- nsdManager.stopServiceDiscovery(this);
104
- callback.onError("Discovery failed with error code: " + errorCode);
105
- }
106
-
107
- @Override
108
- public void onStopDiscoveryFailed(String serviceType, int errorCode) {
109
- Log.e(TAG, "Discovery stop failed: " + errorCode);
110
- }
111
-
112
- @Override
113
- public void onDiscoveryStarted(String serviceType) {
114
- Log.d(TAG, "Service discovery started");
115
- callback.onDiscoveryStarted();
116
- }
117
-
118
- @Override
119
- public void onDiscoveryStopped(String serviceType) {
120
- Log.d(TAG, "Service discovery stopped");
121
- }
122
-
123
- @Override
124
- public void onServiceFound(NsdServiceInfo service) {
125
- Log.d(TAG, "Service found: " + service.getServiceName());
126
-
127
- nsdManager.resolveService(service, new NsdManager.ResolveListener() {
128
- @Override
129
- public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
130
- Log.e(TAG, "Resolve failed: " + errorCode);
131
- }
132
-
133
- @Override
134
- public void onServiceResolved(NsdServiceInfo serviceInfo) {
135
- Log.d(TAG, "Service resolved: " + serviceInfo);
136
-
137
- JSObject serviceData = buildServiceObject(serviceInfo);
138
- callback.onServiceFound(serviceData);
139
- }
140
- });
141
- }
142
-
143
- @Override
144
- public void onServiceLost(NsdServiceInfo service) {
145
- Log.d(TAG, "Service lost: " + service.getServiceName());
146
-
147
- JSObject serviceData = new JSObject();
148
- serviceData.put("serviceName", service.getServiceName());
149
- serviceData.put("serviceType", service.getServiceType());
150
-
151
- callback.onServiceLost(serviceData);
152
- }
153
- };
154
-
155
- nsdManager.discoverServices(serviceType, NsdManager.PROTOCOL_DNS_SD, discoveryListener);
156
- }
157
-
158
- public void stopDiscovery(StopCallback callback) {
159
- if (discoveryListener != null) {
160
- try {
161
- nsdManager.stopServiceDiscovery(discoveryListener);
162
- discoveryListener = null;
163
- callback.onSuccess();
164
- } catch (Exception e) {
165
- callback.onError("Error stopping discovery: " + e.getMessage());
166
- }
167
- } else {
168
- callback.onError("No active discovery to stop");
169
- }
170
- }
171
-
172
- private JSObject buildServiceObject(NsdServiceInfo serviceInfo) {
173
- JSObject serviceData = new JSObject();
174
- serviceData.put("serviceName", serviceInfo.getServiceName());
175
- serviceData.put("serviceType", serviceInfo.getServiceType());
176
- serviceData.put("hostName", serviceInfo.getHost() != null ? serviceInfo.getHost().getHostName() : "");
177
- serviceData.put("port", serviceInfo.getPort());
178
-
179
- // Agregar direcciones IP
180
- InetAddress host = serviceInfo.getHost();
181
- if (host != null) {
182
- JSONArray addresses = new JSONArray();
183
- addresses.put(host.getHostAddress());
184
- serviceData.put("addresses", addresses);
185
- }
186
-
187
- // Agregar TXT records
188
- Map<String, byte[]> attributes = serviceInfo.getAttributes();
189
- if (attributes != null && !attributes.isEmpty()) {
190
- JSObject txtRecordObj = new JSObject();
191
- for (Map.Entry<String, byte[]> entry : attributes.entrySet()) {
192
- txtRecordObj.put(entry.getKey(), new String(entry.getValue()));
193
- }
194
- serviceData.put("txtRecord", txtRecordObj);
195
- }
196
-
197
- return serviceData;
198
- }
199
-
200
- // Callbacks interfaces
201
- public interface AdvertisingCallback {
202
- void onSuccess();
203
- void onError(String error);
204
- }
205
-
206
- public interface StopCallback {
207
- void onSuccess();
208
- void onError(String error);
209
- }
210
-
211
- public interface DiscoveryCallback {
212
- void onDiscoveryStarted();
213
- void onServiceFound(JSObject service);
214
- void onServiceLost(JSObject service);
215
- void onError(String error);
216
- }
1
+ package com.cappitolian.plugins.networkdiscovery;
2
+
3
+ import android.content.Context;
4
+ import android.net.nsd.NsdManager;
5
+ import android.net.nsd.NsdServiceInfo;
6
+ import android.net.wifi.WifiManager;
7
+ import android.os.Handler;
8
+ import android.os.Looper;
9
+ import com.getcapacitor.JSObject;
10
+ import java.nio.charset.StandardCharsets;
11
+ import java.util.Map;
12
+
13
+ public class NetworkDiscovery {
14
+ private NsdManager nsdManager;
15
+ private WifiManager.MulticastLock multicastLock;
16
+ private NsdManager.RegistrationListener activeRegistrationListener;
17
+ private NsdManager.DiscoveryListener activeDiscoveryListener;
18
+
19
+ public interface Callback {
20
+ void success(JSObject data);
21
+ void error(String msg);
22
+ }
23
+
24
+ public NetworkDiscovery(Context context) {
25
+ nsdManager = (NsdManager) context.getSystemService(Context.NSD_SERVICE);
26
+ WifiManager wm = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
27
+ multicastLock = wm.createMulticastLock("SSSPOS_Lock");
28
+ multicastLock.setReferenceCounted(true);
29
+ }
30
+
31
+ public void startServer(String name, String type, int port, Map<String, String> metadata, final Callback callback) {
32
+ stopServer(null);
33
+ if (!multicastLock.isHeld()) multicastLock.acquire();
34
+
35
+ // TRUCO: Incluimos la IP en el nombre por si los metadatos fallan en iOS
36
+ String ipForName = (metadata != null && metadata.containsKey("ip")) ? metadata.get("ip") : "";
37
+ String displayName = ipForName.isEmpty() ? name : name + "-" + ipForName;
38
+
39
+ NsdServiceInfo serviceInfo = new NsdServiceInfo();
40
+ serviceInfo.setServiceName(displayName);
41
+ serviceInfo.setServiceType(type);
42
+ serviceInfo.setPort(port);
43
+
44
+ // IMPORTANTE: Atributos antes de registrar
45
+ if (metadata != null) {
46
+ for (Map.Entry<String, String> entry : metadata.entrySet()) {
47
+ serviceInfo.setAttribute(entry.getKey().toLowerCase(), entry.getValue());
48
+ }
49
+ }
50
+
51
+ activeRegistrationListener = new NsdManager.RegistrationListener() {
52
+ @Override public void onServiceRegistered(NsdServiceInfo info) { callback.success(new JSObject()); }
53
+ @Override public void onRegistrationFailed(NsdServiceInfo info, int err) { callback.error("REG_ERR_" + err); }
54
+ @Override public void onServiceUnregistered(NsdServiceInfo info) {}
55
+ @Override public void onUnregistrationFailed(NsdServiceInfo info, int err) {}
56
+ };
57
+
58
+ nsdManager.registerService(serviceInfo, NsdManager.PROTOCOL_DNS_SD, activeRegistrationListener);
59
+ }
60
+
61
+ public void findServer(String name, String type, int timeout, final Callback callback) {
62
+ stopDiscovery();
63
+ if (!multicastLock.isHeld()) multicastLock.acquire();
64
+
65
+ final String cleanType = type.startsWith("_") ? type : "_" + type;
66
+ final boolean[] finished = {false};
67
+
68
+ activeDiscoveryListener = new NsdManager.DiscoveryListener() {
69
+ @Override public void onDiscoveryStarted(String s) {}
70
+ @Override public void onStartDiscoveryFailed(String s, int i) { if(!finished[0]){ finished[0]=true; callback.error("START_FAIL"); } }
71
+ @Override
72
+ public void onServiceFound(NsdServiceInfo service) {
73
+ // 1. Log para ver qué está viendo Android realmente antes de filtrar
74
+ System.out.println("NSD_DEBUG: Servicio encontrado en red: " + service.getServiceName());
75
+
76
+ // 2. Filtro estricto: El nombre debe empezar con el prefijo exacto
77
+ if (service.getServiceName().startsWith(name)) {
78
+ nsdManager.resolveService(service, new NsdManager.ResolveListener() {
79
+ @Override public void onResolveFailed(NsdServiceInfo nsi, int i) {
80
+ System.out.println("NSD_DEBUG: Fallo al resolver servicio: " + i);
81
+ }
82
+
83
+ @Override
84
+ public void onServiceResolved(NsdServiceInfo resolved) {
85
+ if (!finished[0]) {
86
+ String sName = resolved.getServiceName();
87
+
88
+ // --- LÓGICA ANTI-GHOSTING ---
89
+ // Intentamos sacar la IP del nombre primero (es la fuente de verdad)
90
+ String ipFromName = "";
91
+ if (sName.contains("-")) {
92
+ ipFromName = sName.substring(sName.lastIndexOf("-") + 1);
93
+ }
94
+
95
+ // Si el nombre no tiene IP, usamos la resuelta por el sistema
96
+ String resolvedIp = resolved.getHost().getHostAddress();
97
+ if (resolvedIp.startsWith("/")) resolvedIp = resolvedIp.substring(1);
98
+
99
+ // Decisión final de IP
100
+ String finalIp = (!ipFromName.isEmpty()) ? ipFromName : resolvedIp;
101
+
102
+ // IMPORTANTE: Si la IP resuelta es 0.0.0.0 o vacía, ignoramos este evento
103
+ if (finalIp.equals("0.0.0.0") || finalIp.isEmpty()) return;
104
+
105
+ finished[0] = true;
106
+ stopDiscovery();
107
+
108
+ JSObject res = new JSObject();
109
+ JSObject meta = new JSObject();
110
+ for (Map.Entry<String, byte[]> entry : resolved.getAttributes().entrySet()) {
111
+ meta.put(entry.getKey(), new String(entry.getValue(), StandardCharsets.UTF_8));
112
+ }
113
+
114
+ res.put("ip", finalIp);
115
+ res.put("port", resolved.getPort());
116
+ res.put("metadata", meta);
117
+
118
+ System.out.println("NSD_DEBUG: IP Final entregada al Cliente: " + finalIp);
119
+ callback.success(res);
120
+ }
121
+ }
122
+ });
123
+ }
124
+ }
125
+ @Override public void onStopDiscoveryFailed(String s, int i) {}
126
+ @Override public void onDiscoveryStopped(String s) {}
127
+ @Override public void onServiceLost(NsdServiceInfo s) {}
128
+ };
129
+
130
+ nsdManager.discoverServices(cleanType, NsdManager.PROTOCOL_DNS_SD, activeDiscoveryListener);
131
+ new Handler(Looper.getMainLooper()).postDelayed(() -> {
132
+ if (!finished[0]) { finished[0]=true; stopDiscovery(); callback.error("TIMEOUT_ERROR"); }
133
+ }, timeout);
134
+ }
135
+
136
+ public void stopServer(Callback c) {
137
+ if (activeRegistrationListener != null) { try { nsdManager.unregisterService(activeRegistrationListener); } catch (Exception e) {} }
138
+ activeRegistrationListener = null;
139
+ if (multicastLock.isHeld()) multicastLock.release();
140
+ if (c != null) c.success(new JSObject());
141
+ }
142
+
143
+ public void stopDiscovery() {
144
+ if (activeDiscoveryListener != null) {
145
+ try {
146
+ nsdManager.stopServiceDiscovery(activeDiscoveryListener);
147
+ System.out.println("NSD_DEBUG: Discovery detenido.");
148
+ } catch (Exception e) {
149
+ System.out.println("NSD_DEBUG: Error al detener discovery: " + e.getMessage());
150
+ }
151
+ activeDiscoveryListener = null;
152
+ }
153
+ // Liberamos el lock solo si se detiene por completo el proceso
154
+ if (multicastLock != null && multicastLock.isHeld()) {
155
+ multicastLock.release();
156
+ }
157
+ }
217
158
  }
@@ -1,116 +1,62 @@
1
- package com.cappitolian.plugins.networkdiscovery;
2
-
3
- import com.getcapacitor.JSObject;
4
- import com.getcapacitor.Plugin;
5
- import com.getcapacitor.PluginCall;
6
- import com.getcapacitor.PluginMethod;
7
- import com.getcapacitor.annotation.CapacitorPlugin;
8
-
9
- @CapacitorPlugin(name = "NetworkDiscovery")
10
- public class NetworkDiscoveryPlugin extends Plugin {
11
- private NetworkDiscovery implementation;
12
-
13
- @Override
14
- public void load() {
15
- implementation = new NetworkDiscovery(this, getContext());
16
- }
17
-
18
- @PluginMethod
19
- public void startAdvertising(PluginCall call) {
20
- String serviceName = call.getString("serviceName");
21
- String serviceType = call.getString("serviceType");
22
- Integer port = call.getInt("port");
23
- JSObject txtRecord = call.getObject("txtRecord");
24
-
25
- if (serviceName == null || serviceType == null || port == null) {
26
- call.reject("Missing required parameters");
27
- return;
28
- }
29
-
30
- implementation.startAdvertising(
31
- serviceName,
32
- serviceType,
33
- port,
34
- txtRecord,
35
- new NetworkDiscovery.AdvertisingCallback() {
36
- @Override
37
- public void onSuccess() {
38
- JSObject ret = new JSObject();
39
- ret.put("success", true);
40
- call.resolve(ret);
41
- }
42
-
43
- @Override
44
- public void onError(String error) {
45
- call.reject(error);
46
- }
47
- }
48
- );
49
- }
50
-
51
- @PluginMethod
52
- public void stopAdvertising(PluginCall call) {
53
- implementation.stopAdvertising(new NetworkDiscovery.StopCallback() {
54
- @Override
55
- public void onSuccess() {
56
- JSObject ret = new JSObject();
57
- ret.put("success", true);
58
- call.resolve(ret);
59
- }
60
-
61
- @Override
62
- public void onError(String error) {
63
- call.reject(error);
64
- }
65
- });
66
- }
67
-
68
- @PluginMethod
69
- public void startDiscovery(PluginCall call) {
70
- String serviceType = call.getString("serviceType");
71
-
72
- if (serviceType == null) {
73
- call.reject("Missing serviceType parameter");
74
- return;
75
- }
76
-
77
- implementation.startDiscovery(serviceType, new NetworkDiscovery.DiscoveryCallback() {
78
- @Override
79
- public void onDiscoveryStarted() {
80
- call.resolve();
81
- }
82
-
83
- @Override
84
- public void onServiceFound(JSObject service) {
85
- notifyListeners("serviceFound", service);
86
- }
87
-
88
- @Override
89
- public void onServiceLost(JSObject service) {
90
- notifyListeners("serviceLost", service);
91
- }
92
-
93
- @Override
94
- public void onError(String error) {
95
- call.reject(error);
96
- }
97
- });
98
- }
99
-
100
- @PluginMethod
101
- public void stopDiscovery(PluginCall call) {
102
- implementation.stopDiscovery(new NetworkDiscovery.StopCallback() {
103
- @Override
104
- public void onSuccess() {
105
- JSObject ret = new JSObject();
106
- ret.put("success", true);
107
- call.resolve(ret);
108
- }
109
-
110
- @Override
111
- public void onError(String error) {
112
- call.reject(error);
113
- }
114
- });
115
- }
1
+ package com.cappitolian.plugins.networkdiscovery;
2
+
3
+ import com.getcapacitor.JSObject;
4
+ import com.getcapacitor.Plugin;
5
+ import com.getcapacitor.PluginCall;
6
+ import com.getcapacitor.PluginMethod;
7
+ import com.getcapacitor.annotation.CapacitorPlugin;
8
+ import java.util.HashMap;
9
+ import java.util.Iterator;
10
+ import java.util.Map;
11
+
12
+ @CapacitorPlugin(name = "NetworkDiscovery")
13
+ public class NetworkDiscoveryPlugin extends Plugin {
14
+ private NetworkDiscovery implementation;
15
+
16
+ @Override
17
+ public void load() {
18
+ implementation = new NetworkDiscovery(getContext());
19
+ }
20
+
21
+ @PluginMethod
22
+ public void startServer(PluginCall call) {
23
+ String name = call.getString("serviceName");
24
+ String type = call.getString("serviceType");
25
+ Integer port = call.getInt("port", 8081);
26
+ JSObject metaJS = call.getObject("metadata");
27
+
28
+ Map<String, String> metadata = new HashMap<>();
29
+ if (metaJS != null) {
30
+ Iterator<String> keys = metaJS.keys();
31
+ while (keys.hasNext()) {
32
+ String key = keys.next();
33
+ metadata.put(key, metaJS.getString(key));
34
+ }
35
+ }
36
+
37
+ implementation.startServer(name, type, port, metadata, new NetworkDiscovery.Callback() {
38
+ @Override public void success(JSObject data) { call.resolve(data); }
39
+ @Override public void error(String msg) { call.reject(msg); }
40
+ });
41
+ }
42
+
43
+ @PluginMethod
44
+ public void stopServer(PluginCall call) {
45
+ implementation.stopServer(new NetworkDiscovery.Callback() {
46
+ @Override public void success(JSObject data) { call.resolve(data); }
47
+ @Override public void error(String msg) { call.reject(msg); }
48
+ });
49
+ }
50
+
51
+ @PluginMethod
52
+ public void findServer(PluginCall call) {
53
+ String name = call.getString("serviceName");
54
+ String type = call.getString("serviceType");
55
+ Integer timeout = call.getInt("timeout", 10000);
56
+
57
+ implementation.findServer(name, type, timeout, new NetworkDiscovery.Callback() {
58
+ @Override public void success(JSObject data) { call.resolve(data); }
59
+ @Override public void error(String msg) { call.reject(msg); }
60
+ });
61
+ }
116
62
  }