@capgo/capacitor-zebra-datawedge 8.0.0

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.
@@ -0,0 +1,990 @@
1
+ package app.capgo.zebradatawedge;
2
+
3
+ import android.content.BroadcastReceiver;
4
+ import android.content.Context;
5
+ import android.content.Intent;
6
+ import android.content.IntentFilter;
7
+ import android.os.Bundle;
8
+ import android.os.Handler;
9
+ import android.os.Looper;
10
+ import androidx.core.content.ContextCompat;
11
+ import com.getcapacitor.JSArray;
12
+ import com.getcapacitor.JSObject;
13
+ import com.getcapacitor.Plugin;
14
+ import com.getcapacitor.PluginCall;
15
+ import com.getcapacitor.PluginMethod;
16
+ import com.getcapacitor.annotation.CapacitorPlugin;
17
+ import java.util.ArrayList;
18
+ import java.util.Collections;
19
+ import java.util.LinkedHashSet;
20
+ import java.util.List;
21
+ import java.util.Map;
22
+ import java.util.Set;
23
+ import java.util.concurrent.ConcurrentHashMap;
24
+ import org.json.JSONArray;
25
+ import org.json.JSONException;
26
+ import org.json.JSONObject;
27
+
28
+ @CapacitorPlugin(name = "ZebraDataWedge")
29
+ public class ZebraDataWedgePlugin extends Plugin {
30
+
31
+ private static final String PLUGIN_VERSION = "8.0.0";
32
+ private static final long REQUEST_TIMEOUT_MS = 8000L;
33
+ private static final long SCAN_TIMEOUT_MS = 15000L;
34
+
35
+ private final Handler handler = new Handler(Looper.getMainLooper());
36
+ private final Map<String, PendingRequest> pendingRequests = new ConcurrentHashMap<>();
37
+ private final Map<String, ScanRequest> pendingScans = new ConcurrentHashMap<>();
38
+ private final Set<String> registeredIntentActions = Collections.synchronizedSet(new LinkedHashSet<>());
39
+ private BroadcastReceiver receiver;
40
+ private boolean receiverRegistered = false;
41
+
42
+ @Override
43
+ public void load() {
44
+ ensureReceiver();
45
+ }
46
+
47
+ @Override
48
+ protected void handleOnDestroy() {
49
+ super.handleOnDestroy();
50
+ if (receiverRegistered && receiver != null) {
51
+ try {
52
+ getContext().unregisterReceiver(receiver);
53
+ } catch (IllegalArgumentException ignored) {}
54
+ receiverRegistered = false;
55
+ }
56
+ for (PendingRequest request : pendingRequests.values()) {
57
+ handler.removeCallbacks(request.timeoutRunnable);
58
+ request.call.reject("Timed out waiting for DataWedge response.");
59
+ }
60
+ pendingRequests.clear();
61
+ for (ScanRequest request : pendingScans.values()) {
62
+ handler.removeCallbacks(request.timeoutRunnable);
63
+ request.call.reject("Timed out waiting for a Zebra scan result.");
64
+ }
65
+ pendingScans.clear();
66
+ }
67
+
68
+ @PluginMethod
69
+ public void cloneProfile(PluginCall call) {
70
+ String source = requiredString(call, "sourceProfileName");
71
+ String destination = requiredString(call, "destProfileName");
72
+ if (source == null || destination == null) {
73
+ return;
74
+ }
75
+ Intent intent = ZebraDataWedge.newIntent();
76
+ intent.putExtra(ZebraDataWedge.CMD_CLONE_PROFILE, new String[] { source, destination });
77
+ sendCommand(call, intent, "clone-profile", this::emptyResponse);
78
+ }
79
+
80
+ @PluginMethod
81
+ public void createProfile(PluginCall call) {
82
+ String profileName = requiredString(call, "profileName");
83
+ if (profileName == null) {
84
+ return;
85
+ }
86
+ Intent intent = ZebraDataWedge.newIntent();
87
+ intent.putExtra(ZebraDataWedge.CMD_CREATE_PROFILE, profileName);
88
+ sendCommand(call, intent, "create-profile", this::emptyResponse);
89
+ }
90
+
91
+ @PluginMethod
92
+ public void deleteProfile(PluginCall call) {
93
+ JSONArray profileNames = call.getArray("profileNames");
94
+ if (profileNames == null || profileNames.length() == 0) {
95
+ call.reject("profileNames is required.");
96
+ return;
97
+ }
98
+ Intent intent = ZebraDataWedge.newIntent();
99
+ intent.putExtra(ZebraDataWedge.CMD_DELETE_PROFILE, ZebraDataWedge.jsonArrayToStringArray(profileNames));
100
+ sendCommand(call, intent, "delete-profile", this::emptyResponse);
101
+ }
102
+
103
+ @PluginMethod
104
+ public void importConfig(PluginCall call) {
105
+ String folderPath = requiredString(call, "folderPath");
106
+ if (folderPath == null) {
107
+ return;
108
+ }
109
+ Bundle options = new Bundle();
110
+ options.putString("FOLDER_PATH", folderPath);
111
+ JSONArray fileList = call.getArray("fileList");
112
+ if (fileList != null && fileList.length() > 0) {
113
+ options.putStringArray("FILE_LIST", ZebraDataWedge.jsonArrayToStringArray(fileList));
114
+ }
115
+ Intent intent = ZebraDataWedge.newIntent();
116
+ intent.putExtra(ZebraDataWedge.CMD_IMPORT_CONFIG, options);
117
+ sendCommand(call, intent, "import-config", this::emptyResponse);
118
+ }
119
+
120
+ @PluginMethod
121
+ public void renameProfile(PluginCall call) {
122
+ String currentProfileName = requiredString(call, "currentProfileName");
123
+ String newProfileName = requiredString(call, "newProfileName");
124
+ if (currentProfileName == null || newProfileName == null) {
125
+ return;
126
+ }
127
+ Intent intent = ZebraDataWedge.newIntent();
128
+ intent.putExtra(ZebraDataWedge.CMD_RENAME_PROFILE, new String[] { currentProfileName, newProfileName });
129
+ sendCommand(call, intent, "rename-profile", this::emptyResponse);
130
+ }
131
+
132
+ @PluginMethod
133
+ public void restoreConfig(PluginCall call) {
134
+ Intent intent = ZebraDataWedge.newIntent();
135
+ intent.putExtra(ZebraDataWedge.CMD_RESTORE_CONFIG, "");
136
+ sendCommand(call, intent, "restore-config", this::emptyResponse);
137
+ }
138
+
139
+ @PluginMethod
140
+ public void setConfig(PluginCall call) {
141
+ String profileName = requiredString(call, "profileName");
142
+ if (profileName == null) {
143
+ return;
144
+ }
145
+ Bundle config = new Bundle();
146
+ config.putString("PROFILE_NAME", profileName);
147
+ Boolean profileEnabled = call.getBoolean("profileEnabled");
148
+ if (profileEnabled != null) {
149
+ config.putString("PROFILE_ENABLED", Boolean.toString(profileEnabled));
150
+ }
151
+ String configMode = call.getString("configMode");
152
+ if (configMode != null) {
153
+ config.putString("CONFIG_MODE", configMode);
154
+ }
155
+ JSONArray appList = call.getArray("appList");
156
+ if (appList != null && appList.length() > 0) {
157
+ config.putParcelableArray("APP_LIST", parseAppList(appList));
158
+ }
159
+ JSONArray pluginConfigs = call.getArray("pluginConfigs");
160
+ if (pluginConfigs != null && pluginConfigs.length() > 0) {
161
+ config.putParcelableArrayList("PLUGIN_CONFIG", parsePluginConfigs(pluginConfigs));
162
+ }
163
+ Intent intent = ZebraDataWedge.newIntent();
164
+ intent.putExtra(ZebraDataWedge.CMD_SET_CONFIG, config);
165
+ sendCommand(call, intent, "set-config", this::emptyResponse);
166
+ }
167
+
168
+ @PluginMethod
169
+ public void setDisabledAppList(PluginCall call) {
170
+ String configMode = requiredString(call, "configMode");
171
+ if (configMode == null) {
172
+ return;
173
+ }
174
+ Bundle config = new Bundle();
175
+ config.putString("CONFIG_MODE", configMode);
176
+ JSONArray appList = call.getArray("appList");
177
+ if (appList != null && appList.length() > 0) {
178
+ config.putParcelableArray("APP_LIST", parseAppList(appList));
179
+ }
180
+ Intent intent = ZebraDataWedge.newIntent();
181
+ intent.putExtra(ZebraDataWedge.CMD_SET_DISABLED_APP_LIST, config);
182
+ sendCommand(call, intent, "set-disabled-app-list", this::emptyResponse);
183
+ }
184
+
185
+ @PluginMethod
186
+ public void setIgnoreDisabledProfiles(PluginCall call) {
187
+ Boolean enabled = call.getBoolean("enabled");
188
+ if (enabled == null) {
189
+ call.reject("enabled is required.");
190
+ return;
191
+ }
192
+ Intent intent = ZebraDataWedge.newIntent();
193
+ intent.putExtra(ZebraDataWedge.CMD_SET_IGNORE_DISABLED_PROFILES, enabled);
194
+ sendCommand(call, intent, "set-ignore-disabled-profiles", this::emptyResponse);
195
+ }
196
+
197
+ @PluginMethod
198
+ public void registerForNotification(PluginCall call) {
199
+ String notificationType = requiredString(call, "notificationType");
200
+ if (notificationType == null) {
201
+ return;
202
+ }
203
+ String intentAction = call.getString("intentAction");
204
+ if (intentAction != null && !intentAction.isEmpty()) {
205
+ ensureIntentAction(intentAction);
206
+ }
207
+ Bundle options = new Bundle();
208
+ options.putString("APPLICATION_NAME", call.getString("appName", getContext().getPackageName()));
209
+ options.putString("NOTIFICATION_TYPE", notificationType);
210
+ Intent intent = ZebraDataWedge.newIntent();
211
+ intent.putExtra(ZebraDataWedge.CMD_REGISTER_FOR_NOTIFICATION, options);
212
+ sendCommand(call, intent, "register-for-notification", this::emptyResponse);
213
+ }
214
+
215
+ @PluginMethod
216
+ public void unRegisterForNotification(PluginCall call) {
217
+ String notificationType = requiredString(call, "notificationType");
218
+ if (notificationType == null) {
219
+ return;
220
+ }
221
+ Bundle options = new Bundle();
222
+ options.putString("APPLICATION_NAME", call.getString("appName", getContext().getPackageName()));
223
+ options.putString("NOTIFICATION_TYPE", notificationType);
224
+ Intent intent = ZebraDataWedge.newIntent();
225
+ intent.putExtra(ZebraDataWedge.CMD_UNREGISTER_FOR_NOTIFICATION, options);
226
+ sendCommand(call, intent, "unregister-for-notification", this::emptyResponse);
227
+ }
228
+
229
+ @PluginMethod
230
+ public void enumerateScanners(PluginCall call) {
231
+ Intent intent = ZebraDataWedge.newIntent();
232
+ intent.putExtra(ZebraDataWedge.CMD_ENUMERATE_SCANNERS, "");
233
+ sendCommand(call, intent, "enumerate-scanners", this::parseEnumerateScanners);
234
+ }
235
+
236
+ @PluginMethod
237
+ public void getActiveProfile(PluginCall call) {
238
+ Intent intent = ZebraDataWedge.newIntent();
239
+ intent.putExtra(ZebraDataWedge.CMD_GET_ACTIVE_PROFILE, "");
240
+ sendCommand(call, intent, "get-active-profile", this::parseActiveProfile);
241
+ }
242
+
243
+ @PluginMethod
244
+ public void getAssociatedApps(PluginCall call) {
245
+ String profileName = requiredString(call, "profileName");
246
+ if (profileName == null) {
247
+ return;
248
+ }
249
+ Bundle options = new Bundle();
250
+ options.putString("PROFILE_NAME", profileName);
251
+ Intent intent = ZebraDataWedge.newIntent();
252
+ intent.putExtra(ZebraDataWedge.CMD_GET_CONFIG, options);
253
+ sendCommand(call, intent, "get-associated-apps", (response) -> {
254
+ JSObject config = parseConfig(response);
255
+ JSObject ret = new JSObject();
256
+ ret.put("appList", config.optJSONArray("appList"));
257
+ return ret;
258
+ });
259
+ }
260
+
261
+ @PluginMethod
262
+ public void getConfig(PluginCall call) {
263
+ String profileName = requiredString(call, "profileName");
264
+ if (profileName == null) {
265
+ return;
266
+ }
267
+ Bundle options = new Bundle();
268
+ options.putString("PROFILE_NAME", profileName);
269
+ JSONArray pluginConfigs = call.getArray("pluginConfigs");
270
+ if (pluginConfigs != null && pluginConfigs.length() > 0) {
271
+ ArrayList<Bundle> bundles = new ArrayList<>();
272
+ for (int i = 0; i < pluginConfigs.length(); i++) {
273
+ JSONObject jsonObject = pluginConfigs.optJSONObject(i);
274
+ if (jsonObject == null) {
275
+ continue;
276
+ }
277
+ Bundle config = new Bundle();
278
+ config.putString("PLUGIN_NAME", jsonObject.optString("pluginName"));
279
+ if (jsonObject.has("outputPluginName")) {
280
+ config.putString("OUTPUT_PLUGIN_NAME", jsonObject.optString("outputPluginName"));
281
+ }
282
+ bundles.add(config);
283
+ }
284
+ options.putParcelableArrayList("PLUGIN_CONFIG", bundles);
285
+ }
286
+ Intent intent = ZebraDataWedge.newIntent();
287
+ intent.putExtra(ZebraDataWedge.CMD_GET_CONFIG, options);
288
+ sendCommand(call, intent, "get-config", this::parseConfig);
289
+ }
290
+
291
+ @PluginMethod
292
+ public void getDatawedgeStatus(PluginCall call) {
293
+ Intent intent = ZebraDataWedge.newIntent();
294
+ intent.putExtra(ZebraDataWedge.CMD_GET_DATAWEDGE_STATUS, "");
295
+ sendCommand(call, intent, "get-datawedge-status", this::parseDataWedgeStatus);
296
+ }
297
+
298
+ @PluginMethod
299
+ public void getDisabledAppList(PluginCall call) {
300
+ Intent intent = ZebraDataWedge.newIntent();
301
+ intent.putExtra(ZebraDataWedge.CMD_GET_DISABLED_APP_LIST, "");
302
+ sendCommand(call, intent, "get-disabled-app-list", this::parseDisabledAppList);
303
+ }
304
+
305
+ @PluginMethod
306
+ public void getIgnoreDisabledProfiles(PluginCall call) {
307
+ Intent intent = ZebraDataWedge.newIntent();
308
+ intent.putExtra(ZebraDataWedge.CMD_GET_IGNORE_DISABLED_PROFILES, "");
309
+ sendCommand(call, intent, "get-ignore-disabled-profiles", this::parseIgnoreDisabledProfiles);
310
+ }
311
+
312
+ @PluginMethod
313
+ public void getProfilesList(PluginCall call) {
314
+ Intent intent = ZebraDataWedge.newIntent();
315
+ intent.putExtra(ZebraDataWedge.CMD_GET_PROFILES_LIST, "");
316
+ sendCommand(call, intent, "get-profiles-list", this::parseProfilesList);
317
+ }
318
+
319
+ @PluginMethod
320
+ public void getScannerStatus(PluginCall call) {
321
+ Intent intent = ZebraDataWedge.newIntent();
322
+ intent.putExtra(ZebraDataWedge.CMD_GET_SCANNER_STATUS, "");
323
+ sendCommand(call, intent, "get-scanner-status", this::parseScannerStatus);
324
+ }
325
+
326
+ @PluginMethod
327
+ public void getVersionInfo(PluginCall call) {
328
+ Intent intent = ZebraDataWedge.newIntent();
329
+ intent.putExtra(ZebraDataWedge.CMD_GET_VERSION_INFO, "");
330
+ sendCommand(call, intent, "get-version-info", this::parseVersionInfo);
331
+ }
332
+
333
+ @PluginMethod
334
+ public void disableDatawedge(PluginCall call) {
335
+ Intent intent = ZebraDataWedge.newIntent();
336
+ intent.putExtra(ZebraDataWedge.CMD_ENABLE_DATAWEDGE, false);
337
+ sendCommand(call, intent, "disable-datawedge", this::emptyResponse);
338
+ }
339
+
340
+ @PluginMethod
341
+ public void disableScannerInput(PluginCall call) {
342
+ Intent intent = ZebraDataWedge.newIntent();
343
+ intent.putExtra(ZebraDataWedge.CMD_SCANNER_INPUT_PLUGIN, ZebraDataWedge.VALUE_DISABLE_PLUGIN);
344
+ sendCommand(call, intent, "disable-scanner-input", this::emptyResponse);
345
+ }
346
+
347
+ @PluginMethod
348
+ public void enableDatawedge(PluginCall call) {
349
+ Intent intent = ZebraDataWedge.newIntent();
350
+ intent.putExtra(ZebraDataWedge.CMD_ENABLE_DATAWEDGE, true);
351
+ sendCommand(call, intent, "enable-datawedge", this::emptyResponse);
352
+ }
353
+
354
+ @PluginMethod
355
+ public void enableScannerInput(PluginCall call) {
356
+ Intent intent = ZebraDataWedge.newIntent();
357
+ intent.putExtra(ZebraDataWedge.CMD_SCANNER_INPUT_PLUGIN, ZebraDataWedge.VALUE_ENABLE_PLUGIN);
358
+ sendCommand(call, intent, "enable-scanner-input", this::emptyResponse);
359
+ }
360
+
361
+ @PluginMethod
362
+ public void enumerateTriggers(PluginCall call) {
363
+ Intent intent = ZebraDataWedge.newIntent();
364
+ intent.putExtra(ZebraDataWedge.CMD_ENUMERATE_TRIGGERS, "");
365
+ sendCommand(call, intent, "enumerate-triggers", this::parseTriggers);
366
+ }
367
+
368
+ @PluginMethod
369
+ public void notify(PluginCall call) {
370
+ String deviceIdentifier = requiredString(call, "deviceIdentifier");
371
+ JSONArray notificationSettings = call.getArray("notificationSettings");
372
+ if (deviceIdentifier == null || notificationSettings == null) {
373
+ if (notificationSettings == null) {
374
+ call.reject("notificationSettings is required.");
375
+ }
376
+ return;
377
+ }
378
+ Bundle options = new Bundle();
379
+ options.putString("DEVICE_IDENTIFIER", deviceIdentifier);
380
+ options.putIntArray("NOTIFICATION_SETTINGS", ZebraDataWedge.jsonArrayToIntArray(notificationSettings));
381
+ Intent intent = ZebraDataWedge.newIntent();
382
+ intent.putExtra(ZebraDataWedge.CMD_NOTIFY, options);
383
+ sendCommand(call, intent, "notify", this::emptyResponse);
384
+ }
385
+
386
+ @PluginMethod
387
+ public void resetDefaultProfile(PluginCall call) {
388
+ Intent intent = ZebraDataWedge.newIntent();
389
+ intent.putExtra(ZebraDataWedge.CMD_RESET_DEFAULT_PROFILE, "");
390
+ sendCommand(call, intent, "reset-default-profile", this::emptyResponse);
391
+ }
392
+
393
+ @PluginMethod
394
+ public void setDefaultProfile(PluginCall call) {
395
+ String profileName = requiredString(call, "profileName");
396
+ if (profileName == null) {
397
+ return;
398
+ }
399
+ Intent intent = ZebraDataWedge.newIntent();
400
+ intent.putExtra(ZebraDataWedge.CMD_SET_DEFAULT_PROFILE, profileName);
401
+ sendCommand(call, intent, "set-default-profile", this::emptyResponse);
402
+ }
403
+
404
+ @PluginMethod
405
+ public void setReportingOptions(PluginCall call) {
406
+ Boolean reportingEnabled = call.getBoolean("reportingEnabled");
407
+ if (reportingEnabled == null) {
408
+ call.reject("reportingEnabled is required.");
409
+ return;
410
+ }
411
+ Bundle options = new Bundle();
412
+ options.putString("REPORTING_ENABLED", Boolean.toString(reportingEnabled));
413
+ if (call.hasOption("reportingGenerateOption")) {
414
+ options.putString("REPORTING_GENERATE_OPTION", call.getString("reportingGenerateOption"));
415
+ }
416
+ if (call.hasOption("reportingShowForManualImport")) {
417
+ options.putString("REPORTING_SHOW_FOR_MANUAL_IMPORT", Boolean.toString(call.getBoolean("reportingShowForManualImport", false)));
418
+ }
419
+ Intent intent = ZebraDataWedge.newIntent();
420
+ intent.putExtra(ZebraDataWedge.CMD_SET_REPORTING_OPTIONS, options);
421
+ sendCommand(call, intent, "set-reporting-options", this::emptyResponse);
422
+ }
423
+
424
+ @PluginMethod
425
+ public void softRfidTrigger(PluginCall call) {
426
+ String action = registeredIntentActions.stream().findFirst().orElse(null);
427
+ if (action == null) {
428
+ call.reject(
429
+ "No scan intentAction is registered. Call softScanTrigger(intentAction) or registerForNotification({ intentAction }) first."
430
+ );
431
+ return;
432
+ }
433
+ startPendingScan(call, action);
434
+ Intent intent = ZebraDataWedge.newIntent();
435
+ intent.putExtra(ZebraDataWedge.CMD_SOFT_RFID_TRIGGER, ZebraDataWedge.VALUE_START_SCANNING);
436
+ sendBroadcast(intent, call);
437
+ }
438
+
439
+ @PluginMethod
440
+ public void softScanTrigger(PluginCall call) {
441
+ String intentAction = requiredString(call, "intentAction");
442
+ if (intentAction == null) {
443
+ return;
444
+ }
445
+ ensureIntentAction(intentAction);
446
+ startPendingScan(call, intentAction);
447
+ Intent intent = ZebraDataWedge.newIntent();
448
+ intent.putExtra(ZebraDataWedge.CMD_SOFT_SCAN_TRIGGER, ZebraDataWedge.VALUE_START_SCANNING);
449
+ sendBroadcast(intent, call);
450
+ }
451
+
452
+ @PluginMethod
453
+ public void switchScanner(PluginCall call) {
454
+ String scannerIdentifier = call.getString("scannerIdentifier");
455
+ String scannerIndex = call.getString("scannerIndex");
456
+ String value = scannerIdentifier != null ? scannerIdentifier : scannerIndex;
457
+ if (value == null || value.isEmpty()) {
458
+ call.reject("scannerIdentifier or scannerIndex is required.");
459
+ return;
460
+ }
461
+ Intent intent = ZebraDataWedge.newIntent();
462
+ intent.putExtra(ZebraDataWedge.CMD_SWITCH_SCANNER, value);
463
+ sendCommand(call, intent, "switch-scanner", this::emptyResponse);
464
+ }
465
+
466
+ @PluginMethod
467
+ public void switchScannerParams(PluginCall call) {
468
+ String scannerIdentifier = requiredString(call, "scannerIdentifier");
469
+ JSObject scannerParams = call.getObject("scannerParams");
470
+ if (scannerIdentifier == null || scannerParams == null) {
471
+ if (scannerParams == null) {
472
+ call.reject("scannerParams is required.");
473
+ }
474
+ return;
475
+ }
476
+ Bundle options = new Bundle();
477
+ options.putString("SCANNER_IDENTIFIER", scannerIdentifier);
478
+ options.putBundle("SCANNER_PARAMS", ZebraDataWedge.jsonObjectToBundle(scannerParams));
479
+ Intent intent = ZebraDataWedge.newIntent();
480
+ intent.putExtra(ZebraDataWedge.CMD_SWITCH_SCANNER_PARAMS, options);
481
+ sendCommand(call, intent, "switch-scanner-params", this::emptyResponse);
482
+ }
483
+
484
+ @PluginMethod
485
+ public void switchToProfile(PluginCall call) {
486
+ String profileName = requiredString(call, "profileName");
487
+ if (profileName == null) {
488
+ return;
489
+ }
490
+ Intent intent = ZebraDataWedge.newIntent();
491
+ intent.putExtra(ZebraDataWedge.CMD_SWITCH_TO_PROFILE, profileName);
492
+ sendCommand(call, intent, "switch-to-profile", this::emptyResponse);
493
+ }
494
+
495
+ @PluginMethod
496
+ public void getPluginVersion(PluginCall call) {
497
+ JSObject ret = new JSObject();
498
+ ret.put("version", PLUGIN_VERSION);
499
+ call.resolve(ret);
500
+ }
501
+
502
+ private void ensureReceiver() {
503
+ if (receiver == null) {
504
+ receiver = new BroadcastReceiver() {
505
+ @Override
506
+ public void onReceive(Context context, Intent intent) {
507
+ handleIntent(intent);
508
+ }
509
+ };
510
+ }
511
+ refreshReceiver();
512
+ }
513
+
514
+ private void ensureIntentAction(String intentAction) {
515
+ if (registeredIntentActions.add(intentAction)) {
516
+ refreshReceiver();
517
+ }
518
+ }
519
+
520
+ private void refreshReceiver() {
521
+ if (receiver == null) {
522
+ return;
523
+ }
524
+ if (receiverRegistered) {
525
+ try {
526
+ getContext().unregisterReceiver(receiver);
527
+ } catch (IllegalArgumentException ignored) {}
528
+ receiverRegistered = false;
529
+ }
530
+ IntentFilter filter = new IntentFilter();
531
+ filter.addAction(ZebraDataWedge.RESULT_ACTION);
532
+ filter.addAction(ZebraDataWedge.NOTIFICATION_ACTION);
533
+ filter.addCategory(Intent.CATEGORY_DEFAULT);
534
+ synchronized (registeredIntentActions) {
535
+ for (String action : registeredIntentActions) {
536
+ filter.addAction(action);
537
+ }
538
+ }
539
+ ContextCompat.registerReceiver(getContext(), receiver, filter, ContextCompat.RECEIVER_EXPORTED);
540
+ receiverRegistered = true;
541
+ }
542
+
543
+ private void handleIntent(Intent intent) {
544
+ String action = intent.getAction();
545
+ if (action == null) {
546
+ return;
547
+ }
548
+ if (ZebraDataWedge.RESULT_ACTION.equals(action)) {
549
+ String commandId = intent.getStringExtra(ZebraDataWedge.EXTRA_COMMAND_IDENTIFIER);
550
+ if (commandId != null) {
551
+ PendingRequest request = pendingRequests.remove(commandId);
552
+ if (request != null) {
553
+ handler.removeCallbacks(request.timeoutRunnable);
554
+ resolvePendingRequest(request, intent);
555
+ return;
556
+ }
557
+ }
558
+ }
559
+
560
+ if (intent.hasExtra(ZebraDataWedge.EXTRA_NOTIFICATION)) {
561
+ notifyListeners("notification", parseNotification(intent));
562
+ }
563
+
564
+ if (intent.hasExtra(ZebraDataWedge.EXTRA_SCAN_DATA)) {
565
+ JSObject payload = ZebraDataWedge.parseScanIntent(intent);
566
+ notifyListeners("scan", payload);
567
+ resolvePendingScan(intent.getAction(), payload);
568
+ }
569
+ }
570
+
571
+ private void sendCommand(PluginCall call, Intent intent, String prefix, ResponseParser parser) {
572
+ String commandId = ZebraDataWedge.newCommandIdentifier(prefix);
573
+ intent.putExtra(ZebraDataWedge.EXTRA_SEND_RESULT, ZebraDataWedge.VALUE_LAST_RESULT);
574
+ intent.putExtra(ZebraDataWedge.EXTRA_COMMAND_IDENTIFIER, commandId);
575
+ Runnable timeout = () -> {
576
+ PendingRequest removed = pendingRequests.remove(commandId);
577
+ if (removed != null) {
578
+ removed.call.reject("Timed out waiting for DataWedge response.");
579
+ }
580
+ };
581
+ pendingRequests.put(commandId, new PendingRequest(call, parser, timeout));
582
+ handler.postDelayed(timeout, REQUEST_TIMEOUT_MS);
583
+ sendBroadcast(intent, call);
584
+ }
585
+
586
+ private void sendBroadcast(Intent intent, PluginCall call) {
587
+ try {
588
+ getContext().sendBroadcast(intent);
589
+ } catch (Exception exception) {
590
+ call.reject("Failed to communicate with Zebra DataWedge.", exception);
591
+ }
592
+ }
593
+
594
+ private void resolvePendingRequest(PendingRequest request, Intent intent) {
595
+ try {
596
+ rejectIfFailure(intent);
597
+ request.call.resolve(request.parser.parse(intent));
598
+ } catch (ZebraDataWedgeException exception) {
599
+ request.call.reject(exception.getMessage(), exception.getCode());
600
+ } catch (Exception exception) {
601
+ request.call.reject(exception.getMessage(), exception);
602
+ }
603
+ }
604
+
605
+ private void startPendingScan(PluginCall call, String intentAction) {
606
+ Runnable timeout = () -> {
607
+ ScanRequest removed = pendingScans.remove(intentAction);
608
+ if (removed != null) {
609
+ removed.call.reject("Timed out waiting for a Zebra scan result.");
610
+ }
611
+ };
612
+ ScanRequest previous = pendingScans.put(intentAction, new ScanRequest(call, timeout));
613
+ if (previous != null) {
614
+ handler.removeCallbacks(previous.timeoutRunnable);
615
+ previous.call.reject("A scan request was replaced by a newer request.");
616
+ }
617
+ handler.postDelayed(timeout, SCAN_TIMEOUT_MS);
618
+ }
619
+
620
+ private void resolvePendingScan(String action, JSObject payload) {
621
+ ScanRequest request = pendingScans.remove(action);
622
+ if (request == null) {
623
+ return;
624
+ }
625
+ handler.removeCallbacks(request.timeoutRunnable);
626
+ request.call.resolve(payload);
627
+ }
628
+
629
+ private void rejectIfFailure(Intent intent) throws ZebraDataWedgeException {
630
+ String result = intent.getStringExtra(ZebraDataWedge.EXTRA_RESULT);
631
+ Bundle resultInfo = intent.getBundleExtra(ZebraDataWedge.EXTRA_RESULT_INFO);
632
+ if (ZebraDataWedge.RESULT_FAILURE.equalsIgnoreCase(result)) {
633
+ throw errorFromResult(resultInfo);
634
+ }
635
+ if (resultInfo != null) {
636
+ String resultCode = resultInfo.getString("RESULT_CODE");
637
+ if (resultCode != null && !resultCode.isEmpty() && ZebraDataWedge.RESULT_FAILURE.equalsIgnoreCase(result)) {
638
+ throw errorFromResult(resultInfo);
639
+ }
640
+ }
641
+ }
642
+
643
+ private ZebraDataWedgeException errorFromResult(Bundle resultInfo) {
644
+ String code = resultInfo != null ? resultInfo.getString("RESULT_CODE", "UNKNOWN") : "UNKNOWN";
645
+ String message = resultInfo != null ? ZebraDataWedge.bundleToJSObject(resultInfo).toString() : "Unknown DataWedge error.";
646
+ return new ZebraDataWedgeException(code, message);
647
+ }
648
+
649
+ private JSObject emptyResponse(Intent intent) {
650
+ return new JSObject();
651
+ }
652
+
653
+ private JSObject parseProfilesList(Intent intent) {
654
+ String[] profiles = firstStringArray(intent, ZebraDataWedge.RESULT_GET_PROFILES_LIST);
655
+ JSObject ret = new JSObject();
656
+ ret.put("profiles", ZebraDataWedge.stringArrayToJSArray(profiles));
657
+ return ret;
658
+ }
659
+
660
+ private JSObject parseActiveProfile(Intent intent) {
661
+ JSObject ret = new JSObject();
662
+ ret.put("profileName", firstString(intent, ZebraDataWedge.RESULT_GET_ACTIVE_PROFILE, "PROFILE_NAME"));
663
+ return ret;
664
+ }
665
+
666
+ private JSObject parseDataWedgeStatus(Intent intent) {
667
+ String rawStatus = firstString(intent, ZebraDataWedge.RESULT_GET_DATAWEDGE_STATUS, "DATAWEDGE_STATUS");
668
+ JSObject ret = new JSObject();
669
+ ret.put("isEnabled", rawStatus != null && ("enabled".equalsIgnoreCase(rawStatus) || Boolean.parseBoolean(rawStatus)));
670
+ return ret;
671
+ }
672
+
673
+ private JSObject parseIgnoreDisabledProfiles(Intent intent) {
674
+ String rawValue = firstString(intent, ZebraDataWedge.RESULT_GET_IGNORE_DISABLED_PROFILES, "IGNORE_DISABLED_PROFILES");
675
+ JSObject ret = new JSObject();
676
+ ret.put("enabled", rawValue != null && ("true".equalsIgnoreCase(rawValue) || "enabled".equalsIgnoreCase(rawValue)));
677
+ return ret;
678
+ }
679
+
680
+ private JSObject parseScannerStatus(Intent intent) {
681
+ JSObject ret = new JSObject();
682
+ ret.put("status", firstString(intent, ZebraDataWedge.RESULT_GET_SCANNER_STATUS, "SCANNER_STATUS"));
683
+ return ret;
684
+ }
685
+
686
+ private JSObject parseTriggers(Intent intent) {
687
+ String[] triggers = firstStringArray(intent, ZebraDataWedge.RESULT_ENUMERATE_TRIGGERS, "ENUMERATE_TRIGGERS");
688
+ JSObject ret = new JSObject();
689
+ ret.put("triggers", ZebraDataWedge.stringArrayToJSArray(triggers));
690
+ return ret;
691
+ }
692
+
693
+ private JSObject parseDisabledAppList(Intent intent) {
694
+ JSObject ret = new JSObject();
695
+ ret.put("appList", parseAppListResult(extractBundleList(intent, ZebraDataWedge.RESULT_GET_DISABLED_APP_LIST)));
696
+ return ret;
697
+ }
698
+
699
+ private JSObject parseVersionInfo(Intent intent) {
700
+ Bundle versionInfo = firstBundle(intent, ZebraDataWedge.RESULT_GET_VERSION_INFO, "GET_VERSION_INFO_RESULT");
701
+ JSObject ret = new JSObject();
702
+ if (versionInfo == null) {
703
+ return ret;
704
+ }
705
+ ret.put("dataWedgeVersion", versionInfo.getString("DATAWEDGE"));
706
+ ret.put("barcodeVersion", versionInfo.getString("BARCODE_SCANNING"));
707
+ ret.put("decoderVersion", versionInfo.getString("DECODER_LIBRARY"));
708
+ ret.put("simulScanVersion", versionInfo.getString("SIMULSCAN"));
709
+ String[] firmware = versionInfo.getStringArray("SCANNER_FIRMWARE");
710
+ if (firmware != null) {
711
+ ret.put("scannerFirmwareVersions", ZebraDataWedge.stringArrayToJSArray(firmware));
712
+ }
713
+ return ret;
714
+ }
715
+
716
+ private JSObject parseConfig(Intent intent) {
717
+ Bundle config = firstBundle(intent, ZebraDataWedge.RESULT_GET_CONFIG, ZebraDataWedge.RESULT_GET_CONFIG_LEGACY);
718
+ JSObject ret = new JSObject();
719
+ if (config == null) {
720
+ return ret;
721
+ }
722
+ ret.put("profileName", config.getString("PROFILE_NAME"));
723
+ ret.put("profileEnabled", "true".equalsIgnoreCase(config.getString("PROFILE_ENABLED")));
724
+ ret.put("pluginConfigList", parsePluginConfigResult(extractPluginConfig(config)));
725
+ ret.put("appList", parseAppListResult(extractAppList(config)));
726
+ return ret;
727
+ }
728
+
729
+ private JSObject parseEnumerateScanners(Intent intent) {
730
+ JSArray scanners = new JSArray();
731
+ ArrayList<Bundle> bundles = extractBundleList(intent, ZebraDataWedge.RESULT_ENUMERATE_SCANNERS);
732
+ if (bundles != null && !bundles.isEmpty()) {
733
+ for (Bundle bundle : bundles) {
734
+ scanners.put(parseScannerBundle(bundle));
735
+ }
736
+ } else {
737
+ String[] legacyScanners = firstStringArray(intent, ZebraDataWedge.RESULT_ENUMERATED_SCANNER_LIST);
738
+ if (legacyScanners != null) {
739
+ for (String scanner : legacyScanners) {
740
+ scanners.put(parseLegacyScanner(scanner));
741
+ }
742
+ }
743
+ }
744
+ JSObject ret = new JSObject();
745
+ ret.put("scanners", scanners);
746
+ return ret;
747
+ }
748
+
749
+ private JSArray parsePluginConfigResult(ArrayList<Bundle> pluginConfigs) {
750
+ JSArray result = new JSArray();
751
+ if (pluginConfigs == null) {
752
+ return result;
753
+ }
754
+ for (Bundle config : pluginConfigs) {
755
+ if (config == null) {
756
+ continue;
757
+ }
758
+ JSObject item = new JSObject();
759
+ item.put("pluginName", config.getString("PLUGIN_NAME"));
760
+ item.put("outputPluginName", config.getString("OUTPUT_PLUGIN_NAME"));
761
+ item.put("resetConfig", "true".equalsIgnoreCase(config.getString("RESET_CONFIG")));
762
+ item.put("paramList", ZebraDataWedge.bundleToJSObject(config.getBundle("PARAM_LIST")));
763
+ result.put(item);
764
+ }
765
+ return result;
766
+ }
767
+
768
+ private JSArray parseAppListResult(ArrayList<Bundle> appList) {
769
+ JSArray result = new JSArray();
770
+ if (appList == null) {
771
+ return result;
772
+ }
773
+ for (Bundle app : appList) {
774
+ if (app == null) {
775
+ continue;
776
+ }
777
+ JSObject item = new JSObject();
778
+ item.put("packageName", app.getString("PACKAGE_NAME"));
779
+ item.put("activityList", ZebraDataWedge.stringArrayToJSArray(app.getStringArray("ACTIVITY_LIST")));
780
+ result.put(item);
781
+ }
782
+ return result;
783
+ }
784
+
785
+ private JSObject parseNotification(Intent intent) {
786
+ Bundle notification = intent.getBundleExtra(ZebraDataWedge.EXTRA_NOTIFICATION);
787
+ JSObject raw = ZebraDataWedge.bundleToJSObject(notification);
788
+ JSObject ret = new JSObject();
789
+ ret.put("notificationType", notification != null ? notification.getString("NOTIFICATION_TYPE") : null);
790
+ ret.put("profileName", notification != null ? notification.getString("PROFILE_NAME") : null);
791
+ ret.put("status", notification != null ? notification.getString("STATUS") : null);
792
+ ret.put("scannerStatus", notification != null ? notification.getString("SCANNER_STATUS") : null);
793
+ ret.put("raw", raw);
794
+ return ret;
795
+ }
796
+
797
+ private String requiredString(PluginCall call, String key) {
798
+ String value = call.getString(key);
799
+ if (value == null || value.isEmpty()) {
800
+ call.reject(key + " is required.");
801
+ return null;
802
+ }
803
+ return value;
804
+ }
805
+
806
+ private ArrayList<Bundle> parsePluginConfigs(JSONArray pluginConfigs) {
807
+ ArrayList<Bundle> bundles = new ArrayList<>();
808
+ for (int i = 0; i < pluginConfigs.length(); i++) {
809
+ JSONObject json = pluginConfigs.optJSONObject(i);
810
+ if (json == null) {
811
+ continue;
812
+ }
813
+ Bundle config = new Bundle();
814
+ config.putString("PLUGIN_NAME", json.optString("pluginName"));
815
+ config.putString("RESET_CONFIG", Boolean.toString(json.optBoolean("resetConfig", true)));
816
+ if (json.has("outputPluginName")) {
817
+ config.putString("OUTPUT_PLUGIN_NAME", json.optString("outputPluginName"));
818
+ }
819
+ JSONObject paramList = json.optJSONObject("paramList");
820
+ if (paramList != null) {
821
+ config.putBundle("PARAM_LIST", ZebraDataWedge.jsonToBundle(paramList));
822
+ }
823
+ bundles.add(config);
824
+ }
825
+ return bundles;
826
+ }
827
+
828
+ private Bundle[] parseAppList(JSONArray appList) {
829
+ List<Bundle> bundles = new ArrayList<>();
830
+ for (int i = 0; i < appList.length(); i++) {
831
+ JSONObject json = appList.optJSONObject(i);
832
+ if (json == null) {
833
+ continue;
834
+ }
835
+ Bundle app = new Bundle();
836
+ app.putString("PACKAGE_NAME", json.optString("packageName"));
837
+ app.putStringArray("ACTIVITY_LIST", ZebraDataWedge.jsonArrayToStringArray(json.optJSONArray("activityList")));
838
+ bundles.add(app);
839
+ }
840
+ return bundles.toArray(new Bundle[0]);
841
+ }
842
+
843
+ private ArrayList<Bundle> extractPluginConfig(Bundle bundle) {
844
+ ArrayList<Bundle> result = bundle.getParcelableArrayList("PLUGIN_CONFIG");
845
+ if (result != null) {
846
+ return result;
847
+ }
848
+ Bundle single = bundle.getBundle("PLUGIN_CONFIG");
849
+ if (single == null) {
850
+ return null;
851
+ }
852
+ ArrayList<Bundle> list = new ArrayList<>();
853
+ list.add(single);
854
+ return list;
855
+ }
856
+
857
+ private ArrayList<Bundle> extractAppList(Bundle bundle) {
858
+ Object raw = bundle.get("APP_LIST");
859
+ if (raw instanceof Bundle[]) {
860
+ Bundle[] values = (Bundle[]) raw;
861
+ ArrayList<Bundle> result = new ArrayList<>();
862
+ Collections.addAll(result, values);
863
+ return result;
864
+ }
865
+ if (raw instanceof ArrayList<?>) {
866
+ ArrayList<Bundle> result = new ArrayList<>();
867
+ for (Object value : (ArrayList<?>) raw) {
868
+ if (value instanceof Bundle) {
869
+ result.add((Bundle) value);
870
+ }
871
+ }
872
+ return result;
873
+ }
874
+ return null;
875
+ }
876
+
877
+ private ArrayList<Bundle> extractBundleList(Intent intent, String... keys) {
878
+ for (String key : keys) {
879
+ Object raw = intent.getExtras() != null ? intent.getExtras().get(key) : null;
880
+ if (raw instanceof ArrayList<?>) {
881
+ ArrayList<Bundle> result = new ArrayList<>();
882
+ for (Object value : (ArrayList<?>) raw) {
883
+ if (value instanceof Bundle) {
884
+ result.add((Bundle) value);
885
+ }
886
+ }
887
+ return result;
888
+ }
889
+ if (raw instanceof Bundle[]) {
890
+ ArrayList<Bundle> result = new ArrayList<>();
891
+ Collections.addAll(result, (Bundle[]) raw);
892
+ return result;
893
+ }
894
+ }
895
+ return null;
896
+ }
897
+
898
+ private Bundle firstBundle(Intent intent, String... keys) {
899
+ for (String key : keys) {
900
+ Bundle value = intent.getBundleExtra(key);
901
+ if (value != null) {
902
+ return value;
903
+ }
904
+ }
905
+ return null;
906
+ }
907
+
908
+ private String firstString(Intent intent, String... keys) {
909
+ for (String key : keys) {
910
+ String value = intent.getStringExtra(key);
911
+ if (value != null) {
912
+ return value;
913
+ }
914
+ }
915
+ return null;
916
+ }
917
+
918
+ private String[] firstStringArray(Intent intent, String... keys) {
919
+ for (String key : keys) {
920
+ String[] value = intent.getStringArrayExtra(key);
921
+ if (value != null) {
922
+ return value;
923
+ }
924
+ }
925
+ return null;
926
+ }
927
+
928
+ private JSObject parseScannerBundle(Bundle bundle) {
929
+ JSObject ret = new JSObject();
930
+ ret.put("index", bundle.getInt("SCANNER_INDEX"));
931
+ ret.put("name", bundle.getString("SCANNER_NAME"));
932
+ ret.put("id", bundle.getString("SCANNER_IDENTIFIER"));
933
+ ret.put(
934
+ "connectionState",
935
+ "true".equalsIgnoreCase(bundle.getString("SCANNER_CONNECTION_STATE")) || bundle.getBoolean("SCANNER_CONNECTION_STATE")
936
+ );
937
+ return ret;
938
+ }
939
+
940
+ private JSObject parseLegacyScanner(String scanner) {
941
+ JSObject ret = new JSObject();
942
+ ret.put("index", -1);
943
+ ret.put("name", scanner);
944
+ ret.put("id", scanner);
945
+ ret.put("connectionState", false);
946
+ return ret;
947
+ }
948
+
949
+ private interface ResponseParser {
950
+ JSObject parse(Intent intent) throws Exception;
951
+ }
952
+
953
+ private static class PendingRequest {
954
+
955
+ final PluginCall call;
956
+ final ResponseParser parser;
957
+ final Runnable timeoutRunnable;
958
+
959
+ PendingRequest(PluginCall call, ResponseParser parser, Runnable timeoutRunnable) {
960
+ this.call = call;
961
+ this.parser = parser;
962
+ this.timeoutRunnable = timeoutRunnable;
963
+ }
964
+ }
965
+
966
+ private static class ScanRequest {
967
+
968
+ final PluginCall call;
969
+ final Runnable timeoutRunnable;
970
+
971
+ ScanRequest(PluginCall call, Runnable timeoutRunnable) {
972
+ this.call = call;
973
+ this.timeoutRunnable = timeoutRunnable;
974
+ }
975
+ }
976
+
977
+ private static class ZebraDataWedgeException extends Exception {
978
+
979
+ private final String code;
980
+
981
+ ZebraDataWedgeException(String code, String message) {
982
+ super(message);
983
+ this.code = code;
984
+ }
985
+
986
+ public String getCode() {
987
+ return code;
988
+ }
989
+ }
990
+ }