@bits-innovate/react-native-vstarcam 1.0.15 → 1.0.17

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.
@@ -13,13 +13,21 @@ import com.facebook.react.bridge.ReactMethod;
13
13
  import com.facebook.react.bridge.WritableMap;
14
14
  import com.facebook.react.modules.core.DeviceEventManagerModule;
15
15
 
16
+ import java.io.BufferedReader;
17
+ import java.io.InputStreamReader;
16
18
  import java.lang.reflect.InvocationHandler;
17
19
  import java.lang.reflect.Method;
18
20
  import java.lang.reflect.Proxy;
21
+ import java.net.HttpURLConnection;
22
+ import java.net.URL;
19
23
  import java.util.HashMap;
20
24
  import java.util.Map;
21
25
  import java.util.concurrent.ExecutorService;
22
26
  import java.util.concurrent.Executors;
27
+ import java.util.regex.Pattern;
28
+
29
+ import org.json.JSONObject;
30
+
23
31
 
24
32
  /**
25
33
  * VStarCam React Native Module
@@ -78,6 +86,56 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
78
86
  return param;
79
87
  }
80
88
 
89
+ // Pattern to detect virtual UIDs (like ACAE0001151GWYQ)
90
+ // Virtual UIDs: start with letters, have 7+ digits, end with letters
91
+ private static final Pattern VIRTUAL_UID_PATTERN = Pattern.compile("^[a-zA-Z]{1,}\\d{7,}.*[a-zA-Z]$");
92
+
93
+ // Check if a device ID is a virtual UID that needs conversion
94
+ private static boolean isVirtualId(String deviceId) {
95
+ if (deviceId == null || deviceId.length() < 10) return false;
96
+ return VIRTUAL_UID_PATTERN.matcher(deviceId).matches();
97
+ }
98
+
99
+ // Convert virtual UID to real client ID using VStarCam API
100
+ // Returns: {uid, supplier, cluster} or null on failure
101
+ private String[] convertVirtualUid(String virtualUid) {
102
+ try {
103
+ URL url = new URL("https://vuid.eye4.cn?vuid=" + virtualUid);
104
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection();
105
+ conn.setRequestMethod("GET");
106
+ conn.setConnectTimeout(10000);
107
+ conn.setReadTimeout(10000);
108
+ conn.setRequestProperty("Content-Type", "application/json; charset=utf-8");
109
+
110
+ int responseCode = conn.getResponseCode();
111
+ if (responseCode == 200) {
112
+ BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
113
+ StringBuilder response = new StringBuilder();
114
+ String line;
115
+ while ((line = reader.readLine()) != null) {
116
+ response.append(line);
117
+ }
118
+ reader.close();
119
+
120
+ JSONObject json = new JSONObject(response.toString());
121
+ String uid = json.optString("uid", null);
122
+ String supplier = json.optString("supplier", "");
123
+ String cluster = json.optString("cluster", "");
124
+
125
+ if (uid != null && !uid.isEmpty()) {
126
+ Log.d(TAG, "Converted virtual UID " + virtualUid + " -> real UID: " + uid + " (supplier: " + supplier + ", cluster: " + cluster + ")");
127
+ return new String[]{uid, supplier, cluster};
128
+ }
129
+ } else {
130
+ Log.e(TAG, "Virtual UID conversion failed, HTTP " + responseCode);
131
+ }
132
+ conn.disconnect();
133
+ } catch (Exception e) {
134
+ Log.e(TAG, "Failed to convert virtual UID: " + e.getMessage(), e);
135
+ }
136
+ return null;
137
+ }
138
+
81
139
  private final ReactApplicationContext reactContext;
82
140
  private final ExecutorService executor;
83
141
 
@@ -93,12 +151,14 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
93
151
  private Class<?> releaseListenerClass = null;
94
152
 
95
153
  private static class ClientInfo {
96
- String deviceId;
97
- long sdkClientPtr = 0; // Actual SDK client pointer (long)
154
+ String deviceId; // Original device ID (can be virtual UID)
155
+ String realClientId; // Converted client ID (for JNI calls)
156
+ long sdkClientPtr = 0; // Actual SDK client pointer (long)
98
157
  boolean isConnected = false;
99
158
  boolean isLoggedIn = false;
100
159
  }
101
160
 
161
+
102
162
  public VStarCamModule(ReactApplicationContext reactContext) {
103
163
  super(reactContext);
104
164
  this.reactContext = reactContext;
@@ -334,10 +394,23 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
334
394
  return;
335
395
  }
336
396
 
337
- // Call JNIApi.create(did, serverParam)
338
- String serviceParam = getServiceParam(deviceId);
397
+ // Check if this is a virtual UID that needs conversion
398
+ String realClientId = deviceId;
399
+ if (isVirtualId(deviceId)) {
400
+ Log.d(TAG, "Device ID " + deviceId + " looks like a virtual UID, converting...");
401
+ String[] conversionResult = convertVirtualUid(deviceId);
402
+ if (conversionResult != null && conversionResult[0] != null) {
403
+ realClientId = conversionResult[0];
404
+ Log.d(TAG, "Using converted client ID: " + realClientId);
405
+ } else {
406
+ Log.w(TAG, "Virtual UID conversion failed, trying with original ID");
407
+ }
408
+ }
409
+
410
+ // Call JNIApi.create(did, serverParam) with real client ID
411
+ String serviceParam = getServiceParam(realClientId); // Use real client ID prefix
339
412
  Method createMethod = jniApiClass.getMethod("create", String.class, String.class);
340
- Object result = createMethod.invoke(null, deviceId, serviceParam);
413
+ Object result = createMethod.invoke(null, realClientId, serviceParam);
341
414
  long sdkClientPtr = (Long) result;
342
415
 
343
416
  Log.d(TAG, "JNIApi.create result: " + sdkClientPtr);
@@ -353,10 +426,11 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
353
426
 
354
427
  ClientInfo clientInfo = new ClientInfo();
355
428
  clientInfo.deviceId = deviceId;
429
+ clientInfo.realClientId = realClientId; // Store the converted ID
356
430
  clientInfo.sdkClientPtr = sdkClientPtr;
357
431
  clients.put(ourClientPtr, clientInfo);
358
432
 
359
- Log.d(TAG, "Created client: ourPtr=" + ourClientPtr + ", sdkPtr=" + sdkClientPtr);
433
+ Log.d(TAG, "Created client: ourPtr=" + ourClientPtr + ", sdkPtr=" + sdkClientPtr + ", realId=" + realClientId);
360
434
  promise.resolve(ourClientPtr);
361
435
  } catch (Exception e) {
362
436
  Log.e(TAG, "clientCreate failed", e);
@@ -392,19 +466,25 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
392
466
  params.putInt("state", 1); // CONNECTING
393
467
  sendEvent("onConnectionStateChanged", params);
394
468
 
469
+ // Use realClientId for service param lookup (it has the correct prefix like VSTN)
470
+ String realId = clientInfo.realClientId != null ? clientInfo.realClientId : clientInfo.deviceId;
395
471
  String param = (serverParam != null && !serverParam.isEmpty())
396
472
  ? serverParam
397
- : getServiceParam(clientInfo.deviceId);
473
+ : getServiceParam(realId);
474
+
475
+ // Default connectType to 126 (from V1 app) if not specified
476
+ // connectType 126 = P2P/Relay combination that works reliably
477
+ int actualConnectType = (connectType <= 0) ? 126 : connectType;
398
478
 
399
479
  // Call JNIApi.connect(sdkClientPtr, timeout, serverParam, connectType)
400
480
  // Signature: connect([long, int, class java.lang.String, int])
401
481
  Method connectMethod = jniApiClass.getMethod("connect",
402
482
  long.class, int.class, String.class, int.class);
403
483
 
404
- Log.d(TAG, "Calling JNIApi.connect(" + clientInfo.sdkClientPtr + ", 15, " + param + ", " + connectType + ")");
484
+ Log.d(TAG, "Calling JNIApi.connect(" + clientInfo.sdkClientPtr + ", 15, " + param + ", " + actualConnectType + ")");
405
485
 
406
486
  try {
407
- connectMethod.invoke(null, clientInfo.sdkClientPtr, 15, param, connectType);
487
+ connectMethod.invoke(null, clientInfo.sdkClientPtr, 15, param, actualConnectType);
408
488
  Log.d(TAG, "JNIApi.connect returned normally");
409
489
  } catch (java.lang.reflect.InvocationTargetException ite) {
410
490
  Log.e(TAG, "JNIApi.connect threw exception: " + ite.getCause(), ite.getCause());
@@ -459,7 +539,17 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
459
539
  long.class, String.class, String.class);
460
540
 
461
541
  Log.d(TAG, "Calling JNIApi.login(" + clientInfo.sdkClientPtr + ", " + username + ", ***)");
462
- loginMethod.invoke(null, clientInfo.sdkClientPtr, username, password);
542
+
543
+ try {
544
+ loginMethod.invoke(null, clientInfo.sdkClientPtr, username, password);
545
+ Log.d(TAG, "JNIApi.login returned normally");
546
+ } catch (java.lang.reflect.InvocationTargetException ite) {
547
+ Log.e(TAG, "JNIApi.login threw exception: " + ite.getCause(), ite.getCause());
548
+ throw ite;
549
+ } catch (Throwable t) {
550
+ Log.e(TAG, "JNIApi.login crashed: " + t.getMessage(), t);
551
+ throw t;
552
+ }
463
553
 
464
554
  clientInfo.isLoggedIn = true;
465
555
  Log.d(TAG, "JNIApi.login called successfully");
@@ -614,25 +704,38 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
614
704
  */
