react-native-zeroconf 0.17.1 → 0.17.2

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.
package/README.md CHANGED
@@ -2,6 +2,14 @@
2
2
  <a href="https://zeroconf.balthazar.dev"><img src=".github/banner.png" alt="react-native-zeroconf: Bonjour / mDNS discovery and publishing for React Native, on iOS, Android, Windows, macOS, tvOS and Expo" width="100%"></a>
3
3
  </p>
4
4
 
5
+ <p align="center">
6
+ <a href="https://www.npmjs.com/package/react-native-zeroconf"><img src="https://img.shields.io/npm/v/react-native-zeroconf?style=flat" alt="npm version"></a>
7
+ <a href="https://www.npmjs.com/package/react-native-zeroconf"><img src="https://img.shields.io/npm/dm/react-native-zeroconf?style=flat" alt="npm downloads"></a>
8
+ <a href="https://github.com/balthazar/react-native-zeroconf/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/balthazar/react-native-zeroconf/ci.yml?branch=master&label=tests&style=flat" alt="tests"></a>
9
+ <a href="https://github.com/balthazar/react-native-zeroconf/actions/workflows/windows.yml"><img src="https://img.shields.io/github/actions/workflow/status/balthazar/react-native-zeroconf/windows.yml?branch=master&label=windows&style=flat" alt="windows"></a>
10
+ <a href="LICENSE"><img src="https://img.shields.io/npm/l/react-native-zeroconf?style=flat" alt="license"></a>
11
+ </p>
12
+
5
13
  Find the services other devices advertise on the local network (printers, speakers, cameras, your own servers) and advertise your own, on iOS, Android, macOS, tvOS and Windows.
6
14
 
7
15
  **[Read the documentation](https://zeroconf.balthazar.dev)**
@@ -532,6 +532,21 @@ public class NsdServiceImpl implements Zeroconf {
532
532
  return mNsdManager;
533
533
  }
534
534
 
535
+ // Before Android 14 each NsdManager client resolves one service at a time and a resolve can't be cancelled:
536
+ // a service that never answers would block every later resolve. After a timeout the queue moves on to a
537
+ // client of its own, an NsdManager from a new Context (system services are cached per Context)
538
+ @Nullable private volatile NsdManager mResolveManager;
539
+
540
+ private NsdManager getResolveManager() {
541
+ return mResolveManager != null ? mResolveManager : getNsdManager();
542
+ }
543
+
544
+ private void replaceResolveManager() {
545
+ Context context = getReactApplicationContext();
546
+ Context fresh = context.createConfigurationContext(context.getResources().getConfiguration());
547
+ mResolveManager = (NsdManager) fresh.getSystemService(Context.NSD_SERVICE);
548
+ }
549
+
535
550
  private ReactApplicationContext getReactApplicationContext() {
536
551
  return reactApplicationContext;
537
552
  }
@@ -560,8 +575,8 @@ public class NsdServiceImpl implements Zeroconf {
560
575
  }
561
576
  final ZeroResolveListener listener = new ZeroResolveListener(next);
562
577
  try {
563
- getNsdManager().resolveService(next.serviceInfo, listener);
564
- // The system keeps the resolve until it answers or fails, the queue waits for it
578
+ getResolveManager().resolveService(next.serviceInfo, listener);
579
+ // The queue waits for the answer, or moves on to another client after the timeout
565
580
  mHandler.postDelayed(listener::timedOut, (long) (next.timeoutSeconds * 1000));
566
581
  } catch (Throwable e) {
567
582
  Log.e(TAG, "resolveService failed", e);
@@ -582,7 +597,7 @@ public class NsdServiceImpl implements Zeroconf {
582
597
  private final PendingResolve pending;
583
598
  @Nullable private final String scanId;
584
599
  @Nullable private final Promise promise;
585
- // Settled: answered, failed or timed out. A late answer after the timeout only frees the queue
600
+ // Settled: answered, failed or timed out. A late answer after the timeout is ignored
586
601
  private boolean settled = false;
587
602
 
588
603
  ZeroResolveListener(PendingResolve pending) {
@@ -609,6 +624,8 @@ public class NsdServiceImpl implements Zeroconf {
609
624
  } else if (mScans.containsKey(scanId)) {
610
625
  sendResolveTimeout(serviceName, scanId);
611
626
  }
627
+ replaceResolveManager();
628
+ onResolveDone();
612
629
  }
613
630
 
614
631
  @Override
@@ -616,7 +633,6 @@ public class NsdServiceImpl implements Zeroconf {
616
633
  if (errorCode == NsdManager.FAILURE_ALREADY_ACTIVE) {
617
634
  // Another resolve (possibly from another app or listener) is in flight: retry shortly
618
635
  if (!settle()) {
619
- onResolveDone();
620
636
  return;
621
637
  }
622
638
  synchronized (mResolveQueue) {
@@ -627,7 +643,7 @@ public class NsdServiceImpl implements Zeroconf {
627
643
  return;
628
644
  }
629
645
  if (!settle()) {
630
- onResolveDone();
646
+ // Timed out: the queue already moved on to another client
631
647
  return;
632
648
  }
633
649
  String message = "Resolving service " + serviceInfo.getServiceName() + " failed: " + ZeroconfModule.describeNsdError(errorCode);
@@ -642,7 +658,7 @@ public class NsdServiceImpl implements Zeroconf {
642
658
  @Override
643
659
  public void onServiceResolved(NsdServiceInfo serviceInfo) {
644
660
  if (!settle()) {
645
- onResolveDone();
661
+ // Timed out: the queue already moved on to another client
646
662
  return;
647
663
  }
648
664
  if (promise != null) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-zeroconf",
3
- "version": "0.17.1",
3
+ "version": "0.17.2",
4
4
  "description": "A Zeroconf discovery utility for react-native",
5
5
  "main": "dist",
6
6
  "types": "index.d.ts",