@bits-innovate/react-native-vstarcam 1.0.14 → 1.0.16

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;
@@ -297,6 +357,20 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
297
357
  return MODULE_NAME;
298
358
  }
299
359
 
360
+ // Required by NativeEventEmitter
361
+ @ReactMethod
362
+ public void addListener(String eventName) {
363
+ // Keep: Required for RN built in Event Emitter Calls
364
+ Log.d(TAG, "addListener called for: " + eventName);
365
+ }
366
+
367
+ // Required by NativeEventEmitter
368
+ @ReactMethod
369
+ public void removeListeners(Integer count) {
370
+ // Keep: Required for RN built in Event Emitter Calls
371
+ Log.d(TAG, "removeListeners called with count: " + count);
372
+ }
373
+
300
374
  private void sendEvent(String eventName, @Nullable WritableMap params) {
301
375
  if (reactContext.hasActiveReactInstance()) {
302
376
  reactContext
@@ -320,10 +394,23 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
320
394
  return;
321
395
  }
322
396
 
323
- // Call JNIApi.create(did, serverParam)
324
- 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
325
412
  Method createMethod = jniApiClass.getMethod("create", String.class, String.class);
326
- Object result = createMethod.invoke(null, deviceId, serviceParam);
413
+ Object result = createMethod.invoke(null, realClientId, serviceParam);
327
414
  long sdkClientPtr = (Long) result;
328
415
 
329
416
  Log.d(TAG, "JNIApi.create result: " + sdkClientPtr);
@@ -339,10 +426,11 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
339
426
 
340
427
  ClientInfo clientInfo = new ClientInfo();
341
428
  clientInfo.deviceId = deviceId;
429
+ clientInfo.realClientId = realClientId; // Store the converted ID
342
430
  clientInfo.sdkClientPtr = sdkClientPtr;
343
431
  clients.put(ourClientPtr, clientInfo);
344
432
 
345
- Log.d(TAG, "Created client: ourPtr=" + ourClientPtr + ", sdkPtr=" + sdkClientPtr);
433
+ Log.d(TAG, "Created client: ourPtr=" + ourClientPtr + ", sdkPtr=" + sdkClientPtr + ", realId=" + realClientId);
346
434
  promise.resolve(ourClientPtr);
347
435
  } catch (Exception e) {
348
436
  Log.e(TAG, "clientCreate failed", e);
@@ -378,17 +466,33 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
378
466
  params.putInt("state", 1); // CONNECTING
379
467
  sendEvent("onConnectionStateChanged", params);
380
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;
381
471
  String param = (serverParam != null && !serverParam.isEmpty())
382
472
  ? serverParam
383
- : 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;
384
478
 
385
479
  // Call JNIApi.connect(sdkClientPtr, timeout, serverParam, connectType)
386
480
  // Signature: connect([long, int, class java.lang.String, int])
387
481
  Method connectMethod = jniApiClass.getMethod("connect",
388
482
  long.class, int.class, String.class, int.class);
389
483
 
390
- Log.d(TAG, "Calling JNIApi.connect(" + clientInfo.sdkClientPtr + ", 15, " + param + ", " + connectType + ")");
391
- connectMethod.invoke(null, clientInfo.sdkClientPtr, 15, param, connectType);
484
+ Log.d(TAG, "Calling JNIApi.connect(" + clientInfo.sdkClientPtr + ", 15, " + param + ", " + actualConnectType + ")");
485
+
486
+ try {
487
+ connectMethod.invoke(null, clientInfo.sdkClientPtr, 15, param, actualConnectType);
488
+ Log.d(TAG, "JNIApi.connect returned normally");
489
+ } catch (java.lang.reflect.InvocationTargetException ite) {
490
+ Log.e(TAG, "JNIApi.connect threw exception: " + ite.getCause(), ite.getCause());
491
+ throw ite;
492
+ } catch (Throwable t) {
493
+ Log.e(TAG, "JNIApi.connect crashed: " + t.getMessage(), t);
494
+ throw t;
495
+ }
392
496
 
393
497
  Log.d(TAG, "JNIApi.connect called - waiting for state callback");
394
498
 
@@ -590,25 +694,38 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
590
694
  */
591
695
  @ReactMethod
592
696
  public void clientCheckMode(int clientPtr, Promise promise) {
697
+ Log.d(TAG, "clientCheckMode called for: " + clientPtr);
593
698
  try {
594
699
  ClientInfo clientInfo = clients.get(clientPtr);
595
700
 
596
701
  int mode = 0;
597
- if (clientInfo != null && jniApiClass != null && clientInfo.sdkClientPtr > 0) {
702
+ // Note: sdkClientPtr can be negative (unsigned to signed cast) - only check != 0
703
+ if (clientInfo != null && jniApiClass != null && clientInfo.sdkClientPtr != 0) {
598
704
  try {
599
705
  Method checkModeMethod = jniApiClass.getMethod("checkMode", long.class);
600
706
  Object result = checkModeMethod.invoke(null, clientInfo.sdkClientPtr);
601
707
  mode = (Integer) result;
602
- Log.d(TAG, "JNIApi.checkMode result: " + mode);
708
+ Log.d(TAG, "JNIApi.checkMode result: " + mode + " (0=none, 1=P2P, 2=relay, 3=sock)");
603
709
  } catch (Exception e) {
604
- Log.e(TAG, "checkMode failed", e);
710
+ Log.e(TAG, "checkMode JNI call failed", e);
605
711
  }
712
+ } else {
713
+ Log.w(TAG, "checkMode skipped: clientInfo=" + clientInfo +
714
+ ", jniApiClass=" + (jniApiClass != null) +
715
+ ", sdkPtr=" + (clientInfo != null ? clientInfo.sdkClientPtr : "null"));
716
+ }
717
+
718
+ // Mode > 0 means connected (1=P2P, 2=Relay, 3=Socket)
719
+ boolean connected = mode > 0;
720
+ if (connected && clientInfo != null) {
721
+ clientInfo.isConnected = true;
606
722
  }
607
723
 
608
724
  WritableMap result = Arguments.createMap();
609
- result.putBoolean("success", clientInfo != null && clientInfo.isConnected);
725
+ result.putBoolean("success", connected);
610
726
  result.putInt("mode", mode);
611
727
  result.putDouble("sessionHandle", clientInfo != null ? clientInfo.sdkClientPtr : -1);
728
+ Log.d(TAG, "clientCheckMode returning: success=" + connected + ", mode=" + mode);
612
729
  promise.resolve(result);
613
730
  } catch (Exception e) {
614
731
  Log.e(TAG, "clientCheckMode failed", e);
@@ -630,7 +747,7 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
630
747
  @ReactMethod
631
748
  public void getSdkVersion(Promise promise) {
632
749
  WritableMap result = Arguments.createMap();
633
- result.putString("version", "1.0.14");
750
+ result.putString("version", "1.0.16");
634
751
  result.putBoolean("nativeLoaded", isNativeLibraryLoaded);
635
752
  result.putString("nativeLib", "OKSMARTPPCS");
636
753
  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.14",
3
+ "version": "1.0.16",
4
4
  "description": "React Native bridge for VStarCam P2P SDK",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",