615
705
  @ReactMethod
616
706
  public void clientCheckMode(int clientPtr, Promise promise) {
707
+ Log.d(TAG, "clientCheckMode called for: " + clientPtr);
617
708
  try {
618
709
  ClientInfo clientInfo = clients.get(clientPtr);
619
710
 
620
711
  int mode = 0;
621
- if (clientInfo != null && jniApiClass != null && clientInfo.sdkClientPtr > 0) {
712
+ // Note: sdkClientPtr can be negative (unsigned to signed cast) - only check != 0
713
+ if (clientInfo != null && jniApiClass != null && clientInfo.sdkClientPtr != 0) {
622
714
  try {
623
715
  Method checkModeMethod = jniApiClass.getMethod("checkMode", long.class);
624
716
  Object result = checkModeMethod.invoke(null, clientInfo.sdkClientPtr);
625
717
  mode = (Integer) result;
626
- Log.d(TAG, "JNIApi.checkMode result: " + mode);
718
+ Log.d(TAG, "JNIApi.checkMode result: " + mode + " (0=none, 1=P2P, 2=relay, 3=sock)");
627
719
  } catch (Exception e) {
628
- Log.e(TAG, "checkMode failed", e);
720
+ Log.e(TAG, "checkMode JNI call failed", e);
629
721
  }
722
+ } else {
723
+ Log.w(TAG, "checkMode skipped: clientInfo=" + clientInfo +
724
+ ", jniApiClass=" + (jniApiClass != null) +
725
+ ", sdkPtr=" + (clientInfo != null ? clientInfo.sdkClientPtr : "null"));
726
+ }
727
+
728
+ // Mode > 0 means connected (1=P2P, 2=Relay, 3=Socket)
729
+ boolean connected = mode > 0;
730
+ if (connected && clientInfo != null) {
731
+ clientInfo.isConnected = true;
630
732
  }
631
733
 
632
734
  WritableMap result = Arguments.createMap();
633
- result.putBoolean("success", clientInfo != null && clientInfo.isConnected);
735
+ result.putBoolean("success", connected);
634
736
  result.putInt("mode", mode);
635
737
  result.putDouble("sessionHandle", clientInfo != null ? clientInfo.sdkClientPtr : -1);
738
+ Log.d(TAG, "clientCheckMode returning: success=" + connected + ", mode=" + mode);
636
739
  promise.resolve(result);
637
740
  } catch (Exception e) {
638
741
  Log.e(TAG, "clientCheckMode failed", e);
@@ -654,7 +757,7 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
654
757
  @ReactMethod
655
758
  public void getSdkVersion(Promise promise) {
656
759
  WritableMap result = Arguments.createMap();
657
- result.putString("version", "1.0.15");
760
+ result.putString("version", "1.0.17");
658
761
  result.putBoolean("nativeLoaded", isNativeLibraryLoaded);
659
762
  result.putString("nativeLib", "OKSMARTPPCS");
660
763
  result.putBoolean("p2pInitialized", isP2PInitialized);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bits-innovate/react-native-vstarcam",
3
- "version": "1.0.15",
3
+ "version": "1.0.17",
4
4
  "description": "React Native bridge for VStarCam P2P SDK",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",