@shenai/capacitor-sdk 3.1.1
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/CapacitorShenaiSdk.podspec +18 -0
- package/LICENSE.md +5 -0
- package/README.md +0 -0
- package/android/build.gradle +59 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/ai/mxlabs/shenai_sdk/plugins/capacitor/ShenaiSdkCapacitorPlugin.java +1476 -0
- package/android/src/main/res/.gitkeep +0 -0
- package/dist/docs.json +3226 -0
- package/dist/esm/definitions.d.ts +612 -0
- package/dist/esm/definitions.js +208 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.js +29 -0
- package/dist/plugin.cjs.js +241 -0
- package/dist/plugin.js +244 -0
- package/ios/Sources/ShenaiSdkCapacitorPlugin/ShenaiSdkCapacitorPlugin.swift +1101 -0
- package/package.json +47 -0
package/android/src/main/java/ai/mxlabs/shenai_sdk/plugins/capacitor/ShenaiSdkCapacitorPlugin.java
ADDED
|
@@ -0,0 +1,1476 @@
|
|
|
1
|
+
package ai.mxlabs.shenai_sdk.plugins.capacitor;
|
|
2
|
+
|
|
3
|
+
import com.getcapacitor.JSObject;
|
|
4
|
+
import com.getcapacitor.Plugin;
|
|
5
|
+
import com.getcapacitor.PluginCall;
|
|
6
|
+
import com.getcapacitor.PluginMethod;
|
|
7
|
+
import com.getcapacitor.annotation.CapacitorPlugin;
|
|
8
|
+
|
|
9
|
+
import android.util.Base64;
|
|
10
|
+
import android.util.Log;
|
|
11
|
+
import android.Manifest;
|
|
12
|
+
import android.os.Handler;
|
|
13
|
+
import android.os.Looper;
|
|
14
|
+
import android.view.MotionEvent;
|
|
15
|
+
import android.view.View;
|
|
16
|
+
import android.view.ViewGroup;
|
|
17
|
+
import android.view.WindowManager;
|
|
18
|
+
import android.graphics.Color;
|
|
19
|
+
import android.util.DisplayMetrics;
|
|
20
|
+
import android.util.TypedValue;
|
|
21
|
+
import android.widget.FrameLayout;
|
|
22
|
+
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
|
23
|
+
import java.util.Optional;
|
|
24
|
+
import java.util.List;
|
|
25
|
+
import java.util.ArrayList;
|
|
26
|
+
import org.json.JSONArray;
|
|
27
|
+
import org.json.JSONException;
|
|
28
|
+
|
|
29
|
+
import ai.mxlabs.shenai_sdk.ShenAIAndroidSDK;
|
|
30
|
+
import ai.mxlabs.shenai_sdk.ShenAIView;
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@CapacitorPlugin(name = "ShenaiSdkCapacitor")
|
|
34
|
+
public class ShenaiSdkCapacitorPlugin extends Plugin {
|
|
35
|
+
// ────────────────────────────────────────────────────────────── state
|
|
36
|
+
private static final String TAG = "shen-capacitor";
|
|
37
|
+
private static final int CONTAINER_VIEW_ID = 15835421;
|
|
38
|
+
private ShenAIAndroidSDK sdk;
|
|
39
|
+
private ShenAIView shenaiView;
|
|
40
|
+
private FrameLayout containerView;
|
|
41
|
+
private boolean isTouchForwardingActive;
|
|
42
|
+
|
|
43
|
+
// ────────────────────────────────────────────────────────────── JS API
|
|
44
|
+
|
|
45
|
+
// demo echo method
|
|
46
|
+
@PluginMethod
|
|
47
|
+
public void echo(PluginCall call) {
|
|
48
|
+
String value = call.getString("value", "");
|
|
49
|
+
Log.i(TAG, value);
|
|
50
|
+
JSObject ret = new JSObject();
|
|
51
|
+
ret.put("value", value);
|
|
52
|
+
call.resolve(ret);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* initialize(options: { apiKey: string, userId?: string, settings?: InitializationSettings }):
|
|
57
|
+
* Promise<InitializationResult>
|
|
58
|
+
*/
|
|
59
|
+
@PluginMethod
|
|
60
|
+
public void initialize(PluginCall call) {
|
|
61
|
+
String apiKey = call.getString("apiKey");
|
|
62
|
+
if (apiKey == null || apiKey.isEmpty()) {
|
|
63
|
+
call.reject("apiKey is required");
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
String userId = call.getString("userId", "");
|
|
68
|
+
|
|
69
|
+
// 1 · init SDK
|
|
70
|
+
sdk = new ShenAIAndroidSDK();
|
|
71
|
+
ShenAIAndroidSDK.InitializationSettings settings = sdk.getDefaultInitializationSettings();
|
|
72
|
+
|
|
73
|
+
JSObject settingsObj = call.getObject("settings", new JSObject());
|
|
74
|
+
if (settingsObj != null) {
|
|
75
|
+
try {
|
|
76
|
+
applyInitializationSettings(settingsObj, settings);
|
|
77
|
+
} catch (JSONException e) {
|
|
78
|
+
call.reject("Failed to parse initialization settings: " + e.getMessage());
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
settings.eventCallback = new ShenAIAndroidSDK.EventCallback() {
|
|
84
|
+
@Override
|
|
85
|
+
public void onEvent(ShenAIAndroidSDK.Event event) {
|
|
86
|
+
String name;
|
|
87
|
+
switch (event) {
|
|
88
|
+
case START_BUTTON_CLICKED:
|
|
89
|
+
name = "START_BUTTON_CLICKED";
|
|
90
|
+
break;
|
|
91
|
+
case STOP_BUTTON_CLICKED:
|
|
92
|
+
name = "STOP_BUTTON_CLICKED";
|
|
93
|
+
break;
|
|
94
|
+
case MEASUREMENT_FINISHED:
|
|
95
|
+
name = "MEASUREMENT_FINISHED";
|
|
96
|
+
break;
|
|
97
|
+
case USER_FLOW_FINISHED:
|
|
98
|
+
name = "USER_FLOW_FINISHED";
|
|
99
|
+
break;
|
|
100
|
+
case SCREEN_CHANGED:
|
|
101
|
+
name = "SCREEN_CHANGED";
|
|
102
|
+
break;
|
|
103
|
+
default:
|
|
104
|
+
name = "UNKNOWN";
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
JSObject data = new JSObject();
|
|
108
|
+
data.put("EventName", name);
|
|
109
|
+
notifyListeners("ShenAIEvent", data);
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
getActivity().runOnUiThread(() -> {
|
|
114
|
+
try {
|
|
115
|
+
ViewGroup root = (ViewGroup) getBridge().getWebView().getParent();
|
|
116
|
+
if (containerView != null && containerView.getParent() instanceof ViewGroup) {
|
|
117
|
+
((ViewGroup) containerView.getParent()).removeView(containerView);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
containerView = new FrameLayout(getContext());
|
|
121
|
+
containerView.setId(CONTAINER_VIEW_ID);
|
|
122
|
+
|
|
123
|
+
shenaiView = new ShenAIView(getContext());
|
|
124
|
+
containerView.addView(
|
|
125
|
+
shenaiView,
|
|
126
|
+
new FrameLayout.LayoutParams(
|
|
127
|
+
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
128
|
+
ViewGroup.LayoutParams.MATCH_PARENT));
|
|
129
|
+
|
|
130
|
+
root.addView(
|
|
131
|
+
containerView,
|
|
132
|
+
new ViewGroup.LayoutParams(
|
|
133
|
+
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
134
|
+
ViewGroup.LayoutParams.MATCH_PARENT));
|
|
135
|
+
|
|
136
|
+
getBridge().getWebView().setBackgroundColor(Color.TRANSPARENT);
|
|
137
|
+
getBridge().getWebView().setAlpha(1.0f);
|
|
138
|
+
root.bringChildToFront(getBridge().getWebView());
|
|
139
|
+
setupTouchForwarding();
|
|
140
|
+
shenaiView.onResume();
|
|
141
|
+
getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
|
142
|
+
|
|
143
|
+
resolveInitialization(call, apiKey, userId, settings);
|
|
144
|
+
} catch (Throwable t) {
|
|
145
|
+
call.reject(
|
|
146
|
+
"Failed to initialize ShenAI SDK: " + t.getMessage(),
|
|
147
|
+
t instanceof Exception ? (Exception) t : new RuntimeException(t)
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
private void setupTouchForwarding() {
|
|
154
|
+
final View webView = getBridge().getWebView();
|
|
155
|
+
webView.setClickable(true);
|
|
156
|
+
webView.setOnTouchListener((v, event) -> {
|
|
157
|
+
if (containerView == null) {
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
int[] webLoc = new int[2];
|
|
162
|
+
int[] containerLoc = new int[2];
|
|
163
|
+
webView.getLocationOnScreen(webLoc);
|
|
164
|
+
containerView.getLocationOnScreen(containerLoc);
|
|
165
|
+
|
|
166
|
+
MotionEvent forwarded = MotionEvent.obtain(event);
|
|
167
|
+
forwarded.offsetLocation(webLoc[0] - containerLoc[0], webLoc[1] - containerLoc[1]);
|
|
168
|
+
|
|
169
|
+
int action = forwarded.getActionMasked();
|
|
170
|
+
if (action == MotionEvent.ACTION_DOWN) {
|
|
171
|
+
isTouchForwardingActive = isPointInsideView(forwarded.getX(), forwarded.getY(), containerView);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (isTouchForwardingActive) {
|
|
175
|
+
containerView.dispatchTouchEvent(forwarded);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
|
|
179
|
+
isTouchForwardingActive = false;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
forwarded.recycle();
|
|
183
|
+
return false;
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
private boolean isPointInsideView(float x, float y, View view) {
|
|
188
|
+
return x >= 0 && y >= 0 && x < view.getWidth() && y < view.getHeight();
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
private void resolveInitialization(
|
|
192
|
+
PluginCall call,
|
|
193
|
+
String apiKey,
|
|
194
|
+
String userId,
|
|
195
|
+
ShenAIAndroidSDK.InitializationSettings settings
|
|
196
|
+
) {
|
|
197
|
+
ShenAIAndroidSDK.InitializationResult result =
|
|
198
|
+
sdk.initialize(getActivity(), apiKey, userId, settings);
|
|
199
|
+
JSObject ret = new JSObject();
|
|
200
|
+
ret.put("value", result.ordinal());
|
|
201
|
+
call.resolve(ret);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/** isInitialized(): Promise<boolean> */
|
|
205
|
+
@PluginMethod
|
|
206
|
+
public void isInitialized(PluginCall call) {
|
|
207
|
+
JSObject ret = new JSObject();
|
|
208
|
+
ret.put("value", sdk != null && sdk.isInitialized());
|
|
209
|
+
call.resolve(ret);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/** deinitialize(): Promise<void> */
|
|
213
|
+
@PluginMethod
|
|
214
|
+
public void deinitialize(PluginCall call) {
|
|
215
|
+
final ShenAIView capturedView = shenaiView;
|
|
216
|
+
final FrameLayout capturedContainer = containerView;
|
|
217
|
+
shenaiView = null;
|
|
218
|
+
containerView = null;
|
|
219
|
+
isTouchForwardingActive = false;
|
|
220
|
+
|
|
221
|
+
getActivity().runOnUiThread(() -> {
|
|
222
|
+
try {
|
|
223
|
+
getBridge().getWebView().setOnTouchListener(null);
|
|
224
|
+
getBridge().getWebView().setAlpha(1.0f);
|
|
225
|
+
|
|
226
|
+
if (capturedView != null) {
|
|
227
|
+
try { capturedView.activityPaused(); } catch (Throwable ignored) {}
|
|
228
|
+
}
|
|
229
|
+
if (capturedContainer != null) {
|
|
230
|
+
ViewGroup root = (ViewGroup) getBridge().getWebView().getParent();
|
|
231
|
+
root.removeView(capturedContainer);
|
|
232
|
+
|
|
233
|
+
getBridge().getWebView().setBackgroundColor(Color.WHITE);
|
|
234
|
+
}
|
|
235
|
+
if (shenaiView == null) {
|
|
236
|
+
try { getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } catch (Throwable ignored) {}
|
|
237
|
+
}
|
|
238
|
+
} catch (Throwable ignored) {}
|
|
239
|
+
});
|
|
240
|
+
try { if (sdk != null) sdk.deinitialize(); } catch (Throwable ignored) {}
|
|
241
|
+
|
|
242
|
+
sdk = null;
|
|
243
|
+
|
|
244
|
+
call.resolve();
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* setViewRect(options: { x?: number, y?: number, width?: number, height?: number }): Promise<void>
|
|
249
|
+
*/
|
|
250
|
+
@PluginMethod
|
|
251
|
+
public void setViewRect(PluginCall call) {
|
|
252
|
+
final double x = call.getDouble("x", 0.0);
|
|
253
|
+
final double y = call.getDouble("y", 0.0);
|
|
254
|
+
final double width = call.getDouble("width", 0.0);
|
|
255
|
+
final double height = call.getDouble("height", 0.0);
|
|
256
|
+
|
|
257
|
+
getActivity().runOnUiThread(() -> {
|
|
258
|
+
if (containerView == null) {
|
|
259
|
+
call.reject("View not initialized");
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
DisplayMetrics metrics = getActivity().getResources().getDisplayMetrics();
|
|
264
|
+
|
|
265
|
+
int computedX = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, (float) x, metrics);
|
|
266
|
+
int computedY = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, (float) y, metrics);
|
|
267
|
+
int computedWidth = width == 0.0 ? ViewGroup.LayoutParams.MATCH_PARENT :
|
|
268
|
+
(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, (float) width, metrics);
|
|
269
|
+
int computedHeight = height == 0.0 ? ViewGroup.LayoutParams.MATCH_PARENT :
|
|
270
|
+
(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, (float) height, metrics);
|
|
271
|
+
|
|
272
|
+
ViewGroup parent = (ViewGroup) containerView.getParent();
|
|
273
|
+
ViewGroup.LayoutParams layoutParams;
|
|
274
|
+
|
|
275
|
+
if (parent instanceof CoordinatorLayout) {
|
|
276
|
+
layoutParams = new CoordinatorLayout.LayoutParams(computedWidth, computedHeight);
|
|
277
|
+
((CoordinatorLayout.LayoutParams) layoutParams).setMargins(computedX, computedY, 0, 0);
|
|
278
|
+
} else {
|
|
279
|
+
layoutParams = new FrameLayout.LayoutParams(computedWidth, computedHeight);
|
|
280
|
+
((FrameLayout.LayoutParams) layoutParams).setMargins(computedX, computedY, 0, 0);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
containerView.setLayoutParams(layoutParams);
|
|
284
|
+
|
|
285
|
+
call.resolve();
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* setOverlaysWebview(options: { overlay: boolean }): Promise<void>
|
|
291
|
+
*/
|
|
292
|
+
@PluginMethod
|
|
293
|
+
public void setOverlaysWebview(PluginCall call) {
|
|
294
|
+
final Boolean overlay = call.getBoolean("overlay", null);
|
|
295
|
+
if (overlay == null) {
|
|
296
|
+
call.reject("overlays is required");
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
getActivity().runOnUiThread(() -> {
|
|
301
|
+
if (containerView == null) {
|
|
302
|
+
call.reject("View not initialized");
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
ViewGroup root = (ViewGroup) getBridge().getWebView().getParent();
|
|
307
|
+
if (overlay) {
|
|
308
|
+
root.bringChildToFront(containerView);
|
|
309
|
+
} else {
|
|
310
|
+
root.bringChildToFront(getBridge().getWebView());
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
call.resolve();
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/** setOperatingMode(options: { mode: number }): Promise<void> */
|
|
318
|
+
@PluginMethod
|
|
319
|
+
public void setOperatingMode(PluginCall call) {
|
|
320
|
+
int mode = call.getInt("operatingMode", 0);
|
|
321
|
+
if (sdk != null) {
|
|
322
|
+
sdk.setOperatingMode(ShenAIAndroidSDK.OperatingMode.values()[mode]);
|
|
323
|
+
}
|
|
324
|
+
call.resolve();
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
@PluginMethod
|
|
328
|
+
public void startMeasurement(PluginCall call) {
|
|
329
|
+
if (sdk != null) {
|
|
330
|
+
sdk.startMeasurement();
|
|
331
|
+
}
|
|
332
|
+
call.resolve();
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
@PluginMethod
|
|
336
|
+
public void stopMeasurement(PluginCall call) {
|
|
337
|
+
if (sdk != null) {
|
|
338
|
+
sdk.stopMeasurement();
|
|
339
|
+
}
|
|
340
|
+
call.resolve();
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
@PluginMethod
|
|
344
|
+
public void resetMeasurementSession(PluginCall call) {
|
|
345
|
+
if (sdk != null) {
|
|
346
|
+
sdk.resetMeasurementSession();
|
|
347
|
+
}
|
|
348
|
+
call.resolve();
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/** getOperatingMode(): Promise<number> */
|
|
352
|
+
@PluginMethod
|
|
353
|
+
public void getOperatingMode(PluginCall call) {
|
|
354
|
+
JSObject ret = new JSObject();
|
|
355
|
+
if (sdk != null) {
|
|
356
|
+
ret.put("value", sdk.getOperatingMode().ordinal());
|
|
357
|
+
} else {
|
|
358
|
+
ret.put("value", 0);
|
|
359
|
+
}
|
|
360
|
+
call.resolve(ret);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/** getCalibrationState(): Promise<number> */
|
|
364
|
+
@PluginMethod
|
|
365
|
+
public void getCalibrationState(PluginCall call) {
|
|
366
|
+
JSObject ret = new JSObject();
|
|
367
|
+
if (sdk != null) {
|
|
368
|
+
ret.put("value", sdk.getCalibrationState().ordinal());
|
|
369
|
+
} else {
|
|
370
|
+
ret.put("value", 0);
|
|
371
|
+
}
|
|
372
|
+
call.resolve(ret);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/** setPrecisionMode(options: { mode: number }): Promise<void> */
|
|
376
|
+
@PluginMethod
|
|
377
|
+
public void setPrecisionMode(PluginCall call) {
|
|
378
|
+
int mode = call.getInt("precisionMode", 0);
|
|
379
|
+
if (sdk != null) {
|
|
380
|
+
sdk.setPrecisionMode(ShenAIAndroidSDK.PrecisionMode.values()[mode]);
|
|
381
|
+
}
|
|
382
|
+
call.resolve();
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/** getPrecisionMode(): Promise<number> */
|
|
386
|
+
@PluginMethod
|
|
387
|
+
public void getPrecisionMode(PluginCall call) {
|
|
388
|
+
JSObject ret = new JSObject();
|
|
389
|
+
if (sdk != null) {
|
|
390
|
+
ret.put("value", sdk.getPrecisionMode().ordinal());
|
|
391
|
+
} else {
|
|
392
|
+
ret.put("value", 0);
|
|
393
|
+
}
|
|
394
|
+
call.resolve(ret);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/** setMeasurementPreset(options: { preset:number }):Promise<void> */
|
|
398
|
+
@PluginMethod
|
|
399
|
+
public void setMeasurementPreset(PluginCall call) {
|
|
400
|
+
int preset = call.getInt("measurementPreset", 0);
|
|
401
|
+
if (sdk != null) {
|
|
402
|
+
sdk.setMeasurementPreset(ShenAIAndroidSDK.MeasurementPreset.values()[preset]);
|
|
403
|
+
}
|
|
404
|
+
call.resolve();
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/** getMeasurementPreset(): Promise<number> */
|
|
408
|
+
@PluginMethod
|
|
409
|
+
public void getMeasurementPreset(PluginCall call) {
|
|
410
|
+
JSObject ret = new JSObject();
|
|
411
|
+
if (sdk != null) {
|
|
412
|
+
ret.put("value", sdk.getMeasurementPreset().ordinal());
|
|
413
|
+
} else {
|
|
414
|
+
ret.put("value", 0);
|
|
415
|
+
}
|
|
416
|
+
call.resolve(ret);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/** setCameraMode(options: { mode:number }):Promise<void> */
|
|
420
|
+
@PluginMethod
|
|
421
|
+
public void setCameraMode(PluginCall call) {
|
|
422
|
+
int mode = call.getInt("cameraMode", 0);
|
|
423
|
+
if (sdk != null) {
|
|
424
|
+
sdk.setCameraMode(ShenAIAndroidSDK.CameraMode.values()[mode]);
|
|
425
|
+
}
|
|
426
|
+
call.resolve();
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/** getCameraMode(): Promise<number> */
|
|
430
|
+
@PluginMethod
|
|
431
|
+
public void getCameraMode(PluginCall call) {
|
|
432
|
+
JSObject ret = new JSObject();
|
|
433
|
+
if (sdk != null) {
|
|
434
|
+
ret.put("value", sdk.getCameraMode().ordinal());
|
|
435
|
+
} else {
|
|
436
|
+
ret.put("value", 0);
|
|
437
|
+
}
|
|
438
|
+
call.resolve(ret);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/** getLastCameraError(): Promise<number | null> */
|
|
442
|
+
@PluginMethod
|
|
443
|
+
public void getLastCameraError(PluginCall call) {
|
|
444
|
+
JSObject ret = new JSObject();
|
|
445
|
+
if (sdk != null) {
|
|
446
|
+
final ShenAIAndroidSDK.CameraError cameraError = sdk.getLastCameraError();
|
|
447
|
+
if (cameraError != null) {
|
|
448
|
+
ret.put("value", cameraError.ordinal());
|
|
449
|
+
} else {
|
|
450
|
+
ret.put("value", JSObject.NULL);
|
|
451
|
+
}
|
|
452
|
+
} else {
|
|
453
|
+
ret.put("value", JSObject.NULL);
|
|
454
|
+
}
|
|
455
|
+
call.resolve(ret);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
/** setScreen(options: { screen:number }):Promise<void> */
|
|
459
|
+
@PluginMethod
|
|
460
|
+
public void setScreen(PluginCall call) {
|
|
461
|
+
int screen = call.getInt("screen", 0);
|
|
462
|
+
if (sdk != null) {
|
|
463
|
+
sdk.setScreen(ShenAIAndroidSDK.Screen.values()[screen]);
|
|
464
|
+
}
|
|
465
|
+
call.resolve();
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/** getScreen(): Promise<number> */
|
|
469
|
+
@PluginMethod
|
|
470
|
+
public void getScreen(PluginCall call) {
|
|
471
|
+
JSObject ret = new JSObject();
|
|
472
|
+
if (sdk != null) {
|
|
473
|
+
ret.put("value", sdk.getScreen().ordinal());
|
|
474
|
+
} else {
|
|
475
|
+
ret.put("value", 0);
|
|
476
|
+
}
|
|
477
|
+
call.resolve(ret);
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
/** setShowUserInterface(options: { value:boolean }) */
|
|
481
|
+
@PluginMethod
|
|
482
|
+
public void setShowUserInterface(PluginCall call) {
|
|
483
|
+
boolean value = call.getBoolean("value", true);
|
|
484
|
+
if (sdk != null) sdk.setShowUserInterface(value);
|
|
485
|
+
call.resolve();
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
/** getShowUserInterface():Promise<boolean> */
|
|
489
|
+
@PluginMethod
|
|
490
|
+
public void getShowUserInterface(PluginCall call) {
|
|
491
|
+
JSObject ret = new JSObject();
|
|
492
|
+
ret.put("value", sdk != null && sdk.getShowUserInterface());
|
|
493
|
+
call.resolve(ret);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/** setShowFacePositioningOverlay(options: { value:boolean }) */
|
|
497
|
+
@PluginMethod
|
|
498
|
+
public void setShowFacePositioningOverlay(PluginCall call) {
|
|
499
|
+
boolean value = call.getBoolean("value", true);
|
|
500
|
+
if (sdk != null) sdk.setShowFacePositioningOverlay(value);
|
|
501
|
+
call.resolve();
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
/** getShowFacePositioningOverlay():Promise<boolean> */
|
|
505
|
+
@PluginMethod
|
|
506
|
+
public void getShowFacePositioningOverlay(PluginCall call) {
|
|
507
|
+
JSObject ret = new JSObject();
|
|
508
|
+
ret.put("value", sdk != null && sdk.getShowFacePositioningOverlay());
|
|
509
|
+
call.resolve(ret);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
/** setShowVisualWarnings(options: { value:boolean }) */
|
|
513
|
+
@PluginMethod
|
|
514
|
+
public void setShowVisualWarnings(PluginCall call) {
|
|
515
|
+
boolean value = call.getBoolean("value", true);
|
|
516
|
+
if (sdk != null) sdk.setShowVisualWarnings(value);
|
|
517
|
+
call.resolve();
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
/** getShowVisualWarnings():Promise<boolean> */
|
|
521
|
+
@PluginMethod
|
|
522
|
+
public void getShowVisualWarnings(PluginCall call) {
|
|
523
|
+
JSObject ret = new JSObject();
|
|
524
|
+
ret.put("value", sdk != null && sdk.getShowVisualWarnings());
|
|
525
|
+
call.resolve(ret);
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
/** setEnableCameraSwap(options: { value:boolean} ) */
|
|
529
|
+
@PluginMethod
|
|
530
|
+
public void setEnableCameraSwap(PluginCall call) {
|
|
531
|
+
boolean value = call.getBoolean("value", true);
|
|
532
|
+
if (sdk != null) sdk.setEnableCameraSwap(value);
|
|
533
|
+
call.resolve();
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
/** getEnableCameraSwap():Promise<boolean> */
|
|
537
|
+
@PluginMethod
|
|
538
|
+
public void getEnableCameraSwap(PluginCall call) {
|
|
539
|
+
JSObject ret = new JSObject();
|
|
540
|
+
ret.put("value", sdk != null && sdk.getEnableCameraSwap());
|
|
541
|
+
call.resolve(ret);
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
/** setShowFaceMask(options: { value:boolean }) */
|
|
545
|
+
@PluginMethod
|
|
546
|
+
public void setShowFaceMask(PluginCall call) {
|
|
547
|
+
boolean value = call.getBoolean("value", true);
|
|
548
|
+
if (sdk != null) sdk.setShowFaceMask(value);
|
|
549
|
+
call.resolve();
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
/** getShowFaceMask():Promise<boolean> */
|
|
553
|
+
@PluginMethod
|
|
554
|
+
public void getShowFaceMask(PluginCall call) {
|
|
555
|
+
JSObject ret = new JSObject();
|
|
556
|
+
ret.put("value", sdk != null && sdk.getShowFaceMask());
|
|
557
|
+
call.resolve(ret);
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
/** setShowBloodFlow(options: { value:boolean }) */
|
|
561
|
+
@PluginMethod
|
|
562
|
+
public void setShowBloodFlow(PluginCall call) {
|
|
563
|
+
boolean value = call.getBoolean("value", true);
|
|
564
|
+
if (sdk != null) sdk.setShowBloodFlow(value);
|
|
565
|
+
call.resolve();
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
/** getShowBloodFlow():Promise<boolean> */
|
|
569
|
+
@PluginMethod
|
|
570
|
+
public void getShowBloodFlow(PluginCall call) {
|
|
571
|
+
JSObject ret = new JSObject();
|
|
572
|
+
ret.put("value", sdk != null && sdk.getShowBloodFlow());
|
|
573
|
+
call.resolve(ret);
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
/** setIncludeTimestampInPdf(options: { value:boolean }) */
|
|
577
|
+
@PluginMethod
|
|
578
|
+
public void setIncludeTimestampInPdf(PluginCall call) {
|
|
579
|
+
boolean value = call.getBoolean("value", true);
|
|
580
|
+
if (sdk != null) sdk.setIncludeTimestampInPdf(value);
|
|
581
|
+
call.resolve();
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
/** getIncludeTimestampInPdf():Promise<boolean> */
|
|
585
|
+
@PluginMethod
|
|
586
|
+
public void getIncludeTimestampInPdf(PluginCall call) {
|
|
587
|
+
JSObject ret = new JSObject();
|
|
588
|
+
ret.put("value", sdk != null && sdk.getIncludeTimestampInPdf());
|
|
589
|
+
call.resolve(ret);
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
/** setPdfEmailSubject(options: { subject:string }) */
|
|
593
|
+
@PluginMethod
|
|
594
|
+
public void setPdfEmailSubject(PluginCall call) {
|
|
595
|
+
String subject = call.getString("subject", "");
|
|
596
|
+
if (sdk != null) sdk.setPdfEmailSubject(subject);
|
|
597
|
+
call.resolve();
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
/** setPdfEmailBody(options: { body:string }) */
|
|
601
|
+
@PluginMethod
|
|
602
|
+
public void setPdfEmailBody(PluginCall call) {
|
|
603
|
+
String body = call.getString("body", "");
|
|
604
|
+
if (sdk != null) sdk.setPdfEmailBody(body);
|
|
605
|
+
call.resolve();
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
/** setShowStartStopButton(options: { value:boolean }) */
|
|
609
|
+
@PluginMethod
|
|
610
|
+
public void setShowStartStopButton(PluginCall call) {
|
|
611
|
+
boolean value = call.getBoolean("value", true);
|
|
612
|
+
if (sdk != null) sdk.setShowStartStopButton(value);
|
|
613
|
+
call.resolve();
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
/** getShowStartStopButton():Promise<boolean> */
|
|
617
|
+
@PluginMethod
|
|
618
|
+
public void getShowStartStopButton(PluginCall call) {
|
|
619
|
+
JSObject ret = new JSObject();
|
|
620
|
+
ret.put("value", sdk != null && sdk.getShowStartStopButton());
|
|
621
|
+
call.resolve(ret);
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
/** setEnableMeasurementsDashboard(options: { value:boolean }) */
|
|
625
|
+
@PluginMethod
|
|
626
|
+
public void setEnableMeasurementsDashboard(PluginCall call) {
|
|
627
|
+
boolean value = call.getBoolean("value", true);
|
|
628
|
+
if (sdk != null) sdk.setEnableMeasurementsDashboard(value);
|
|
629
|
+
call.resolve();
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
/** getEnableMeasurementsDashboard():Promise<boolean> */
|
|
633
|
+
@PluginMethod
|
|
634
|
+
public void getEnableMeasurementsDashboard(PluginCall call) {
|
|
635
|
+
JSObject ret = new JSObject();
|
|
636
|
+
ret.put("value", sdk != null && sdk.getEnableMeasurementsDashboard());
|
|
637
|
+
call.resolve(ret);
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
/** setShowInfoButton(options: { value:boolean }) */
|
|
641
|
+
@PluginMethod
|
|
642
|
+
public void setShowInfoButton(PluginCall call) {
|
|
643
|
+
boolean value = call.getBoolean("value", true);
|
|
644
|
+
if (sdk != null) sdk.setShowInfoButton(value);
|
|
645
|
+
call.resolve();
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
/** getShowInfoButton():Promise<boolean> */
|
|
649
|
+
@PluginMethod
|
|
650
|
+
public void getShowInfoButton(PluginCall call) {
|
|
651
|
+
JSObject ret = new JSObject();
|
|
652
|
+
ret.put("value", sdk != null && sdk.getShowInfoButton());
|
|
653
|
+
call.resolve(ret);
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
/** getShowDisclaimer():Promise<boolean> */
|
|
657
|
+
@PluginMethod
|
|
658
|
+
public void getShowDisclaimer(PluginCall call) {
|
|
659
|
+
JSObject ret = new JSObject();
|
|
660
|
+
ret.put("value", sdk != null && sdk.getShowDisclaimer());
|
|
661
|
+
call.resolve(ret);
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
/** setEnableStartAfterSuccess(options: { value:boolean }) */
|
|
665
|
+
@PluginMethod
|
|
666
|
+
public void setEnableStartAfterSuccess(PluginCall call) {
|
|
667
|
+
boolean value = call.getBoolean("value", true);
|
|
668
|
+
if (sdk != null) sdk.setEnableStartAfterSuccess(value);
|
|
669
|
+
call.resolve();
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
/** getEnableStartAfterSuccess():Promise<boolean> */
|
|
673
|
+
@PluginMethod
|
|
674
|
+
public void getEnableStartAfterSuccess(PluginCall call) {
|
|
675
|
+
JSObject ret = new JSObject();
|
|
676
|
+
ret.put("value", sdk != null && sdk.getEnableStartAfterSuccess());
|
|
677
|
+
call.resolve(ret);
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
/** getFaceState():Promise<number> */
|
|
681
|
+
@PluginMethod
|
|
682
|
+
public void getFaceState(PluginCall call) {
|
|
683
|
+
JSObject ret = new JSObject();
|
|
684
|
+
if (sdk != null) {
|
|
685
|
+
ret.put("value", sdk.getFaceState().ordinal());
|
|
686
|
+
} else {
|
|
687
|
+
ret.put("value", 0);
|
|
688
|
+
}
|
|
689
|
+
call.resolve(ret);
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
/** getNormalizedFaceBbox():Promise<object|null> */
|
|
693
|
+
@PluginMethod
|
|
694
|
+
public void getNormalizedFaceBbox(PluginCall call) {
|
|
695
|
+
JSObject ret = new JSObject();
|
|
696
|
+
if (sdk != null) {
|
|
697
|
+
ShenAIAndroidSDK.NormalizedFaceBbox b = sdk.getNormalizedFaceBbox();
|
|
698
|
+
if (b != null) {
|
|
699
|
+
JSObject box = new JSObject();
|
|
700
|
+
box.put("x", b.x);
|
|
701
|
+
box.put("y", b.y);
|
|
702
|
+
box.put("width", b.width);
|
|
703
|
+
box.put("height", b.height);
|
|
704
|
+
ret.put("value", box);
|
|
705
|
+
call.resolve(ret);
|
|
706
|
+
return;
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
call.resolve();
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
/** getMeasurementState():Promise<number> */
|
|
713
|
+
@PluginMethod
|
|
714
|
+
public void getMeasurementState(PluginCall call) {
|
|
715
|
+
JSObject ret = new JSObject();
|
|
716
|
+
if (sdk != null) ret.put("value", sdk.getMeasurementState().ordinal());
|
|
717
|
+
else ret.put("value", 0);
|
|
718
|
+
call.resolve(ret);
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
@PluginMethod
|
|
722
|
+
public void getCurrentViolatedMeasurementEnvironmentCondition(PluginCall call) {
|
|
723
|
+
JSObject ret = new JSObject();
|
|
724
|
+
if (sdk != null) {
|
|
725
|
+
ShenAIAndroidSDK.MeasurementEnvironmentCondition value =
|
|
726
|
+
sdk.getCurrentViolatedMeasurementEnvironmentCondition();
|
|
727
|
+
ret.put("value", value == null ? JSObject.NULL : value.ordinal());
|
|
728
|
+
} else {
|
|
729
|
+
ret.put("value", JSObject.NULL);
|
|
730
|
+
}
|
|
731
|
+
call.resolve(ret);
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
/** isReadyToStartMeasurement():Promise<boolean> */
|
|
735
|
+
@PluginMethod
|
|
736
|
+
public void isReadyToStartMeasurement(PluginCall call) {
|
|
737
|
+
JSObject ret = new JSObject();
|
|
738
|
+
ret.put("value", sdk != null && sdk.isReadyToStartMeasurement());
|
|
739
|
+
call.resolve(ret);
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
/** areRequiredModelsDownloaded():Promise<boolean> */
|
|
743
|
+
@PluginMethod
|
|
744
|
+
public void areRequiredModelsDownloaded(PluginCall call) {
|
|
745
|
+
JSObject ret = new JSObject();
|
|
746
|
+
ret.put("value", sdk != null && sdk.areRequiredModelsDownloaded());
|
|
747
|
+
call.resolve(ret);
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
/** getMeasurementProgressPercentage():Promise<number> */
|
|
751
|
+
@PluginMethod
|
|
752
|
+
public void getMeasurementProgressPercentage(PluginCall call) {
|
|
753
|
+
JSObject ret = new JSObject();
|
|
754
|
+
if (sdk != null) ret.put("value", sdk.getMeasurementProgressPercentage());
|
|
755
|
+
else ret.put("value", 0);
|
|
756
|
+
call.resolve(ret);
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
/** getHeartRate10s():Promise<number|null> */
|
|
760
|
+
@PluginMethod
|
|
761
|
+
public void getHeartRate10s(PluginCall call) {
|
|
762
|
+
JSObject ret = new JSObject();
|
|
763
|
+
if (sdk == null) {
|
|
764
|
+
ret.put("value", JSObject.NULL);
|
|
765
|
+
} else {
|
|
766
|
+
int v = sdk.getHeartRate10s();
|
|
767
|
+
if (v < 0) ret.put("value", JSObject.NULL); else ret.put("value", v);
|
|
768
|
+
}
|
|
769
|
+
call.resolve(ret);
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
/** getHeartRate4s():Promise<number|null> */
|
|
773
|
+
@PluginMethod
|
|
774
|
+
public void getHeartRate4s(PluginCall call) {
|
|
775
|
+
JSObject ret = new JSObject();
|
|
776
|
+
if (sdk == null) {
|
|
777
|
+
ret.put("value", JSObject.NULL);
|
|
778
|
+
} else {
|
|
779
|
+
int v = sdk.getHeartRate4s();
|
|
780
|
+
if (v < 0) ret.put("value", JSObject.NULL); else ret.put("value", v);
|
|
781
|
+
}
|
|
782
|
+
call.resolve(ret);
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
/** getMeasurementResults():Promise<object|null> */
|
|
786
|
+
@PluginMethod
|
|
787
|
+
public void getMeasurementResults(PluginCall call) {
|
|
788
|
+
if (sdk == null) {
|
|
789
|
+
JSObject wrapper = new JSObject();
|
|
790
|
+
wrapper.put("value", JSObject.NULL);
|
|
791
|
+
call.resolve(wrapper);
|
|
792
|
+
return;
|
|
793
|
+
}
|
|
794
|
+
ShenAIAndroidSDK.MeasurementResults r = sdk.getMeasurementResults();
|
|
795
|
+
if (r == null) {
|
|
796
|
+
JSObject wrapper = new JSObject();
|
|
797
|
+
wrapper.put("value", JSObject.NULL);
|
|
798
|
+
call.resolve(wrapper);
|
|
799
|
+
return;
|
|
800
|
+
}
|
|
801
|
+
JSObject ret = measurementResultsToJSObject(r);
|
|
802
|
+
JSObject wrapper = new JSObject();
|
|
803
|
+
wrapper.put("value", ret);
|
|
804
|
+
call.resolve(wrapper);
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
/** getMeasurementResultsHistory():Promise<object|null> */
|
|
808
|
+
@PluginMethod
|
|
809
|
+
public void getMeasurementResultsHistory(PluginCall call) {
|
|
810
|
+
if (sdk == null) { call.resolve(); return; }
|
|
811
|
+
ShenAIAndroidSDK.MeasurementResultsHistory hist = sdk.getMeasurementResultsHistory();
|
|
812
|
+
if (hist == null) { call.resolve(); return; }
|
|
813
|
+
JSONArray arr = new JSONArray();
|
|
814
|
+
if (hist.history != null) {
|
|
815
|
+
for (ShenAIAndroidSDK.MeasurementResultsWithMetadata md : hist.history) {
|
|
816
|
+
JSObject obj = measurementResultsWithMetadataToJSObject(md);
|
|
817
|
+
arr.put(obj);
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
JSObject ret = new JSObject();
|
|
821
|
+
ret.put("value", arr);
|
|
822
|
+
call.resolve(ret);
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
/** getRealtimeMetrics(periodSec:number):Promise<object|null> */
|
|
826
|
+
@PluginMethod
|
|
827
|
+
public void getRealtimeMetrics(PluginCall call) {
|
|
828
|
+
if (sdk == null) { call.resolve(); return; }
|
|
829
|
+
Double periodOpt = call.getDouble("periodSec", 1.0);
|
|
830
|
+
float period = periodOpt != null ? periodOpt.floatValue() : 1.0f;
|
|
831
|
+
ShenAIAndroidSDK.MeasurementResults r = sdk.getRealtimeMetrics(period);
|
|
832
|
+
if (r == null) { call.resolve(); return; }
|
|
833
|
+
JSObject ret = new JSObject();
|
|
834
|
+
ret.put("value", measurementResultsToJSObject(r));
|
|
835
|
+
call.resolve(ret);
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
/** getRealtimeHeartbeats(periodSec?:number):Promise<object[]> */
|
|
839
|
+
@PluginMethod
|
|
840
|
+
public void getRealtimeHeartbeats(PluginCall call) {
|
|
841
|
+
if (sdk == null) { call.resolve(); return; }
|
|
842
|
+
Double p = call.getDouble("periodSec");
|
|
843
|
+
ShenAIAndroidSDK.Heartbeat[] hb = sdk.getRealtimeHeartbeats(p == null ? null : p.floatValue());
|
|
844
|
+
JSONArray arr = heartbeatsToJSONArray(hb);
|
|
845
|
+
JSObject ret = new JSObject();
|
|
846
|
+
ret.put("value", arr);
|
|
847
|
+
call.resolve(ret);
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
/** getFullPpgSignal(): Promise<{ value: number[] }> */
|
|
851
|
+
@PluginMethod
|
|
852
|
+
public void getFullPpgSignal(PluginCall call) {
|
|
853
|
+
JSObject ret = new JSObject();
|
|
854
|
+
if (sdk != null) {
|
|
855
|
+
double[] signal = sdk.getFullPpgSignal();
|
|
856
|
+
JSONArray arr = new JSONArray();
|
|
857
|
+
for (double v : signal) {
|
|
858
|
+
arr.put(Double.valueOf(v));
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
ret.put("value", arr);
|
|
862
|
+
}
|
|
863
|
+
call.resolve(ret);
|
|
864
|
+
}
|
|
865
|
+
/** setRecordingEnabled(options: { enabled:boolean }): Promise<void> */
|
|
866
|
+
@PluginMethod
|
|
867
|
+
public void setRecordingEnabled(PluginCall call) {
|
|
868
|
+
boolean enabled = call.getBoolean("value", false);
|
|
869
|
+
if (sdk != null) sdk.setRecordingEnabled(enabled);
|
|
870
|
+
call.resolve();
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
/** getRecordingEnabled(): Promise<{ value: boolean }> */
|
|
874
|
+
@PluginMethod
|
|
875
|
+
public void getRecordingEnabled(PluginCall call) {
|
|
876
|
+
JSObject ret = new JSObject();
|
|
877
|
+
ret.put("value", sdk != null && sdk.getRecordingEnabled());
|
|
878
|
+
call.resolve(ret);
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
/** getTotalBadSignalSeconds(): Promise<{ value: number }> */
|
|
882
|
+
@PluginMethod
|
|
883
|
+
public void getTotalBadSignalSeconds(PluginCall call) {
|
|
884
|
+
JSObject ret = new JSObject();
|
|
885
|
+
if (sdk != null) ret.put("value", sdk.getTotalBadSignalSeconds());
|
|
886
|
+
else ret.put("value", 0);
|
|
887
|
+
call.resolve(ret);
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
/** getCurrentSignalQualityMetric(): Promise<{ value: number }> */
|
|
891
|
+
@PluginMethod
|
|
892
|
+
public void getCurrentSignalQualityMetric(PluginCall call) {
|
|
893
|
+
JSObject ret = new JSObject();
|
|
894
|
+
if (sdk != null) ret.put("value", sdk.getCurrentSignalQualityMetric());
|
|
895
|
+
else ret.put("value", 0);
|
|
896
|
+
call.resolve(ret);
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
/** setCustomMeasurementConfig(options: { config:object }): Promise<void> */
|
|
900
|
+
@PluginMethod
|
|
901
|
+
public void setCustomMeasurementConfig(PluginCall call) {
|
|
902
|
+
JSObject cfg = call.getObject("config", new JSObject());
|
|
903
|
+
if (sdk != null && cfg != null) {
|
|
904
|
+
ShenAIAndroidSDK.CustomMeasurementConfig c = sdk.new CustomMeasurementConfig();
|
|
905
|
+
if (cfg.has("durationSeconds"))
|
|
906
|
+
c.durationSeconds = Optional.of((float) cfg.optDouble("durationSeconds"));
|
|
907
|
+
if (cfg.has("infiniteMeasurement"))
|
|
908
|
+
c.infiniteMeasurement = Optional.of(cfg.optBoolean("infiniteMeasurement"));
|
|
909
|
+
if (cfg.has("instantMetrics")) {
|
|
910
|
+
JSONArray arr = cfg.optJSONArray("instantMetrics");
|
|
911
|
+
if (arr != null) {
|
|
912
|
+
List<ShenAIAndroidSDK.Metric> list = new ArrayList<>();
|
|
913
|
+
for (int i = 0; i < arr.length(); ++i) list.add(ShenAIAndroidSDK.Metric.values()[arr.optInt(i)]);
|
|
914
|
+
c.instantMetrics = Optional.of(list);
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
if (cfg.has("summaryMetrics")) {
|
|
918
|
+
JSONArray arr = cfg.optJSONArray("summaryMetrics");
|
|
919
|
+
if (arr != null) {
|
|
920
|
+
List<ShenAIAndroidSDK.Metric> list = new ArrayList<>();
|
|
921
|
+
for (int i = 0; i < arr.length(); ++i) list.add(ShenAIAndroidSDK.Metric.values()[arr.optInt(i)]);
|
|
922
|
+
c.summaryMetrics = Optional.of(list);
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
if (cfg.has("healthIndices")) {
|
|
926
|
+
JSONArray arr = cfg.optJSONArray("healthIndices");
|
|
927
|
+
if (arr != null) {
|
|
928
|
+
List<ShenAIAndroidSDK.HealthIndex> list = new ArrayList<>();
|
|
929
|
+
for (int i = 0; i < arr.length(); ++i) list.add(ShenAIAndroidSDK.HealthIndex.values()[arr.optInt(i)]);
|
|
930
|
+
c.healthIndices = Optional.of(list);
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
if (cfg.has("realtimeHrPeriodSeconds"))
|
|
934
|
+
c.realtimeHrPeriodSeconds = Optional.of((float) cfg.optDouble("realtimeHrPeriodSeconds"));
|
|
935
|
+
if (cfg.has("realtimeHrvPeriodSeconds"))
|
|
936
|
+
c.realtimeHrvPeriodSeconds = Optional.of((float) cfg.optDouble("realtimeHrvPeriodSeconds"));
|
|
937
|
+
if (cfg.has("realtimeCardiacStressPeriodSeconds"))
|
|
938
|
+
c.realtimeCardiacStressPeriodSeconds = Optional.of((float) cfg.optDouble("realtimeCardiacStressPeriodSeconds"));
|
|
939
|
+
sdk.setCustomMeasurementConfig(c);
|
|
940
|
+
}
|
|
941
|
+
call.resolve();
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
/** setCustomColorTheme(options: { theme:object }): Promise<void> */
|
|
945
|
+
@PluginMethod
|
|
946
|
+
public void setCustomColorTheme(PluginCall call) {
|
|
947
|
+
JSObject obj = call.getObject("theme", new JSObject());
|
|
948
|
+
if (sdk != null && obj != null) {
|
|
949
|
+
ShenAIAndroidSDK.CustomColorTheme t = sdk.new CustomColorTheme();
|
|
950
|
+
if (obj.has("themeColor")) t.themeColor = obj.getString("themeColor");
|
|
951
|
+
if (obj.has("textColor")) t.textColor = obj.getString("textColor");
|
|
952
|
+
if (obj.has("backgroundColor")) t.backgroundColor = obj.getString("backgroundColor");
|
|
953
|
+
if (obj.has("tileColor")) t.tileColor = obj.getString("tileColor");
|
|
954
|
+
if (obj.has("buttonMainColor")) t.buttonMainColor = obj.getString("buttonMainColor");
|
|
955
|
+
if (obj.has("buttonSecondaryColor")) t.buttonSecondaryColor = obj.getString("buttonSecondaryColor");
|
|
956
|
+
sdk.setCustomColorTheme(t);
|
|
957
|
+
}
|
|
958
|
+
call.resolve();
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
/** setLanguage(options: { lang:string }) */
|
|
962
|
+
@PluginMethod
|
|
963
|
+
public void setLanguage(PluginCall call) {
|
|
964
|
+
String lang = call.getString("language");
|
|
965
|
+
if (sdk != null && lang != null) {
|
|
966
|
+
sdk.setLanguage(lang);
|
|
967
|
+
}
|
|
968
|
+
call.resolve();
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
/** getHealthRisks():Promise<object> */
|
|
972
|
+
@PluginMethod
|
|
973
|
+
public void getHealthRisks(PluginCall call) {
|
|
974
|
+
if (sdk == null) { call.reject("not initialized"); return; }
|
|
975
|
+
ShenAIAndroidSDK.HealthRisks risks = sdk.getHealthRisks();
|
|
976
|
+
JSObject ret = new JSObject();
|
|
977
|
+
ret.put("value", healthRisksToJSObject(risks));
|
|
978
|
+
call.resolve(ret);
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
/** getHealthRisksFactors():Promise<object> */
|
|
982
|
+
@PluginMethod
|
|
983
|
+
public void getHealthRisksFactors(PluginCall call) {
|
|
984
|
+
if (sdk == null) { call.reject("not initialized"); return; }
|
|
985
|
+
ShenAIAndroidSDK.RisksFactors factors = sdk.getHealthRisksFactors();
|
|
986
|
+
JSObject ret = new JSObject();
|
|
987
|
+
ret.put("value", risksFactorsToJSObject(factors));
|
|
988
|
+
call.resolve(ret);
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
/** getMaximalRisks(options: { risksFactors: object }):Promise<object> */
|
|
992
|
+
@PluginMethod
|
|
993
|
+
public void getMaximalRisks(PluginCall call) {
|
|
994
|
+
if (sdk == null) { call.reject("not initialized"); return; }
|
|
995
|
+
JSObject obj = call.getObject("risksFactors", new JSObject());
|
|
996
|
+
try {
|
|
997
|
+
ShenAIAndroidSDK.RisksFactors factors = jsObjectToRisksFactors(obj);
|
|
998
|
+
ShenAIAndroidSDK.HealthRisks risks = sdk.getMaximalHealthRisks(factors);
|
|
999
|
+
JSObject ret = new JSObject();
|
|
1000
|
+
ret.put("value", healthRisksToJSObject(risks));
|
|
1001
|
+
call.resolve(ret);
|
|
1002
|
+
} catch (JSONException e) {
|
|
1003
|
+
call.reject("Failed to parse risks factors: " + e.getMessage());
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
/** getMinimalRisks(options: { risksFactors: object }):Promise<object> */
|
|
1008
|
+
@PluginMethod
|
|
1009
|
+
public void getMinimalRisks(PluginCall call) {
|
|
1010
|
+
if (sdk == null) { call.reject("not initialized"); return; }
|
|
1011
|
+
JSObject obj = call.getObject("risksFactors", new JSObject());
|
|
1012
|
+
try {
|
|
1013
|
+
ShenAIAndroidSDK.RisksFactors factors = jsObjectToRisksFactors(obj);
|
|
1014
|
+
ShenAIAndroidSDK.HealthRisks risks = sdk.getMinimalHealthRisks(factors);
|
|
1015
|
+
JSObject ret = new JSObject();
|
|
1016
|
+
ret.put("value", healthRisksToJSObject(risks));
|
|
1017
|
+
call.resolve(ret);
|
|
1018
|
+
} catch (JSONException e) {
|
|
1019
|
+
call.reject("Failed to parse risks factors: " + e.getMessage());
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
/** getReferenceRisks(options: { risksFactors: object }):Promise<object> */
|
|
1024
|
+
@PluginMethod
|
|
1025
|
+
public void getReferenceRisks(PluginCall call) {
|
|
1026
|
+
if (sdk == null) { call.reject("not initialized"); return; }
|
|
1027
|
+
JSObject obj = call.getObject("risksFactors", new JSObject());
|
|
1028
|
+
try {
|
|
1029
|
+
ShenAIAndroidSDK.RisksFactors factors = jsObjectToRisksFactors(obj);
|
|
1030
|
+
ShenAIAndroidSDK.HealthRisks risks = sdk.getReferenceHealthRisks(factors);
|
|
1031
|
+
JSObject ret = new JSObject();
|
|
1032
|
+
ret.put("value", healthRisksToJSObject(risks));
|
|
1033
|
+
call.resolve(ret);
|
|
1034
|
+
} catch (JSONException e) {
|
|
1035
|
+
call.reject("Failed to parse risks factors: " + e.getMessage());
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
/** computeHealthRisks(options: { risksFactors: object }):Promise<object> */
|
|
1040
|
+
@PluginMethod
|
|
1041
|
+
public void computeHealthRisks(PluginCall call) {
|
|
1042
|
+
if (sdk == null) { call.reject("not initialized"); return; }
|
|
1043
|
+
JSObject obj = call.getObject("risksFactors", new JSObject());
|
|
1044
|
+
try {
|
|
1045
|
+
ShenAIAndroidSDK.RisksFactors factors = jsObjectToRisksFactors(obj);
|
|
1046
|
+
ShenAIAndroidSDK.HealthRisks risks = sdk.computeHealthRisks(factors);
|
|
1047
|
+
JSObject ret = new JSObject();
|
|
1048
|
+
ret.put("value", healthRisksToJSObject(risks));
|
|
1049
|
+
call.resolve(ret);
|
|
1050
|
+
} catch (JSONException e) {
|
|
1051
|
+
call.reject("Failed to parse risks factors: " + e.getMessage());
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
/** getSignalQualityMapPng(): Promise<{ value: number[] }> */
|
|
1056
|
+
@PluginMethod
|
|
1057
|
+
public void getSignalQualityMapPng(PluginCall call) {
|
|
1058
|
+
JSObject ret = new JSObject();
|
|
1059
|
+
if (sdk != null) {
|
|
1060
|
+
byte[] data = sdk.getSignalQualityMapPng();
|
|
1061
|
+
JSONArray arr = new JSONArray();
|
|
1062
|
+
for (byte b : data) arr.put(b & 0xFF);
|
|
1063
|
+
ret.put("value", arr);
|
|
1064
|
+
}
|
|
1065
|
+
call.resolve(ret);
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
/** getFaceTexturePng(): Promise<{ value: number[] }> */
|
|
1069
|
+
@PluginMethod
|
|
1070
|
+
public void getFaceTexturePng(PluginCall call) {
|
|
1071
|
+
JSObject ret = new JSObject();
|
|
1072
|
+
if (sdk != null) {
|
|
1073
|
+
byte[] data = sdk.getFaceTexturePng();
|
|
1074
|
+
JSONArray arr = new JSONArray();
|
|
1075
|
+
for (byte b : data) arr.put(b & 0xFF);
|
|
1076
|
+
ret.put("value", arr);
|
|
1077
|
+
}
|
|
1078
|
+
call.resolve(ret);
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
/** openMeasurementResultsPdfInBrowser(): Promise<void> */
|
|
1082
|
+
@PluginMethod
|
|
1083
|
+
public void openMeasurementResultsPdfInBrowser(PluginCall call) {
|
|
1084
|
+
if (sdk != null) sdk.openMeasurementResultsPdfInBrowser();
|
|
1085
|
+
call.resolve();
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
/** sendMeasurementResultsPdfToEmail(options: { email:string }): Promise<void> */
|
|
1089
|
+
@PluginMethod
|
|
1090
|
+
public void sendMeasurementResultsPdfToEmail(PluginCall call) {
|
|
1091
|
+
String email = call.getString("email");
|
|
1092
|
+
if (sdk != null && email != null) sdk.sendMeasurementResultsPdfToEmail(email);
|
|
1093
|
+
call.resolve();
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
/** requestMeasurementResultsPdfUrl(): Promise<void> */
|
|
1097
|
+
@PluginMethod
|
|
1098
|
+
public void requestMeasurementResultsPdfUrl(PluginCall call) {
|
|
1099
|
+
if (sdk != null) sdk.requestMeasurementResultsPdfUrl();
|
|
1100
|
+
call.resolve();
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
/** getMeasurementResultsPdfUrl(): Promise<{ value: string | null }> */
|
|
1104
|
+
@PluginMethod
|
|
1105
|
+
public void getMeasurementResultsPdfUrl(PluginCall call) {
|
|
1106
|
+
JSObject ret = new JSObject();
|
|
1107
|
+
if (sdk != null) {
|
|
1108
|
+
String url = sdk.getMeasurementResultsPdfUrl();
|
|
1109
|
+
if (url == null || url.isEmpty()) ret.put("value", JSObject.NULL); else ret.put("value", url);
|
|
1110
|
+
} else {
|
|
1111
|
+
ret.put("value", JSObject.NULL);
|
|
1112
|
+
}
|
|
1113
|
+
call.resolve(ret);
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
/** requestMeasurementResultsPdfBytes(): Promise<void> */
|
|
1117
|
+
@PluginMethod
|
|
1118
|
+
public void requestMeasurementResultsPdfBytes(PluginCall call) {
|
|
1119
|
+
if (sdk != null) sdk.requestMeasurementResultsPdfBytes();
|
|
1120
|
+
call.resolve();
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
/** getMeasurementResultsPdfBytes(): Promise<{ value: number[] | null }> */
|
|
1124
|
+
@PluginMethod
|
|
1125
|
+
public void getMeasurementResultsPdfBytes(PluginCall call) {
|
|
1126
|
+
JSObject ret = new JSObject();
|
|
1127
|
+
if (sdk != null) {
|
|
1128
|
+
byte[] bytes = sdk.getMeasurementResultsPdfBytes();
|
|
1129
|
+
if (bytes == null) {
|
|
1130
|
+
ret.put("value", JSObject.NULL);
|
|
1131
|
+
} else {
|
|
1132
|
+
ret.put("valueBase64", Base64.encodeToString(bytes, Base64.NO_WRAP));
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
call.resolve(ret);
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
/** getResultAsFhirObservation(): Promise<{ value: string | null }> */
|
|
1139
|
+
@PluginMethod
|
|
1140
|
+
public void getResultAsFhirObservation(PluginCall call) {
|
|
1141
|
+
JSObject ret = new JSObject();
|
|
1142
|
+
if (sdk != null) {
|
|
1143
|
+
String observation = sdk.getResultAsFhirObservation();
|
|
1144
|
+
ret.put("value", (observation == null || observation.isEmpty()) ? JSObject.NULL : observation);
|
|
1145
|
+
} else {
|
|
1146
|
+
ret.put("value", JSObject.NULL);
|
|
1147
|
+
}
|
|
1148
|
+
call.resolve(ret);
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
/** sendResultFhirObservation({ url }): Promise<{ value: string | null }> */
|
|
1152
|
+
@PluginMethod
|
|
1153
|
+
public void sendResultFhirObservation(PluginCall call) {
|
|
1154
|
+
String url = call.getString("url");
|
|
1155
|
+
if (sdk == null) {
|
|
1156
|
+
call.reject("SDK is not initialized");
|
|
1157
|
+
return;
|
|
1158
|
+
}
|
|
1159
|
+
if (url == null || url.isEmpty()) {
|
|
1160
|
+
call.reject("url is required");
|
|
1161
|
+
return;
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
Handler mainHandler = new Handler(Looper.getMainLooper());
|
|
1165
|
+
sdk.sendResultFhirObservation(url, response -> {
|
|
1166
|
+
JSObject ret = new JSObject();
|
|
1167
|
+
String normalized = (response == null || response.isEmpty()) ? null : response;
|
|
1168
|
+
ret.put("value", normalized == null ? JSObject.NULL : normalized);
|
|
1169
|
+
mainHandler.post(() -> call.resolve(ret));
|
|
1170
|
+
});
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
// ──────────────────────────────────────────────────────────── helpers
|
|
1174
|
+
private void applyInitializationSettings(JSObject obj,
|
|
1175
|
+
ShenAIAndroidSDK.InitializationSettings settings) throws JSONException {
|
|
1176
|
+
if (obj == null) return;
|
|
1177
|
+
|
|
1178
|
+
if (obj.has("precisionMode"))
|
|
1179
|
+
settings.precisionMode = ShenAIAndroidSDK.PrecisionMode.values()[obj.getInt("precisionMode")];
|
|
1180
|
+
if (obj.has("operatingMode"))
|
|
1181
|
+
settings.operatingMode = ShenAIAndroidSDK.OperatingMode.values()[obj.getInt("operatingMode")];
|
|
1182
|
+
if (obj.has("measurementPreset"))
|
|
1183
|
+
settings.measurementPreset = ShenAIAndroidSDK.MeasurementPreset.values()[obj.getInt("measurementPreset")];
|
|
1184
|
+
if (obj.has("cameraMode"))
|
|
1185
|
+
settings.cameraMode = ShenAIAndroidSDK.CameraMode.values()[obj.getInt("cameraMode")];
|
|
1186
|
+
if (obj.has("onboardingMode"))
|
|
1187
|
+
settings.onboardingMode = ShenAIAndroidSDK.OnboardingMode.values()[obj.getInt("onboardingMode")];
|
|
1188
|
+
if (obj.has("initializationMode"))
|
|
1189
|
+
settings.initializationMode = ShenAIAndroidSDK.InitializationMode.values()[obj.getInt("initializationMode")];
|
|
1190
|
+
|
|
1191
|
+
if (obj.has("showUserInterface"))
|
|
1192
|
+
settings.showUserInterface = obj.getBoolean("showUserInterface");
|
|
1193
|
+
if (obj.has("showFacePositioningOverlay"))
|
|
1194
|
+
settings.showFacePositioningOverlay = obj.getBoolean("showFacePositioningOverlay");
|
|
1195
|
+
if (obj.has("showVisualWarnings"))
|
|
1196
|
+
settings.showVisualWarnings = obj.getBoolean("showVisualWarnings");
|
|
1197
|
+
if (obj.has("enableCameraSwap"))
|
|
1198
|
+
settings.enableCameraSwap = obj.getBoolean("enableCameraSwap");
|
|
1199
|
+
if (obj.has("showFaceMask"))
|
|
1200
|
+
settings.showFaceMask = obj.getBoolean("showFaceMask");
|
|
1201
|
+
if (obj.has("showBloodFlow"))
|
|
1202
|
+
settings.showBloodFlow = obj.getBoolean("showBloodFlow");
|
|
1203
|
+
if (obj.has("hideShenaiLogo"))
|
|
1204
|
+
settings.hideShenaiLogo = obj.getBoolean("hideShenaiLogo");
|
|
1205
|
+
if (obj.has("includeTimestampInPdf"))
|
|
1206
|
+
settings.includeTimestampInPdf = obj.getBoolean("includeTimestampInPdf");
|
|
1207
|
+
if (obj.has("pdfEmailSubject"))
|
|
1208
|
+
settings.pdfEmailSubject = obj.getString("pdfEmailSubject");
|
|
1209
|
+
if (obj.has("pdfEmailBody"))
|
|
1210
|
+
settings.pdfEmailBody = obj.getString("pdfEmailBody");
|
|
1211
|
+
if (obj.has("enableStartAfterSuccess"))
|
|
1212
|
+
settings.enableStartAfterSuccess = obj.getBoolean("enableStartAfterSuccess");
|
|
1213
|
+
if (obj.has("enableSummaryScreen"))
|
|
1214
|
+
settings.enableSummaryScreen = obj.getBoolean("enableSummaryScreen");
|
|
1215
|
+
if (obj.has("showResultsFinishButton"))
|
|
1216
|
+
settings.showResultsFinishButton = obj.getBoolean("showResultsFinishButton");
|
|
1217
|
+
if (obj.has("enableHealthRisks"))
|
|
1218
|
+
settings.enableHealthRisks = obj.getBoolean("enableHealthRisks");
|
|
1219
|
+
if (obj.has("showHealthIndicesFinishButton"))
|
|
1220
|
+
settings.showHealthIndicesFinishButton = obj.getBoolean("showHealthIndicesFinishButton");
|
|
1221
|
+
if (obj.has("saveHealthRisksFactors"))
|
|
1222
|
+
settings.saveHealthRisksFactors = obj.getBoolean("saveHealthRisksFactors");
|
|
1223
|
+
if (obj.has("showOutOfRangeResultIndicators"))
|
|
1224
|
+
settings.showOutOfRangeResultIndicators = obj.getBoolean("showOutOfRangeResultIndicators");
|
|
1225
|
+
if (obj.has("showTrialMetricLabels"))
|
|
1226
|
+
settings.showTrialMetricLabels = obj.getBoolean("showTrialMetricLabels");
|
|
1227
|
+
if (obj.has("showSignalQualityIndicator"))
|
|
1228
|
+
settings.showSignalQualityIndicator = obj.getBoolean("showSignalQualityIndicator");
|
|
1229
|
+
if (obj.has("showSignalTile"))
|
|
1230
|
+
settings.showSignalTile = obj.getBoolean("showSignalTile");
|
|
1231
|
+
if (obj.has("showStartStopButton"))
|
|
1232
|
+
settings.showStartStopButton = obj.getBoolean("showStartStopButton");
|
|
1233
|
+
if (obj.has("showInfoButton"))
|
|
1234
|
+
settings.showInfoButton = obj.getBoolean("showInfoButton");
|
|
1235
|
+
if (obj.has("showDisclaimer"))
|
|
1236
|
+
settings.showDisclaimer = obj.getBoolean("showDisclaimer");
|
|
1237
|
+
if (obj.has("enableMeasurementsDashboard"))
|
|
1238
|
+
settings.enableMeasurementsDashboard = obj.getBoolean("enableMeasurementsDashboard");
|
|
1239
|
+
if (obj.has("uiVersion"))
|
|
1240
|
+
settings.uiVersion = ShenAIAndroidSDK.UiVersion.values()[obj.getInt("uiVersion")];
|
|
1241
|
+
if (obj.has("frameWidth"))
|
|
1242
|
+
settings.frameWidth = obj.getInt("frameWidth");
|
|
1243
|
+
if (obj.has("frameHeight"))
|
|
1244
|
+
settings.frameHeight = obj.getInt("frameHeight");
|
|
1245
|
+
if (obj.has("rotation"))
|
|
1246
|
+
settings.rotation = obj.getInt("rotation");
|
|
1247
|
+
if (obj.has("offlineProcessing"))
|
|
1248
|
+
settings.offlineProcessing = obj.getBoolean("offlineProcessing");
|
|
1249
|
+
if (obj.has("uiFlowScreens")) {
|
|
1250
|
+
JSONArray array = obj.getJSONArray("uiFlowScreens");
|
|
1251
|
+
settings.uiFlowScreens.clear();
|
|
1252
|
+
for (int i = 0; i < array.length(); ++i) {
|
|
1253
|
+
settings.uiFlowScreens.add(ShenAIAndroidSDK.Screen.values()[array.getInt(i)]);
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
|
|
1257
|
+
if (obj.has("risksFactors")) {
|
|
1258
|
+
JSObject factorsObj = obj.getJSObject("risksFactors");
|
|
1259
|
+
settings.risksFactors = jsObjectToRisksFactors(factorsObj);
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1263
|
+
private ShenAIAndroidSDK.RisksFactors jsObjectToRisksFactors(JSObject obj) throws JSONException {
|
|
1264
|
+
ShenAIAndroidSDK.RisksFactors factors = sdk.new RisksFactors();
|
|
1265
|
+
if (obj == null) return factors;
|
|
1266
|
+
|
|
1267
|
+
if (obj.has("age")) factors.age = Optional.of(obj.getInt("age"));
|
|
1268
|
+
if (obj.has("cholesterol")) factors.cholesterol = Optional.of((float)obj.getDouble("cholesterol"));
|
|
1269
|
+
if (obj.has("cholesterolHdl")) factors.cholesterolHdl = Optional.of((float)obj.getDouble("cholesterolHdl"));
|
|
1270
|
+
if (obj.has("sbp")) factors.sbp = Optional.of((float)obj.getDouble("sbp"));
|
|
1271
|
+
if (obj.has("dbp")) factors.dbp = Optional.of((float)obj.getDouble("dbp"));
|
|
1272
|
+
if (obj.has("isSmoker")) factors.isSmoker = Optional.of(obj.getBoolean("isSmoker"));
|
|
1273
|
+
if (obj.has("hypertensionTreatment")) {
|
|
1274
|
+
int index = obj.getInt("hypertensionTreatment");
|
|
1275
|
+
factors.hypertensionTreatment = Optional.of(ShenAIAndroidSDK.HypertensionTreatment.values()[index]);
|
|
1276
|
+
}
|
|
1277
|
+
if (obj.has("hasDiabetes")) factors.hasDiabetes = Optional.of(obj.getBoolean("hasDiabetes"));
|
|
1278
|
+
if (obj.has("bodyHeight")) factors.bodyHeight = Optional.of((float)obj.getDouble("bodyHeight"));
|
|
1279
|
+
if (obj.has("bodyWeight")) factors.bodyWeight = Optional.of((float)obj.getDouble("bodyWeight"));
|
|
1280
|
+
if (obj.has("waistCircumference")) factors.waistCircumference = Optional.of((float)obj.getDouble("waistCircumference"));
|
|
1281
|
+
if (obj.has("neckCircumference")) factors.neckCircumference = Optional.of((float)obj.getDouble("neckCircumference"));
|
|
1282
|
+
if (obj.has("hipCircumference")) factors.hipCircumference = Optional.of((float)obj.getDouble("hipCircumference"));
|
|
1283
|
+
if (obj.has("gender")) {
|
|
1284
|
+
int index = obj.getInt("gender");
|
|
1285
|
+
factors.gender = Optional.of(ShenAIAndroidSDK.Gender.values()[index]);
|
|
1286
|
+
}
|
|
1287
|
+
if (obj.has("physicalActivity")) {
|
|
1288
|
+
int index = obj.getInt("physicalActivity");
|
|
1289
|
+
factors.physicalActivity = Optional.of(ShenAIAndroidSDK.PhysicalActivity.values()[index]);
|
|
1290
|
+
}
|
|
1291
|
+
if (obj.has("country")) factors.country = obj.getString("country");
|
|
1292
|
+
if (obj.has("race")) {
|
|
1293
|
+
int index = obj.getInt("race");
|
|
1294
|
+
factors.race = Optional.of(ShenAIAndroidSDK.Race.values()[index]);
|
|
1295
|
+
}
|
|
1296
|
+
if (obj.has("vegetableFruitDiet")) factors.vegetableFruitDiet = Optional.of(obj.getBoolean("vegetableFruitDiet"));
|
|
1297
|
+
if (obj.has("historyOfHypertension")) factors.historyOfHypertension = Optional.of(obj.getBoolean("historyOfHypertension"));
|
|
1298
|
+
if (obj.has("historyOfHighGlucose")) factors.historyOfHighGlucose = Optional.of(obj.getBoolean("historyOfHighGlucose"));
|
|
1299
|
+
if (obj.has("fastingGlucose")) factors.fastingGlucose = Optional.of((float)obj.getDouble("fastingGlucose"));
|
|
1300
|
+
if (obj.has("triglyceride")) factors.triglyceride = Optional.of((float)obj.getDouble("triglyceride"));
|
|
1301
|
+
if (obj.has("parentalHypertension")) {
|
|
1302
|
+
int index = obj.getInt("parentalHypertension");
|
|
1303
|
+
factors.parentalHypertension = Optional.of(ShenAIAndroidSDK.ParentalHistory.values()[index]);
|
|
1304
|
+
}
|
|
1305
|
+
if (obj.has("familyDiabetes")) {
|
|
1306
|
+
int index = obj.getInt("familyDiabetes");
|
|
1307
|
+
factors.familyDiabetes = Optional.of(ShenAIAndroidSDK.FamilyHistory.values()[index]);
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
return factors;
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
private JSObject risksFactorsToJSObject(ShenAIAndroidSDK.RisksFactors factors) {
|
|
1314
|
+
JSObject obj = new JSObject();
|
|
1315
|
+
factors.age.ifPresent(v -> obj.put("age", v));
|
|
1316
|
+
factors.cholesterol.ifPresent(v -> obj.put("cholesterol", v));
|
|
1317
|
+
factors.cholesterolHdl.ifPresent(v -> obj.put("cholesterolHdl", v));
|
|
1318
|
+
factors.sbp.ifPresent(v -> obj.put("sbp", v));
|
|
1319
|
+
factors.dbp.ifPresent(v -> obj.put("dbp", v));
|
|
1320
|
+
factors.isSmoker.ifPresent(v -> obj.put("isSmoker", v));
|
|
1321
|
+
factors.hypertensionTreatment.ifPresent(v -> obj.put("hypertensionTreatment", v.ordinal()));
|
|
1322
|
+
factors.hasDiabetes.ifPresent(v -> obj.put("hasDiabetes", v));
|
|
1323
|
+
factors.bodyHeight.ifPresent(v -> obj.put("bodyHeight", v));
|
|
1324
|
+
factors.bodyWeight.ifPresent(v -> obj.put("bodyWeight", v));
|
|
1325
|
+
factors.waistCircumference.ifPresent(v -> obj.put("waistCircumference", v));
|
|
1326
|
+
factors.neckCircumference.ifPresent(v -> obj.put("neckCircumference", v));
|
|
1327
|
+
factors.hipCircumference.ifPresent(v -> obj.put("hipCircumference", v));
|
|
1328
|
+
factors.gender.ifPresent(v -> obj.put("gender", v.ordinal()));
|
|
1329
|
+
factors.physicalActivity.ifPresent(v -> obj.put("physicalActivity", v.ordinal()));
|
|
1330
|
+
if (factors.country != null) obj.put("country", factors.country);
|
|
1331
|
+
factors.race.ifPresent(v -> obj.put("race", v.ordinal()));
|
|
1332
|
+
factors.vegetableFruitDiet.ifPresent(v -> obj.put("vegetableFruitDiet", v));
|
|
1333
|
+
factors.historyOfHypertension.ifPresent(v -> obj.put("historyOfHypertension", v));
|
|
1334
|
+
factors.historyOfHighGlucose.ifPresent(v -> obj.put("historyOfHighGlucose", v));
|
|
1335
|
+
factors.fastingGlucose.ifPresent(v -> obj.put("fastingGlucose", v));
|
|
1336
|
+
factors.triglyceride.ifPresent(v -> obj.put("triglyceride", v));
|
|
1337
|
+
factors.familyDiabetes.ifPresent(v -> obj.put("familyDiabetes", v.ordinal()));
|
|
1338
|
+
factors.parentalHypertension.ifPresent(v -> obj.put("parentalHypertension", v.ordinal()));
|
|
1339
|
+
return obj;
|
|
1340
|
+
}
|
|
1341
|
+
|
|
1342
|
+
private JSObject healthRisksToJSObject(ShenAIAndroidSDK.HealthRisks risks) {
|
|
1343
|
+
JSObject ret = new JSObject();
|
|
1344
|
+
JSObject hard = new JSObject();
|
|
1345
|
+
hard.put("coronaryDeathEventRisk", risks.hardAndFatalEvents.coronaryDeathEventRisk.orElse(null));
|
|
1346
|
+
hard.put("fatalStrokeEventRisk", risks.hardAndFatalEvents.fatalStrokeEventRisk.orElse(null));
|
|
1347
|
+
hard.put("totalCvMortalityRisk", risks.hardAndFatalEvents.totalCVMortalityRisk.orElse(null));
|
|
1348
|
+
hard.put("hardCvEventRisk", risks.hardAndFatalEvents.hardCVEventRisk.orElse(null));
|
|
1349
|
+
ret.put("hardAndFatalEvents", hard);
|
|
1350
|
+
|
|
1351
|
+
JSObject cv = new JSObject();
|
|
1352
|
+
cv.put("overallRisk", risks.cvDiseases.overallRisk.orElse(null));
|
|
1353
|
+
cv.put("coronaryHeartDiseaseRisk", risks.cvDiseases.coronaryHeartDiseaseRisk.orElse(null));
|
|
1354
|
+
cv.put("strokeRisk", risks.cvDiseases.strokeRisk.orElse(null));
|
|
1355
|
+
cv.put("heartFailureRisk", risks.cvDiseases.heartFailureRisk.orElse(null));
|
|
1356
|
+
cv.put("peripheralVascularDiseaseRisk", risks.cvDiseases.peripheralVascularDiseaseRisk.orElse(null));
|
|
1357
|
+
ret.put("cvDiseases", cv);
|
|
1358
|
+
|
|
1359
|
+
JSObject scores = new JSObject();
|
|
1360
|
+
scores.put("ageScore", risks.scores.ageScore.orElse(null));
|
|
1361
|
+
scores.put("sbpScore", risks.scores.sbpScore.orElse(null));
|
|
1362
|
+
scores.put("smokingScore", risks.scores.smokingScore.orElse(null));
|
|
1363
|
+
scores.put("diabetesScore", risks.scores.diabetesScore.orElse(null));
|
|
1364
|
+
scores.put("bmiScore", risks.scores.bmiScore.orElse(null));
|
|
1365
|
+
scores.put("cholesterolScore", risks.scores.cholesterolScore.orElse(null));
|
|
1366
|
+
scores.put("cholesterolHdlScore", risks.scores.cholesterolHdlScore.orElse(null));
|
|
1367
|
+
scores.put("totalScore", risks.scores.totalScore.orElse(null));
|
|
1368
|
+
ret.put("scores", scores);
|
|
1369
|
+
|
|
1370
|
+
ret.put("wellnessScore", risks.wellnessScore.orElse(null));
|
|
1371
|
+
ret.put("vascularAge", risks.vascularAge.orElse(null));
|
|
1372
|
+
ret.put("waistToHeightRatio", risks.waistToHeightRatio.orElse(null));
|
|
1373
|
+
ret.put("bodyFatPercentage", risks.bodyFatPercentage.orElse(null));
|
|
1374
|
+
ret.put("basalMetabolicRate", risks.basalMetabolicRate.orElse(null));
|
|
1375
|
+
ret.put("bodyRoundnessIndex", risks.bodyRoundnessIndex.orElse(null));
|
|
1376
|
+
ret.put("conicityIndex", risks.conicityIndex.orElse(null));
|
|
1377
|
+
ret.put("aBodyShapeIndex", risks.aBodyShapeIndex.orElse(null));
|
|
1378
|
+
ret.put("totalDailyEnergyExpenditure", risks.totalDailyEnergyExpenditure.orElse(null));
|
|
1379
|
+
ret.put("hypertensionRisk", risks.hypertensionRisk.orElse(null));
|
|
1380
|
+
ret.put("diabetesRisk", risks.diabetesRisk.orElse(null));
|
|
1381
|
+
ret.put("nonAlcoholicFattyLiverDiseaseRisk", risks.nonAlcoholicFattyLiverDiseaseRisk.map(Enum::ordinal).orElse(null));
|
|
1382
|
+
return ret;
|
|
1383
|
+
}
|
|
1384
|
+
|
|
1385
|
+
private JSONArray heartbeatsToJSONArray(ShenAIAndroidSDK.Heartbeat[] hbs) {
|
|
1386
|
+
JSONArray arr = new JSONArray();
|
|
1387
|
+
if (hbs != null) {
|
|
1388
|
+
for (ShenAIAndroidSDK.Heartbeat hb : hbs) {
|
|
1389
|
+
JSObject hbObj = new JSObject();
|
|
1390
|
+
hbObj.put("startLocationSec", hb.startLocationSec);
|
|
1391
|
+
hbObj.put("endLocationSec", hb.endLocationSec);
|
|
1392
|
+
hbObj.put("durationMs", hb.durationMs);
|
|
1393
|
+
arr.put(hbObj);
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1396
|
+
return arr;
|
|
1397
|
+
}
|
|
1398
|
+
|
|
1399
|
+
private JSObject measurementQualityMetricsToJSObject(ShenAIAndroidSDK.MeasurementQualityMetrics metrics) {
|
|
1400
|
+
if (metrics == null) return null;
|
|
1401
|
+
JSObject obj = new JSObject();
|
|
1402
|
+
obj.put("ppgQualityIndex", metrics.ppgQualityIndex.orElse(null));
|
|
1403
|
+
obj.put("bcgQualityIndex", metrics.bcgQualityIndex.orElse(null));
|
|
1404
|
+
obj.put("breathingQualityIndex", metrics.breathingQualityIndex.orElse(null));
|
|
1405
|
+
obj.put("bloodPressureQualityIndex", metrics.bloodPressureQualityIndex.orElse(null));
|
|
1406
|
+
obj.put("expectedSbpMedianAbsErrorMmhg", metrics.expectedSbpMedianAbsErrorMmhg.orElse(null));
|
|
1407
|
+
obj.put("expectedSbpP80AbsErrorMmhg", metrics.expectedSbpP80AbsErrorMmhg.orElse(null));
|
|
1408
|
+
obj.put("expectedSbpMeanAbsErrorMmhg", metrics.expectedSbpMeanAbsErrorMmhg.orElse(null));
|
|
1409
|
+
obj.put("expectedSbpBalancedMaeMmhg", metrics.expectedSbpBalancedMaeMmhg.orElse(null));
|
|
1410
|
+
obj.put("expectedDbpMedianAbsErrorMmhg", metrics.expectedDbpMedianAbsErrorMmhg.orElse(null));
|
|
1411
|
+
obj.put("expectedDbpP80AbsErrorMmhg", metrics.expectedDbpP80AbsErrorMmhg.orElse(null));
|
|
1412
|
+
obj.put("expectedDbpMeanAbsErrorMmhg", metrics.expectedDbpMeanAbsErrorMmhg.orElse(null));
|
|
1413
|
+
obj.put("expectedDbpBalancedMaeMmhg", metrics.expectedDbpBalancedMaeMmhg.orElse(null));
|
|
1414
|
+
return obj;
|
|
1415
|
+
}
|
|
1416
|
+
|
|
1417
|
+
private JSObject measurementResultsToJSObject(ShenAIAndroidSDK.MeasurementResults r) {
|
|
1418
|
+
JSObject obj = new JSObject();
|
|
1419
|
+
obj.put("heartRateBpm", r.hrBpm);
|
|
1420
|
+
obj.put("averageSignalQuality", r.averageSignalQuality);
|
|
1421
|
+
obj.put("heartbeats", heartbeatsToJSONArray(r.heartbeats));
|
|
1422
|
+
obj.put("breathingRateBpm", r.brBpm.orElse(null));
|
|
1423
|
+
obj.put("hrvLnrmssdMs", r.hrvLnrmssdMs.orElse(null));
|
|
1424
|
+
obj.put("hrvSdnnMs", r.hrvSdnnMs.orElse(null));
|
|
1425
|
+
obj.put("stressIndex", r.stressIndex.orElse(null));
|
|
1426
|
+
obj.put("parasympatheticActivity", r.parasympatheticActivity.orElse(null));
|
|
1427
|
+
obj.put("systolicBloodPressureMmhg", r.systolicBloodPressureMmhg.orElse(null));
|
|
1428
|
+
obj.put("diastolicBloodPressureMmhg", r.diastolicBloodPressureMmhg.orElse(null));
|
|
1429
|
+
obj.put("cardiacWorkloadMmhgPerSec", r.cardiacWorkloadMmhgPerSec.orElse(null));
|
|
1430
|
+
obj.put("ageYears", r.ageYears.orElse(null));
|
|
1431
|
+
obj.put("bmiKgPerM2", r.bmiKgPerM2.orElse(null));
|
|
1432
|
+
obj.put("bmiCategory", r.bmiCategory.map(Enum::ordinal).orElse(null));
|
|
1433
|
+
obj.put("weightKg", r.weightKg.orElse(null));
|
|
1434
|
+
obj.put("heightCm", r.heightCm.orElse(null));
|
|
1435
|
+
obj.put("qualityMetrics", measurementQualityMetricsToJSObject(r.qualityMetrics));
|
|
1436
|
+
return obj;
|
|
1437
|
+
}
|
|
1438
|
+
|
|
1439
|
+
private JSObject measurementResultsWithMetadataToJSObject(ShenAIAndroidSDK.MeasurementResultsWithMetadata md) {
|
|
1440
|
+
JSObject obj = new JSObject();
|
|
1441
|
+
obj.put("measurementResults", measurementResultsToJSObject(md.measurementResults));
|
|
1442
|
+
obj.put("epochTimestamp", md.epochTimestamp);
|
|
1443
|
+
obj.put("isCalibration", md.isCalibration);
|
|
1444
|
+
return obj;
|
|
1445
|
+
}
|
|
1446
|
+
|
|
1447
|
+
// ───────────────────────────────────────────────────── lifecycle glue
|
|
1448
|
+
@Override
|
|
1449
|
+
protected void handleOnResume() {
|
|
1450
|
+
if (shenaiView != null) shenaiView.onResume();
|
|
1451
|
+
}
|
|
1452
|
+
@Override
|
|
1453
|
+
protected void handleOnPause() {
|
|
1454
|
+
if (shenaiView != null) shenaiView.onPause();
|
|
1455
|
+
}
|
|
1456
|
+
@Override
|
|
1457
|
+
public void handleOnDestroy() {
|
|
1458
|
+
if (shenaiView != null || containerView != null) {
|
|
1459
|
+
getActivity().runOnUiThread(() -> {
|
|
1460
|
+
try {
|
|
1461
|
+
getBridge().getWebView().setOnTouchListener(null);
|
|
1462
|
+
getBridge().getWebView().setAlpha(1.0f);
|
|
1463
|
+
} catch (Throwable ignored) {}
|
|
1464
|
+
|
|
1465
|
+
if (containerView != null) {
|
|
1466
|
+
ViewGroup parent = (ViewGroup) containerView.getParent();
|
|
1467
|
+
if (parent != null) parent.removeView(containerView);
|
|
1468
|
+
}
|
|
1469
|
+
});
|
|
1470
|
+
shenaiView = null;
|
|
1471
|
+
containerView = null;
|
|
1472
|
+
}
|
|
1473
|
+
sdk = null;
|
|
1474
|
+
}
|
|
1475
|
+
|
|
1476
|
+
}
|