@habibov77/cordova-plugin-mcc-mlkit-barcode-scanner-fixed 1.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,496 @@
1
+ package com.mcc.cordova.plugins.mlkit.barcode.scanner;
2
+
3
+ import android.Manifest;
4
+ import android.annotation.SuppressLint;
5
+ import android.content.DialogInterface;
6
+ import android.content.Intent;
7
+ import android.content.pm.PackageManager;
8
+ import android.graphics.Bitmap;
9
+ import android.graphics.Canvas;
10
+ import android.graphics.Color;
11
+ import android.graphics.Paint;
12
+ import android.graphics.PixelFormat;
13
+ import android.graphics.PorterDuff;
14
+ import android.graphics.RectF;
15
+ import android.os.Bundle;
16
+ import android.os.Handler;
17
+ import android.os.Looper;
18
+
19
+ import android.view.GestureDetector;
20
+ import android.view.MotionEvent;
21
+ import android.view.ScaleGestureDetector;
22
+ import android.view.SurfaceHolder;
23
+ import android.view.SurfaceView;
24
+ import android.view.View;
25
+ import android.widget.ImageButton;
26
+
27
+ import androidx.annotation.NonNull;
28
+ import androidx.appcompat.app.AlertDialog;
29
+ import androidx.appcompat.app.AppCompatActivity;
30
+ import androidx.camera.core.AspectRatio;
31
+ import androidx.camera.core.Camera;
32
+ import androidx.camera.core.CameraSelector;
33
+ import androidx.camera.core.ImageAnalysis;
34
+ import androidx.camera.core.ImageProxy;
35
+ import androidx.camera.core.Preview;
36
+ import androidx.camera.lifecycle.ProcessCameraProvider;
37
+ import androidx.camera.view.PreviewView;
38
+ import androidx.core.app.ActivityCompat;
39
+ import androidx.core.content.ContextCompat;
40
+ import androidx.lifecycle.LifecycleOwner;
41
+ import androidx.lifecycle.LiveData;
42
+
43
+ import com.google.android.gms.common.api.CommonStatusCodes;
44
+ import com.google.android.gms.tasks.OnCompleteListener;
45
+ import com.google.android.gms.tasks.OnFailureListener;
46
+ import com.google.android.gms.tasks.OnSuccessListener;
47
+ import com.google.android.gms.tasks.Task;
48
+ import com.google.android.material.snackbar.Snackbar;
49
+ import com.google.common.util.concurrent.ListenableFuture;
50
+ import com.google.mlkit.vision.barcode.common.Barcode;
51
+ import com.google.mlkit.vision.barcode.BarcodeScanner;
52
+ import com.google.mlkit.vision.barcode.BarcodeScannerOptions;
53
+ import com.google.mlkit.vision.barcode.BarcodeScanning;
54
+ import com.google.mlkit.vision.common.InputImage;
55
+ import com.mcc.cordova.plugins.mlkit.barcode.scanner.utils.BitmapUtils;
56
+
57
+ import java.nio.charset.StandardCharsets;
58
+ import java.util.List;
59
+ import java.util.concurrent.ExecutionException;
60
+ import java.util.concurrent.ExecutorService;
61
+ import java.util.concurrent.Executors;
62
+
63
+ public class CaptureActivity extends AppCompatActivity implements SurfaceHolder.Callback {
64
+
65
+ public Integer BarcodeFormats;
66
+ public double DetectorSize = .5;
67
+
68
+ public static final String BarcodeFormat = "MLKitBarcodeFormat";
69
+ public static final String BarcodeType = "MLKitBarcodeType";
70
+ public static final String BarcodeValue = "MLKitBarcodeValue";
71
+
72
+ private ListenableFuture<ProcessCameraProvider> cameraProviderFuture;
73
+ private ExecutorService executor = Executors.newSingleThreadExecutor();
74
+ private PreviewView mCameraView;
75
+ private SurfaceHolder holder;
76
+ private SurfaceView surfaceView;
77
+ private Canvas canvas;
78
+ private Paint paint;
79
+
80
+ private static final int RC_HANDLE_CAMERA_PERM = 2;
81
+ private ImageButton _TorchButton;
82
+ private Camera camera;
83
+
84
+ private ScaleGestureDetector _ScaleGestureDetector;
85
+ private GestureDetector _GestureDetector;
86
+ private Handler timeoutHandler = new Handler(Looper.getMainLooper());
87
+ private Runnable timeoutRunnable;
88
+ private boolean hasFinished = false;
89
+
90
+ @Override
91
+ protected void onCreate(Bundle savedInstanceState) {
92
+ super.onCreate(savedInstanceState);
93
+ setContentView(getResources().getIdentifier("capture_activity", "layout", getPackageName()));
94
+
95
+ // Create the bounding box
96
+ surfaceView = findViewById(getResources().getIdentifier("overlay", "id", getPackageName()));
97
+ surfaceView.setZOrderOnTop(true);
98
+
99
+ holder = surfaceView.getHolder();
100
+ holder.setFormat(PixelFormat.TRANSPARENT);
101
+ holder.addCallback(this);
102
+
103
+ // read parameters from the intent used to launch the activity.
104
+ BarcodeFormats = getIntent().getIntExtra("BarcodeFormats", 1234);
105
+ DetectorSize = getIntent().getDoubleExtra("DetectorSize", .5);
106
+ long scanTimeoutMs = getIntent().getLongExtra("ScanTimeoutMs", 0);
107
+
108
+ if (scanTimeoutMs > 0) {
109
+ timeoutRunnable = () -> finishWithError("SCAN_TIMEOUT");
110
+ timeoutHandler.postDelayed(timeoutRunnable, scanTimeoutMs);
111
+ }
112
+
113
+ if (DetectorSize <= 0 || DetectorSize >= 1) { // setting boundary detectorSize must be between 0 to 1.
114
+ DetectorSize = 0.5;
115
+ }
116
+
117
+ int rc = ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA);
118
+
119
+ if (rc == PackageManager.PERMISSION_GRANTED) {
120
+ // Start Camera
121
+ startCamera();
122
+ } else {
123
+ requestCameraPermission();
124
+ }
125
+
126
+ _GestureDetector = new GestureDetector(this, new CaptureGestureListener());
127
+ _ScaleGestureDetector = new ScaleGestureDetector(this, new ScaleListener());
128
+
129
+ _TorchButton = findViewById(getResources().getIdentifier("torch_button", "id", this.getPackageName()));
130
+
131
+ _TorchButton.setOnClickListener(new View.OnClickListener() {
132
+ @Override
133
+ public void onClick(View v) {
134
+
135
+ LiveData<Integer> flashState = camera.getCameraInfo().getTorchState();
136
+ if (flashState.getValue() != null) {
137
+ boolean state = flashState.getValue() == 1;
138
+ _TorchButton.setBackgroundResource(getResources().getIdentifier(!state ? "torch_active" : "torch_inactive",
139
+ "drawable", CaptureActivity.this.getPackageName()));
140
+ camera.getCameraControl().enableTorch(!state);
141
+ }
142
+
143
+ }
144
+ });
145
+
146
+ }
147
+
148
+ // ----------------------------------------------------------------------------
149
+ // | Helper classes
150
+ // ----------------------------------------------------------------------------
151
+ private class CaptureGestureListener extends GestureDetector.SimpleOnGestureListener {
152
+ @Override
153
+ public boolean onSingleTapConfirmed(MotionEvent e) {
154
+ return super.onSingleTapConfirmed(e);
155
+ }
156
+ }
157
+
158
+ private class ScaleListener implements ScaleGestureDetector.OnScaleGestureListener {
159
+ @Override
160
+ public boolean onScale(ScaleGestureDetector detector) {
161
+ return false;
162
+ }
163
+
164
+ @Override
165
+ public boolean onScaleBegin(ScaleGestureDetector detector) {
166
+ return true;
167
+ }
168
+
169
+ @Override
170
+ public void onScaleEnd(ScaleGestureDetector detector) {
171
+
172
+ if (camera != null) {
173
+ float scale = camera.getCameraInfo().getZoomState().getValue().getZoomRatio() * detector.getScaleFactor();
174
+ camera.getCameraControl().setZoomRatio(scale);
175
+ }
176
+ }
177
+ }
178
+
179
+ private void requestCameraPermission() {
180
+
181
+ final String[] permissions = new String[] { Manifest.permission.CAMERA,
182
+ Manifest.permission.WRITE_EXTERNAL_STORAGE };
183
+
184
+ boolean shouldShowPermission = !ActivityCompat.shouldShowRequestPermissionRationale(this,
185
+ Manifest.permission.CAMERA);
186
+ shouldShowPermission = shouldShowPermission
187
+ && !ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
188
+
189
+ if (shouldShowPermission) {
190
+ ActivityCompat.requestPermissions(this, permissions, RC_HANDLE_CAMERA_PERM);
191
+ return;
192
+ }
193
+
194
+ View.OnClickListener listener = new View.OnClickListener() {
195
+ @Override
196
+ public void onClick(View view) {
197
+ ActivityCompat.requestPermissions(CaptureActivity.this, permissions, RC_HANDLE_CAMERA_PERM);
198
+ }
199
+ };
200
+
201
+ findViewById(getResources().getIdentifier("topLayout", "id", getPackageName())).setOnClickListener(listener);
202
+ Snackbar
203
+ .make(surfaceView, getResources().getIdentifier("permission_camera_rationale", "string", getPackageName()),
204
+ Snackbar.LENGTH_INDEFINITE)
205
+ .setAction(getResources().getIdentifier("ok", "string", getPackageName()), listener).show();
206
+
207
+ }
208
+
209
+ @Override
210
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
211
+ if (requestCode != RC_HANDLE_CAMERA_PERM) {
212
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
213
+ return;
214
+ }
215
+
216
+ if (grantResults.length != 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
217
+ startCamera();
218
+ DrawFocusRect(Color.parseColor("#FFFFFF"));
219
+ return;
220
+ }
221
+
222
+ DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
223
+ public void onClick(DialogInterface dialog, int id) {
224
+ finish();
225
+ }
226
+ };
227
+
228
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
229
+ builder.setTitle("Camera permission required")
230
+ .setMessage(getResources().getIdentifier("no_camera_permission", "string", getPackageName()))
231
+ .setPositiveButton(getResources().getIdentifier("ok", "string", getPackageName()), listener).show();
232
+ }
233
+
234
+ @Override
235
+ public void surfaceCreated(SurfaceHolder surfaceHolder) {
236
+
237
+ }
238
+
239
+ @Override
240
+ public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
241
+ DrawFocusRect(Color.parseColor("#FFFFFF"));
242
+ }
243
+
244
+ @Override
245
+ public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
246
+
247
+ }
248
+
249
+ @Override
250
+ public boolean onTouchEvent(MotionEvent e) {
251
+ boolean b = _ScaleGestureDetector.onTouchEvent(e);
252
+ boolean c = _GestureDetector.onTouchEvent(e);
253
+
254
+ return b || c || super.onTouchEvent(e);
255
+ }
256
+
257
+ @Override
258
+ public void onBackPressed() {
259
+ finishWithError("USER_CANCELLED");
260
+ }
261
+
262
+ @Override
263
+ protected void onDestroy() {
264
+ if (timeoutRunnable != null) {
265
+ timeoutHandler.removeCallbacks(timeoutRunnable);
266
+ }
267
+ super.onDestroy();
268
+ }
269
+
270
+ private void finishWithError(String err) {
271
+ if (hasFinished) {
272
+ return;
273
+ }
274
+ hasFinished = true;
275
+ if (timeoutRunnable != null) {
276
+ timeoutHandler.removeCallbacks(timeoutRunnable);
277
+ }
278
+
279
+ Intent data = new Intent();
280
+ data.putExtra("err", err);
281
+ setResult(CommonStatusCodes.CANCELED, data);
282
+ finish();
283
+ }
284
+
285
+ private void finishWithSuccess(Intent data) {
286
+ if (hasFinished) {
287
+ return;
288
+ }
289
+ hasFinished = true;
290
+ if (timeoutRunnable != null) {
291
+ timeoutHandler.removeCallbacks(timeoutRunnable);
292
+ }
293
+ setResult(CommonStatusCodes.SUCCESS, data);
294
+ finish();
295
+ }
296
+
297
+ @Override
298
+ protected void onPause() {
299
+ super.onPause();
300
+
301
+ }
302
+
303
+ @Override
304
+ protected void onResume() {
305
+ super.onResume();
306
+
307
+ }
308
+
309
+ void startCamera() {
310
+ mCameraView = findViewById(getResources().getIdentifier("previewView", "id", getPackageName()));
311
+ mCameraView.setImplementationMode(PreviewView.ImplementationMode.COMPATIBLE);
312
+
313
+ Boolean rotateCamera = getIntent().getBooleanExtra("RotateCamera", false);
314
+ if (rotateCamera) {
315
+ mCameraView.setScaleX(-1F);
316
+ mCameraView.setScaleY(-1F);
317
+ } else {
318
+ mCameraView.setScaleX(1F);
319
+ mCameraView.setScaleY(1F);
320
+ }
321
+
322
+ // mCameraView.setScaleType(PreviewView.ScaleType.FIT_CENTER);
323
+
324
+ cameraProviderFuture = ProcessCameraProvider.getInstance(this);
325
+ cameraProviderFuture.addListener(new Runnable() {
326
+ @Override
327
+ public void run() {
328
+ try {
329
+ ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
330
+ CaptureActivity.this.bindPreview(cameraProvider);
331
+
332
+ } catch (ExecutionException | InterruptedException e) {
333
+ // No errors need to be handled for this Future.
334
+ // This should never be reached.
335
+ }
336
+ }
337
+ }, ContextCompat.getMainExecutor(this));
338
+ }
339
+
340
+ /**
341
+ * Binding to camera
342
+ */
343
+ private void bindPreview(ProcessCameraProvider cameraProvider) {
344
+
345
+ int barcodeFormat;
346
+ if (BarcodeFormats == 0 || BarcodeFormats == 1234) {
347
+ barcodeFormat = (Barcode.FORMAT_CODE_39 | Barcode.FORMAT_DATA_MATRIX);
348
+ } else {
349
+ barcodeFormat = BarcodeFormats;
350
+ }
351
+
352
+ Preview preview = new Preview.Builder().build();
353
+
354
+ CameraSelector cameraSelector = new CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK)
355
+ .build();
356
+
357
+ preview.setSurfaceProvider(mCameraView.getSurfaceProvider());
358
+
359
+ ImageAnalysis imageAnalysis = new ImageAnalysis.Builder()
360
+ .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST).setTargetAspectRatio(AspectRatio.RATIO_16_9)
361
+ .build();
362
+
363
+ BarcodeScanner scanner = BarcodeScanning
364
+ .getClient(new BarcodeScannerOptions.Builder().setBarcodeFormats(barcodeFormat).build());
365
+
366
+ imageAnalysis.setAnalyzer(executor, new ImageAnalysis.Analyzer() {
367
+ @SuppressLint("UnsafeExperimentalUsageError")
368
+ @Override
369
+ public void analyze(@NonNull ImageProxy image) {
370
+
371
+ if (image == null || image.getImage() == null) {
372
+ return;
373
+ }
374
+
375
+ Bitmap bmp = BitmapUtils.getBitmap(image);
376
+
377
+ int height = bmp.getHeight();
378
+ int width = bmp.getWidth();
379
+
380
+ int left, right, top, bottom, diameter, boxHeight, boxWidth;
381
+
382
+ diameter = width;
383
+ if (height < width) {
384
+ diameter = height;
385
+ }
386
+
387
+ int offset = (int) ((1 - DetectorSize) * diameter);
388
+ diameter -= offset;
389
+
390
+ left = width / 2 - diameter / 2;
391
+ top = height / 2 - diameter / 2;
392
+ right = width / 2 + diameter / 2;
393
+ bottom = height / 2 + diameter / 2;
394
+
395
+ boxHeight = bottom - top;
396
+ boxWidth = right - left;
397
+
398
+ Bitmap bitmap = Bitmap.createBitmap(bmp, left, top, boxWidth, boxHeight);
399
+ scanner.process(InputImage.fromBitmap(bitmap, image.getImageInfo().getRotationDegrees()))
400
+ .addOnSuccessListener(new OnSuccessListener<List<Barcode>>() {
401
+ @Override
402
+ public void onSuccess(List<Barcode> barCodes) {
403
+
404
+ // # Code to test image viewfinder
405
+ /*
406
+ * ImageView imageView = (ImageView)
407
+ * findViewById(getResources().getIdentifier("imageView", "id",
408
+ * getPackageName())); imageView.setImageBitmap(bitmap);
409
+ */
410
+
411
+ if (barCodes.size() > 0) {
412
+ for (Barcode barcode : barCodes) {
413
+ // Toast.makeText(CaptureActivity.this, "FOUND: " + barcode.getDisplayValue(),
414
+ // Toast.LENGTH_SHORT).show();
415
+ Intent data = new Intent();
416
+ String value = barcode.getRawValue();
417
+
418
+ // rawValue returns null if string is not UTF-8 encoded.
419
+ // If that's the case, we will decode it as ASCII,
420
+ // because it's the most common encoding for barcodes.
421
+ // e.g. https://www.barcodefaq.com/1d/code-128/
422
+ if (barcode.getRawValue() == null) {
423
+ value = new String(barcode.getRawBytes(), StandardCharsets.US_ASCII);
424
+ }
425
+
426
+ data.putExtra(BarcodeFormat, barcode.getFormat());
427
+ data.putExtra(BarcodeType, barcode.getValueType());
428
+ data.putExtra(BarcodeValue, value);
429
+ finishWithSuccess(data);
430
+
431
+ }
432
+ }
433
+ }
434
+ }).addOnFailureListener(new OnFailureListener() {
435
+ @Override
436
+ public void onFailure(@NonNull Exception e) {
437
+
438
+ }
439
+ }).addOnCompleteListener(new OnCompleteListener<List<Barcode>>() {
440
+ @Override
441
+ public void onComplete(@NonNull Task<List<Barcode>> task) {
442
+ image.close();
443
+ }
444
+ });
445
+ }
446
+
447
+ });
448
+
449
+ camera = cameraProvider.bindToLifecycle((LifecycleOwner) this, cameraSelector, imageAnalysis, preview);
450
+ }
451
+
452
+ /**
453
+ * For drawing the rectangular box
454
+ */
455
+ private void DrawFocusRect(int color) {
456
+
457
+ if (mCameraView != null) {
458
+ int height = mCameraView.getHeight();
459
+ int width = mCameraView.getWidth();
460
+
461
+ int left, right, top, bottom, diameter;
462
+
463
+ diameter = width;
464
+ if (height < width) {
465
+ diameter = height;
466
+ }
467
+
468
+ int offset = (int) ((1 - DetectorSize) * diameter);
469
+ diameter -= offset;
470
+
471
+ canvas = holder.lockCanvas();
472
+ canvas.drawColor(0, PorterDuff.Mode.CLEAR);
473
+ // border's properties
474
+ paint = new Paint();
475
+ paint.setStyle(Paint.Style.STROKE);
476
+ paint.setColor(color);
477
+ paint.setStrokeWidth(5);
478
+
479
+ left = width / 2 - diameter / 2;
480
+ top = height / 2 - diameter / 2;
481
+ right = width / 2 + diameter / 2;
482
+ bottom = height / 2 + diameter / 2;
483
+
484
+ // Changing the value of x in diameter/x will change the size of the box ;
485
+ // inversely proportionate to x
486
+ if (DetectorSize <= 0.3) {
487
+ canvas.drawRect(new RectF(left, top, right, bottom), paint);
488
+ } else {
489
+ canvas.drawRoundRect(new RectF(left, top, right, bottom), 100, 100, paint);
490
+ }
491
+
492
+ holder.unlockCanvasAndPost(canvas);
493
+ }
494
+
495
+ }
496
+ }
@@ -0,0 +1,183 @@
1
+ package com.mcc.cordova.plugins.mlkit.barcode.scanner;
2
+
3
+ import android.app.Activity;
4
+ import android.app.AlertDialog;
5
+ import android.content.Context;
6
+ import android.content.DialogInterface;
7
+ import android.content.Intent;
8
+ import android.content.pm.PackageManager;
9
+ import android.content.res.AssetFileDescriptor;
10
+ import android.hardware.camera2.CameraManager;
11
+ import android.media.MediaPlayer;
12
+ import android.os.Build;
13
+ import android.os.Bundle;
14
+ import android.os.VibrationEffect;
15
+ import android.os.Vibrator;
16
+ import android.util.Log;
17
+
18
+ import com.google.android.gms.common.api.CommonStatusCodes;
19
+
20
+ import org.apache.cordova.CallbackContext;
21
+ import org.apache.cordova.CordovaInterface;
22
+ import org.apache.cordova.CordovaPlugin;
23
+ import org.apache.cordova.CordovaWebView;
24
+ import org.apache.cordova.PluginResult;
25
+ import org.json.JSONArray;
26
+ import org.json.JSONException;
27
+ import org.json.JSONObject;
28
+
29
+ import java.io.IOException;
30
+
31
+ /**
32
+ * This class echoes a string called from JavaScript.
33
+ */
34
+ public class MLKitBarcodeScanner extends CordovaPlugin {
35
+
36
+ private static final int RC_BARCODE_CAPTURE = 9001;
37
+ private CallbackContext _CallbackContext;
38
+ private Boolean _BeepOnSuccess;
39
+ private Boolean _VibrateOnSuccess;
40
+ private MediaPlayer _MediaPlayer;
41
+ private Vibrator _Vibrator;
42
+
43
+ public void initialize(CordovaInterface cordova, CordovaWebView webView) {
44
+ super.initialize(cordova, webView);
45
+
46
+ Context context = cordova.getContext();
47
+
48
+ _Vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
49
+ _MediaPlayer = new MediaPlayer();
50
+
51
+ try {
52
+ AssetFileDescriptor descriptor = context.getAssets().openFd("beep.ogg");
53
+ _MediaPlayer.setDataSource(descriptor.getFileDescriptor(), descriptor.getStartOffset(), descriptor.getLength());
54
+ descriptor.close();
55
+ _MediaPlayer.prepare();
56
+ } catch (IOException e) {
57
+ e.printStackTrace();
58
+ }
59
+ }
60
+
61
+ @Override
62
+ public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
63
+ Activity activity = cordova.getActivity();
64
+ Boolean hasCamera = activity.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY);
65
+ CameraManager cameraManager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
66
+
67
+ _CallbackContext = callbackContext;
68
+
69
+ int numberOfCameras = 0;
70
+
71
+ try {
72
+ numberOfCameras = cameraManager.getCameraIdList().length;
73
+ } catch (Exception e) {
74
+ e.printStackTrace();
75
+ }
76
+
77
+ if (!hasCamera || numberOfCameras == 0) {
78
+ AlertDialog alertDialog = new AlertDialog.Builder(activity).create();
79
+ alertDialog.setMessage(activity.getString(activity.getResources()
80
+ .getIdentifier("no_cameras_found", "string", activity.getPackageName())));
81
+ alertDialog.setButton(
82
+ AlertDialog.BUTTON_POSITIVE, activity.getString(activity.getResources()
83
+ .getIdentifier("ok", "string", activity.getPackageName())),
84
+ new DialogInterface.OnClickListener() {
85
+ public void onClick(DialogInterface dialog, int which) {
86
+ dialog.dismiss();
87
+ }
88
+ });
89
+ alertDialog.show();
90
+ return false;
91
+ }
92
+
93
+ if (action.equals("startScan")) {
94
+ class OneShotTask implements Runnable {
95
+ private final Context context;
96
+ private final JSONArray args;
97
+
98
+ private OneShotTask(Context ctx, JSONArray as) {
99
+ context = ctx;
100
+ args = as;
101
+ }
102
+
103
+ public void run() {
104
+ try {
105
+ openNewActivity(context, args);
106
+ } catch (JSONException e) {
107
+ _CallbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, e.toString()));
108
+ }
109
+ }
110
+ }
111
+ Thread t = new Thread(new OneShotTask(cordova.getContext(), args));
112
+ t.start();
113
+ return true;
114
+ }
115
+ return false;
116
+ }
117
+
118
+ private void openNewActivity(Context context, JSONArray args) throws JSONException {
119
+ JSONObject config = args.getJSONObject(0);
120
+ Intent intent = new Intent(context, CaptureActivity.class);
121
+ intent.putExtra("BarcodeFormats", config.optInt("barcodeFormats", 1234));
122
+ intent.putExtra("DetectorSize", config.optDouble("detectorSize", 0.5));
123
+ intent.putExtra("RotateCamera", config.optBoolean("rotateCamera", false));
124
+ intent.putExtra("ScanTimeoutMs", config.optLong("timeoutMs", 0));
125
+
126
+ _BeepOnSuccess = config.optBoolean("beepOnSuccess", false);
127
+ _VibrateOnSuccess = config.optBoolean("vibrateOnSuccess", false);
128
+
129
+ this.cordova.setActivityResultCallback(this);
130
+ this.cordova.startActivityForResult(this, intent, RC_BARCODE_CAPTURE);
131
+ }
132
+
133
+ @Override
134
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
135
+ super.onActivityResult(requestCode, resultCode, data);
136
+
137
+ if (requestCode == RC_BARCODE_CAPTURE) {
138
+ if (resultCode == CommonStatusCodes.SUCCESS) {
139
+ if (data != null) {
140
+ Integer barcodeFormat = data.getIntExtra(CaptureActivity.BarcodeFormat, 0);
141
+ Integer barcodeType = data.getIntExtra(CaptureActivity.BarcodeType, 0);
142
+ String barcodeValue = data.getStringExtra(CaptureActivity.BarcodeValue);
143
+ JSONArray result = new JSONArray();
144
+ result.put(barcodeValue);
145
+ result.put(barcodeFormat);
146
+ result.put(barcodeType);
147
+ _CallbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, result));
148
+
149
+ if (_BeepOnSuccess) {
150
+ _MediaPlayer.start();
151
+ }
152
+
153
+ if (_VibrateOnSuccess) {
154
+ Integer duration = 200;
155
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
156
+ _Vibrator.vibrate(VibrationEffect.createOneShot(duration, VibrationEffect.DEFAULT_AMPLITUDE));
157
+ } else {
158
+ // deprecated in API 26 aka Oreo
159
+ _Vibrator.vibrate(duration);
160
+ }
161
+ }
162
+
163
+ Log.d("MLKitBarcodeScanner", "Barcode read: " + barcodeValue);
164
+ }
165
+ } else {
166
+ String err = "USER_CANCELLED";
167
+ if (data != null && data.hasExtra("err")) {
168
+ err = data.getStringExtra("err");
169
+ }
170
+ JSONArray result = new JSONArray();
171
+ result.put(err);
172
+ result.put("");
173
+ result.put("");
174
+ _CallbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, result));
175
+ }
176
+ }
177
+ }
178
+
179
+ @Override
180
+ public void onRestoreStateForActivityResult(Bundle state, CallbackContext callbackContext) {
181
+ _CallbackContext = callbackContext;
182
+ }
183
+ }