@bits-innovate/react-native-vstarcam 1.0.42 → 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.
|
@@ -35,11 +35,20 @@ import org.json.JSONObject;
|
|
|
35
35
|
*
|
|
36
36
|
* Implements P2P camera connectivity using the VStarCam SDK.
|
|
37
37
|
* Uses JNI calls to the native OKSMARTPPCS library via JNIApi class.
|
|
38
|
+
*
|
|
39
|
+
* JNI API Methods (discovered via reflection):
|
|
40
|
+
* - create(String did, String serverParam) -> long clientPtr
|
|
41
|
+
* - connect(long clientPtr, int timeout, String serverParam, int connectType)
|
|
42
|
+
* - login(long clientPtr, String username, String password)
|
|
43
|
+
* - disconnect(long clientPtr)
|
|
44
|
+
* - destroy(long clientPtr)
|
|
45
|
+
* - writeCgi(long clientPtr, String cgi, int timeout)
|
|
46
|
+
* - init(ClientStateListener, ClientCommandListener, ClientReleaseListener)
|
|
38
47
|
*/
|
|
39
|
-
@ReactModule(name =
|
|
48
|
+
@ReactModule(name = VStarCamModule.MODULE_NAME)
|
|
40
49
|
public class VStarCamModule extends ReactContextBaseJavaModule {
|
|
41
50
|
private static final String TAG = "VStarCamModule";
|
|
42
|
-
public static
|
|
51
|
+
public final static String MODULE_NAME = "VStarCam";
|
|
43
52
|
|
|
44
53
|
// Set to true for verbose logging during development
|
|
45
54
|
private static final boolean DEBUG_LOGGING = true;
|
|
@@ -78,8 +87,6 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
|
|
|
78
87
|
put("VSKM", "EIHGFNBAKMIIGLJEEAHKFEEJHLNBHCNIGFFDBLCMAKJNLELPDDAGCNOOGILMJFLJAOMKLADEOEMJAPCDJCNPJF:veepai2024");
|
|
79
88
|
put("VSLL", "EIHGFOBBKKIOGNJKENHHFKEEGMNOHLMNHBFKBBDOAHJBLMKIDLAJCAPIGDLBJGLKAOMILNDJOJMGAHCLJHNMJG:veepai2024");
|
|
80
89
|
put("ACAE", "EEGDFHBLKGJIGEJLEKGOFMEDHAMHHJNAGGFABMCOBGJOLHLJDFAFCPPHGILKIKLMANNHKEDKOINIBNCPJOMK:vstarcam2018"); // Try VSTH params
|
|
81
|
-
put("ACDG", "EEGDFHBLKGJIGEJLEKGOFMEDHAMHHJNAGGFABMCOBGJOLHLJDFAFCPPHGILKIKLMANNHKEDKOINIBNCPJOMK:vstarcam2018"); // Same as ACAE/VSTH
|
|
82
|
-
put("ACAQ", "EEGDFHBLKGJIGEJLEKGOFMEDHAMHHJNAGGFABMCOBGJOLHLJDFAFCPPHGILKIKLMANNHKEDKOINIBNCPJOMK:vstarcam2018"); // Same as ACAE/VSTH
|
|
83
90
|
// Fallback for unknown prefixes
|
|
84
91
|
put("DEFAULT", "EBGBEMBMKGJMGAJPEIGIFKEGHBMCHMNFGKEGBFCBBMJELILDCJADCIOLHHLLJBKEAMMBLCDGONMDBJCJJPNFJP");
|
|
85
92
|
}};
|
|
@@ -99,7 +106,56 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
|
|
|
99
106
|
return param;
|
|
100
107
|
}
|
|
101
108
|
|
|
102
|
-
|
|
109
|
+
// Pattern to detect virtual UIDs (like ACAE0001151GWYQ)
|
|
110
|
+
// Virtual UIDs: start with letters, have 7+ digits, end with letters
|
|
111
|
+
private static final Pattern VIRTUAL_UID_PATTERN = Pattern.compile("^[a-zA-Z]{1,}\\d{7,}.*[a-zA-Z]$");
|
|
112
|
+
|
|
113
|
+
// Check if a device ID is a virtual UID that needs conversion
|
|
114
|
+
private static boolean isVirtualId(String deviceId) {
|
|
115
|
+
if (deviceId == null || deviceId.length() < 10) return false;
|
|
116
|
+
return VIRTUAL_UID_PATTERN.matcher(deviceId).matches();
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Convert virtual UID to real client ID using VStarCam API
|
|
120
|
+
// Returns: {uid, supplier, cluster} or null on failure
|
|
121
|
+
private String[] convertVirtualUid(String virtualUid) {
|
|
122
|
+
try {
|
|
123
|
+
URL url = new URL("https://vuid.eye4.cn?vuid=" + virtualUid);
|
|
124
|
+
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
|
125
|
+
conn.setRequestMethod("GET");
|
|
126
|
+
conn.setConnectTimeout(10000);
|
|
127
|
+
conn.setReadTimeout(10000);
|
|
128
|
+
conn.setRequestProperty("Content-Type", "application/json; charset=utf-8");
|
|
129
|
+
|
|
130
|
+
int responseCode = conn.getResponseCode();
|
|
131
|
+
if (responseCode == 200) {
|
|
132
|
+
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
|
|
133
|
+
StringBuilder response = new StringBuilder();
|
|
134
|
+
String line;
|
|
135
|
+
while ((line = reader.readLine()) != null) {
|
|
136
|
+
response.append(line);
|
|
137
|
+
}
|
|
138
|
+
reader.close();
|
|
139
|
+
|
|
140
|
+
JSONObject json = new JSONObject(response.toString());
|
|
141
|
+
String uid = json.optString("uid", null);
|
|
142
|
+
String supplier = json.optString("supplier", "");
|
|
143
|
+
String cluster = json.optString("cluster", "");
|
|
144
|
+
|
|
145
|
+
if (uid != null && !uid.isEmpty()) {
|
|
146
|
+
Log.d(TAG, "Converted virtual UID " + virtualUid + " -> real UID: " + uid + " (supplier: " + supplier + ", cluster: " + cluster + ")");
|
|
147
|
+
return new String[]{uid, supplier, cluster};
|
|
148
|
+
}
|
|
149
|
+
} else {
|
|
150
|
+
Log.e(TAG, "Virtual UID conversion failed, HTTP " + responseCode);
|
|
151
|
+
}
|
|
152
|
+
conn.disconnect();
|
|
153
|
+
} catch (Exception e) {
|
|
154
|
+
Log.e(TAG, "Failed to convert virtual UID: " + e.getMessage(), e);
|
|
155
|
+
}
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
|
|
103
159
|
private final ReactApplicationContext reactContext;
|
|
104
160
|
private final ExecutorService executor;
|
|
105
161
|
|
|
@@ -116,7 +172,8 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
|
|
|
116
172
|
private Class<?> releaseListenerClass = null;
|
|
117
173
|
|
|
118
174
|
private static class ClientInfo {
|
|
119
|
-
String deviceId; // Original device ID
|
|
175
|
+
String deviceId; // Original device ID (can be virtual UID)
|
|
176
|
+
String realClientId; // Converted client ID (for JNI calls)
|
|
120
177
|
long sdkClientPtr = 0; // Actual SDK client pointer (long)
|
|
121
178
|
boolean isConnected = false;
|
|
122
179
|
boolean isLoggedIn = false;
|
|
@@ -158,11 +215,25 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
|
|
|
158
215
|
Log.d(TAG, "JNIApi class found: " + jniApiClass.getName());
|
|
159
216
|
|
|
160
217
|
// Load listener interfaces
|
|
161
|
-
stateListenerClass = Class.forName("com.vstarcam.app_p2p_api.ClientStateListener"
|
|
162
|
-
commandListenerClass = Class.forName("com.vstarcam.app_p2p_api.ClientCommandListener"
|
|
163
|
-
releaseListenerClass = Class.forName("com.vstarcam.app_p2p_api.ClientReleaseListener"
|
|
218
|
+
stateListenerClass = Class.forName("com.vstarcam.app_p2p_api.ClientStateListener");
|
|
219
|
+
commandListenerClass = Class.forName("com.vstarcam.app_p2p_api.ClientCommandListener");
|
|
220
|
+
releaseListenerClass = Class.forName("com.vstarcam.app_p2p_api.ClientReleaseListener");
|
|
164
221
|
Log.d(TAG, "Listener interfaces loaded");
|
|
165
222
|
|
|
223
|
+
// Log all methods on each listener for debugging
|
|
224
|
+
Log.d(TAG, "ClientStateListener methods:");
|
|
225
|
+
for (Method m : stateListenerClass.getDeclaredMethods()) {
|
|
226
|
+
Log.d(TAG, " -> " + m.getName() + "(" + java.util.Arrays.toString(m.getParameterTypes()) + ")");
|
|
227
|
+
}
|
|
228
|
+
Log.d(TAG, "ClientCommandListener methods:");
|
|
229
|
+
for (Method m : commandListenerClass.getDeclaredMethods()) {
|
|
230
|
+
Log.d(TAG, " -> " + m.getName() + "(" + java.util.Arrays.toString(m.getParameterTypes()) + ")");
|
|
231
|
+
}
|
|
232
|
+
Log.d(TAG, "ClientReleaseListener methods:");
|
|
233
|
+
for (Method m : releaseListenerClass.getDeclaredMethods()) {
|
|
234
|
+
Log.d(TAG, " -> " + m.getName() + "(" + java.util.Arrays.toString(m.getParameterTypes()) + ")");
|
|
235
|
+
}
|
|
236
|
+
|
|
166
237
|
// Initialize P2P system with listeners
|
|
167
238
|
initializeP2P();
|
|
168
239
|
} catch (ClassNotFoundException e) {
|
|
@@ -242,16 +313,17 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
|
|
|
242
313
|
|
|
243
314
|
Log.d(TAG, "ClientCommandListener." + methodName + " called");
|
|
244
315
|
if (methodName.equals("commandListener")) {
|
|
245
|
-
|
|
316
|
+
// args: long clientPtr, byte[] data, int length (from interface)
|
|
317
|
+
final long clientPtr = (Long) args[0];
|
|
246
318
|
final byte[] data = (byte[]) args[1];
|
|
247
319
|
final int length = (Integer) args[2];
|
|
248
|
-
Log.d(TAG, "Command callback:
|
|
320
|
+
Log.d(TAG, "Command callback: clientPtr=" + clientPtr + ", dataLen=" + (data != null ? data.length : 0));
|
|
249
321
|
|
|
250
322
|
if (reactContext != null) {
|
|
251
323
|
reactContext.runOnUiQueueThread(new Runnable() {
|
|
252
324
|
@Override
|
|
253
325
|
public void run() {
|
|
254
|
-
handleCommandReceive(
|
|
326
|
+
handleCommandReceive(clientPtr, 0, data);
|
|
255
327
|
}
|
|
256
328
|
});
|
|
257
329
|
}
|
|
@@ -383,10 +455,23 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
|
|
|
383
455
|
return;
|
|
384
456
|
}
|
|
385
457
|
|
|
386
|
-
//
|
|
387
|
-
String
|
|
458
|
+
// Check if this is a virtual UID that needs conversion
|
|
459
|
+
String realClientId = deviceId;
|
|
460
|
+
if (isVirtualId(deviceId)) {
|
|
461
|
+
Log.d(TAG, "Device ID " + deviceId + " looks like a virtual UID, converting...");
|
|
462
|
+
String[] conversionResult = convertVirtualUid(deviceId);
|
|
463
|
+
if (conversionResult != null && conversionResult[0] != null) {
|
|
464
|
+
realClientId = conversionResult[0];
|
|
465
|
+
Log.d(TAG, "Using converted client ID: " + realClientId);
|
|
466
|
+
} else {
|
|
467
|
+
Log.w(TAG, "Virtual UID conversion failed, trying with original ID");
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// Call JNIApi.create(did, serverParam) with real client ID
|
|
472
|
+
String serviceParam = getServiceParam(realClientId); // Use real client ID prefix
|
|
388
473
|
Method createMethod = jniApiClass.getMethod("create", String.class, String.class);
|
|
389
|
-
Object result = createMethod.invoke(null,
|
|
474
|
+
Object result = createMethod.invoke(null, realClientId, serviceParam);
|
|
390
475
|
long sdkClientPtr = (Long) result;
|
|
391
476
|
|
|
392
477
|
Log.d(TAG, "JNIApi.create result: " + sdkClientPtr);
|
|
@@ -402,10 +487,11 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
|
|
|
402
487
|
|
|
403
488
|
ClientInfo clientInfo = new ClientInfo();
|
|
404
489
|
clientInfo.deviceId = deviceId;
|
|
490
|
+
clientInfo.realClientId = realClientId; // Store the converted ID
|
|
405
491
|
clientInfo.sdkClientPtr = sdkClientPtr;
|
|
406
492
|
clients.put(ourClientPtr, clientInfo);
|
|
407
493
|
|
|
408
|
-
Log.d(TAG, "Created client: ourPtr=" + ourClientPtr + ", sdkPtr=" + sdkClientPtr);
|
|
494
|
+
Log.d(TAG, "Created client: ourPtr=" + ourClientPtr + ", sdkPtr=" + sdkClientPtr + ", realId=" + realClientId);
|
|
409
495
|
promise.resolve(ourClientPtr);
|
|
410
496
|
} catch (Exception e) {
|
|
411
497
|
Log.e(TAG, "clientCreate failed", e);
|
|
@@ -441,10 +527,11 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
|
|
|
441
527
|
params.putInt("state", 1); // CONNECTING
|
|
442
528
|
sendEvent("onConnectionStateChanged", params);
|
|
443
529
|
|
|
444
|
-
//
|
|
530
|
+
// Use realClientId for service param lookup (it has the correct prefix like VSTN)
|
|
531
|
+
String realId = clientInfo.realClientId != null ? clientInfo.realClientId : clientInfo.deviceId;
|
|
445
532
|
String param = (serverParam != null && !serverParam.isEmpty())
|
|
446
533
|
? serverParam
|
|
447
|
-
: getServiceParam(
|
|
534
|
+
: getServiceParam(realId);
|
|
448
535
|
|
|
449
536
|
// Default connectType to 126 (from V1 app) if not specified
|
|
450
537
|
// connectType 126 = P2P/Relay combination that works reliably
|
|
@@ -458,8 +545,8 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
|
|
|
458
545
|
Log.d(TAG, "Calling JNIApi.connect(" + clientInfo.sdkClientPtr + ", 15, " + param + ", " + actualConnectType + ")");
|
|
459
546
|
|
|
460
547
|
try {
|
|
461
|
-
|
|
462
|
-
Log.d(TAG, "JNIApi.connect
|
|
548
|
+
connectMethod.invoke(null, clientInfo.sdkClientPtr, 15, param, actualConnectType);
|
|
549
|
+
Log.d(TAG, "JNIApi.connect returned normally");
|
|
463
550
|
} catch (java.lang.reflect.InvocationTargetException ite) {
|
|
464
551
|
Log.e(TAG, "JNIApi.connect threw exception: " + ite.getCause(), ite.getCause());
|
|
465
552
|
throw ite;
|
|
@@ -530,21 +617,34 @@ public class VStarCamModule extends ReactContextBaseJavaModule {
|
|
|
530
617
|
Method loginMethod = jniApiClass.getMethod("login",
|
|
531
618
|
long.class, String.class, String.class);
|
|
532
619
|
|
|
533
|
-
Log.d(TAG, "Calling JNIApi.login(" + clientInfo.sdkClientPtr + ", " + username + ")");
|
|
620
|
+
Log.d(TAG, "Calling JNIApi.login(" + clientInfo.sdkClientPtr + ", " + username + ", ***)");
|
|
534
621
|
|
|
622
|
+
boolean loginSuccess = false;
|
|
535
623
|
try {
|
|
536
624
|
loginMethod.invoke(null, clientInfo.sdkClientPtr, username, password);
|
|
537
|
-
|
|
538
|
-
|
|
625
|
+
Log.d(TAG, "JNIApi.login returned normally");
|
|
626
|
+
loginSuccess = true;
|
|
627
|
+
} catch (java.lang.reflect.InvocationTargetException ite) {
|
|
628
|
+
Throwable cause = ite.getCause();
|
|
629
|
+
Log.e(TAG, "JNIApi.login threw exception: " + cause, cause);
|
|
630
|
+
// Don't rethrow - return false instead to prevent crash
|
|
631
|
+
promise.resolve(false);
|
|
632
|
+
return;
|
|
633
|
+
} catch (Throwable t) {
|
|
634
|
+
Log.e(TAG, "JNIApi.login crashed: " + t.getMessage(), t);
|
|
635
|
+
// Don't rethrow - return false instead to prevent crash
|
|
539
636
|
promise.resolve(false);
|
|
540
637
|
return;
|
|
541
638
|
}
|
|
542
639
|
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
640
|
+
if (loginSuccess) {
|
|
641
|
+
clientInfo.isLoggedIn = true;
|
|
642
|
+
clientInfo.username = username;
|
|
643
|
+
clientInfo.password = password;
|
|
644
|
+
}
|
|
546
645
|
|
|
547
|
-
|
|
646
|
+
Log.d(TAG, "JNIApi.login completed with result: " + loginSuccess);
|
|
647
|
+
promise.resolve(loginSuccess);
|
|
548
648
|
} catch (Exception e) {
|
|
549
649
|
Log.e(TAG, "clientLogin failed", e);
|
|
550
650
|
promise.reject("LOGIN_ERROR", e.getMessage());
|
|
@@ -90,7 +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", //
|
|
93
|
+
"com.veepai.AppPlayer", // Added as alternative
|
|
94
94
|
"com.veepai.app_player.AppPlayerPlugin", // Flutter plugin wrapper
|
|
95
95
|
"com.vstarcam.player.AppPlayer",
|
|
96
96
|
"com.vstarcam.AppPlayer",
|