@bits-innovate/react-native-vstarcam 1.0.43 → 1.0.44

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.
@@ -11,6 +11,7 @@ import com.facebook.react.bridge.ReactApplicationContext;
11
11
  import com.facebook.react.bridge.ReactContextBaseJavaModule;
12
12
  import com.facebook.react.bridge.ReactMethod;
13
13
  import com.facebook.react.bridge.WritableMap;
14
+ import com.facebook.react.module.annotations.ReactModule;
14
15
  import com.facebook.react.modules.core.DeviceEventManagerModule;
15
16
 
16
17
  import java.io.BufferedReader;
@@ -44,12 +45,21 @@ import org.json.JSONObject;
44
45
  * - writeCgi(long clientPtr, String cgi, int timeout)
45
46
  * - init(ClientStateListener, ClientCommandListener, ClientReleaseListener)
46
47
  */
48
+ @ReactModule(name = VStarCamModule.MODULE_NAME)
47
49
  public class VStarCamModule extends ReactContextBaseJavaModule {
48
50
  private static final String TAG = "VStarCamModule";
49
- private static final String MODULE_NAME = "VStarCam";
51
+ public final static String MODULE_NAME = "VStarCam";
50
52
 
51
53
  // Set to true for verbose logging during development
52
- private static final boolean DEBUG_LOGGING = false;
54
+ private static final boolean DEBUG_LOGGING = true;
55
+
56
+ // Counter for unique internal client IDs
57
+ private static final java.util.concurrent.atomic.AtomicInteger nextClientPtr = new java.util.concurrent.atomic.AtomicInteger(1000);
58
+
59
+ // Static proxy references to prevent GC.
60
+ private static Object stateListenerProxy;
61
+ private static Object commandListenerProxy;
62
+ private static Object releaseListenerProxy;
53
63
 
54
64
  // Helper for conditional debug logging
55
65
  private static void logDebug(String message) {
@@ -151,7 +161,7 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
151
161
 
152
162
  // Client tracking - maps our clientPtr to actual SDK client handle
153
163
  // Made static so VStarCamVideoView can access SDK pointers
154
- private static Map<Integer, ClientInfo> clients = new HashMap<>();
164
+ private static Map<Integer, ClientInfo> clients = new java.util.concurrent.ConcurrentHashMap<>();
155
165
  private boolean isNativeLibraryLoaded = false;
156
166
  private boolean isP2PInitialized = false;
157
167
 
@@ -243,15 +253,24 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
243
253
 
244
254
  try {
245
255
  // Create dynamic proxy for ClientStateListener
246
- Object stateListener = Proxy.newProxyInstance(
256
+ stateListenerProxy = Proxy.newProxyInstance(
247
257
  stateListenerClass.getClassLoader(),
248
258
  new Class<?>[] { stateListenerClass },
249
259
  new InvocationHandler() {
250
260
  @Override
251
261
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
252
262
  try {
253
- Log.d(TAG, "ClientStateListener." + method.getName() + " called with " + (args != null ? args.length : 0) + " args");
254
- if (method.getName().equals("stateListener")) {
263
+ String methodName = method.getName();
264
+
265
+ // Handle standard Object methods
266
+ if (method.getDeclaringClass() == Object.class) {
267
+ if (methodName.equals("equals")) return proxy == args[0];
268
+ if (methodName.equals("hashCode")) return System.identityHashCode(proxy);
269
+ if (methodName.equals("toString")) return proxy.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(proxy));
270
+ }
271
+
272
+ Log.d(TAG, "ClientStateListener." + methodName + " called");
273
+ if (methodName.equals("stateListener")) {
255
274
  // args: long clientPtr, int state
256
275
  final long clientPtr = (Long) args[0];
257
276
  final int state = (Integer) args[1];
@@ -276,15 +295,24 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
276
295
  );
277
296
 
278
297
  // Create dynamic proxy for ClientCommandListener
279
- Object commandListener = Proxy.newProxyInstance(
298
+ commandListenerProxy = Proxy.newProxyInstance(
280
299
  commandListenerClass.getClassLoader(),
281
300
  new Class<?>[] { commandListenerClass },
282
301
  new InvocationHandler() {
283
302
  @Override
284
303
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
285
304
  try {
286
- Log.d(TAG, "ClientCommandListener." + method.getName() + " called with " + (args != null ? args.length : 0) + " args");
287
- if (method.getName().equals("commandListener")) {
305
+ String methodName = method.getName();
306
+
307
+ // Handle standard Object methods
308
+ if (method.getDeclaringClass() == Object.class) {
309
+ if (methodName.equals("equals")) return proxy == args[0];
310
+ if (methodName.equals("hashCode")) return System.identityHashCode(proxy);
311
+ if (methodName.equals("toString")) return proxy.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(proxy));
312
+ }
313
+
314
+ Log.d(TAG, "ClientCommandListener." + methodName + " called");
315
+ if (methodName.equals("commandListener")) {
288
316
  // args: long clientPtr, byte[] data, int length (from interface)
289
317
  final long clientPtr = (Long) args[0];
290
318
  final byte[] data = (byte[]) args[1];
@@ -309,14 +337,23 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
309
337
  );
310
338
 
311
339
  // Create dynamic proxy for ClientReleaseListener
312
- Object releaseListener = Proxy.newProxyInstance(
340
+ releaseListenerProxy = Proxy.newProxyInstance(
313
341
  releaseListenerClass.getClassLoader(),
314
342
  new Class<?>[] { releaseListenerClass },
315
343
  new InvocationHandler() {
316
344
  @Override
317
345
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
318
346
  try {
319
- Log.d(TAG, "ClientReleaseListener." + method.getName() + " called");
347
+ String methodName = method.getName();
348
+
349
+ // Handle standard Object methods
350
+ if (method.getDeclaringClass() == Object.class) {
351
+ if (methodName.equals("equals")) return proxy == args[0];
352
+ if (methodName.equals("hashCode")) return System.identityHashCode(proxy);
353
+ if (methodName.equals("toString")) return proxy.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(proxy));
354
+ }
355
+
356
+ Log.d(TAG, "ClientReleaseListener." + methodName + " called");
320
357
  } catch (Exception e) {
321
358
  Log.e(TAG, "Error in releaseListener callback", e);
322
359
  }
@@ -328,7 +365,7 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
328
365
  // Call JNIApi.init(stateListener, commandListener, releaseListener)
329
366
  Method initMethod = jniApiClass.getMethod("init",
330
367
  stateListenerClass, commandListenerClass, releaseListenerClass);
331
- initMethod.invoke(null, stateListener, commandListener, releaseListener);
368
+ initMethod.invoke(null, stateListenerProxy, commandListenerProxy, releaseListenerProxy);
332
369
 
333
370
  isP2PInitialized = true;
334
371
  Log.d(TAG, "P2P system initialized successfully!");
@@ -537,6 +574,24 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
537
574
  });
538
575
  }
539
576
 
577
+ /**
578
+ * Get the current connection state of a client
579
+ */
580
+ @ReactMethod
581
+ public void clientGetState(int clientPtr, Promise promise) {
582
+ ClientInfo clientInfo = clients.get(clientPtr);
583
+ if (clientInfo == null) {
584
+ promise.resolve(5); // DISCONNECTED
585
+ return;
586
+ }
587
+
588
+ WritableMap result = Arguments.createMap();
589
+ result.putInt("state", clientInfo.isConnected ? 3 : 1); // 3=ONLINE, 1=CONNECTING (approx)
590
+ result.putBoolean("isConnected", clientInfo.isConnected);
591
+ result.putBoolean("isLoggedIn", clientInfo.isLoggedIn);
592
+ promise.resolve(result);
593
+ }
594
+
540
595
  /**
541
596
  * Login to camera
542
597
  * JNIApi.login(long clientPtr, String username, String password)
@@ -714,6 +769,42 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
714
769
  });
715
770
  }
716
771
 
772
+ /**
773
+ * Get device information
774
+ */
775
+ @ReactMethod
776
+ public void clientGetDeviceInfo(int clientPtr, Promise promise) {
777
+ executor.execute(() -> {
778
+ try {
779
+ ClientInfo clientInfo = clients.get(clientPtr);
780
+ if (clientInfo == null) {
781
+ promise.reject("E_CLIENT_NOT_FOUND", "Client not found");
782
+ return;
783
+ }
784
+
785
+ WritableMap result = Arguments.createMap();
786
+ result.putString("serialNumber", clientInfo.deviceId);
787
+ result.putString("model", "VStarCam");
788
+ result.putString("firmware", "Unknown");
789
+ result.putString("manufacturer", "VStarCam");
790
+ result.putBoolean("responsive", clientInfo.isConnected);
791
+
792
+ WritableMap features = Arguments.createMap();
793
+ features.putBoolean("ptz", true);
794
+ features.putBoolean("audio", true);
795
+ features.putBoolean("twoWayAudio", true);
796
+ features.putBoolean("nightVision", true);
797
+ features.putBoolean("motionDetection", true);
798
+ features.putBoolean("wifi", true);
799
+ result.putMap("features", features);
800
+
801
+ promise.resolve(result);
802
+ } catch (Exception e) {
803
+ promise.reject("E_GET_INFO_FAILED", e.getMessage());
804
+ }
805
+ });
806
+ }
807
+
717
808
  /**
718
809
  * Start video stream by sending livestream.cgi command
719
810
  * Resolution: 1=high, 2=general, 4=low, 100=superHD
@@ -90,6 +90,7 @@ public class VStarCamVideoView extends FrameLayout
90
90
  // Based on decompiling app_player-5.0.0.aar classes.jar
91
91
  String[] classNames = {
92
92
  "com.veepai.AppPlayerApi", // Main API class from AAR
93
+ "com.veepai.AppPlayer", // Added as alternative
93
94
  "com.veepai.app_player.AppPlayerPlugin", // Flutter plugin wrapper
94
95
  "com.vstarcam.player.AppPlayer",
95
96
  "com.vstarcam.AppPlayer",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bits-innovate/react-native-vstarcam",
3
- "version": "1.0.43",
3
+ "version": "1.0.44",
4
4
  "description": "React Native bridge for VStarCam P2P SDK",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",