capacitor-camera-module 0.0.33 → 0.0.35
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.
|
@@ -15,7 +15,6 @@ import com.getcapacitor.annotation.PermissionCallback;
|
|
|
15
15
|
|
|
16
16
|
import android.view.ViewGroup;
|
|
17
17
|
import android.widget.FrameLayout;
|
|
18
|
-
import androidx.appcompat.app.AppCompatActivity;
|
|
19
18
|
import androidx.core.content.ContextCompat;
|
|
20
19
|
import androidx.camera.core.CameraSelector;
|
|
21
20
|
import androidx.camera.core.Preview;
|
|
@@ -67,7 +66,11 @@ import com.google.mlkit.vision.barcode.common.Barcode;
|
|
|
67
66
|
import com.google.mlkit.vision.barcode.BarcodeScanner;
|
|
68
67
|
import com.google.mlkit.vision.barcode.BarcodeScanning;
|
|
69
68
|
|
|
69
|
+
import android.graphics.YuvImage;
|
|
70
|
+
import android.graphics.Rect;
|
|
71
|
+
import java.util.concurrent.Executors;
|
|
70
72
|
|
|
73
|
+
import java.util.concurrent.ExecutorService;
|
|
71
74
|
|
|
72
75
|
|
|
73
76
|
@CapacitorPlugin(
|
|
@@ -92,7 +95,6 @@ public class CameraModulePlugin extends Plugin {
|
|
|
92
95
|
|
|
93
96
|
private PreviewView previewView;
|
|
94
97
|
private ProcessCameraProvider cameraProvider;
|
|
95
|
-
private CameraSelector cameraSelector;
|
|
96
98
|
|
|
97
99
|
private Camera camera;
|
|
98
100
|
|
|
@@ -101,12 +103,17 @@ public class CameraModulePlugin extends Plugin {
|
|
|
101
103
|
|
|
102
104
|
private ImageCapture imageCapture;
|
|
103
105
|
|
|
104
|
-
private PluginCall pendingCaptureCall;
|
|
105
|
-
|
|
106
106
|
private ImageAnalysis imageAnalysis;
|
|
107
107
|
private boolean isScanning = false;
|
|
108
108
|
private PluginCall scanCall;
|
|
109
109
|
|
|
110
|
+
private CameraSelector cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA;
|
|
111
|
+
|
|
112
|
+
private BarcodeScanner barcodeScanner;
|
|
113
|
+
|
|
114
|
+
private final ExecutorService barcodeExecutor = Executors.newSingleThreadExecutor();
|
|
115
|
+
|
|
116
|
+
|
|
110
117
|
|
|
111
118
|
@Override
|
|
112
119
|
public void load() {
|
|
@@ -236,6 +243,12 @@ public class CameraModulePlugin extends Plugin {
|
|
|
236
243
|
@PluginMethod
|
|
237
244
|
public void startPreview(PluginCall call) {
|
|
238
245
|
getActivity().runOnUiThread(() -> {
|
|
246
|
+
|
|
247
|
+
if (previewView != null) {
|
|
248
|
+
call.resolve();
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
|
|
239
252
|
previewView = new PreviewView(getContext());
|
|
240
253
|
previewView.setLayoutParams(
|
|
241
254
|
new FrameLayout.LayoutParams(
|
|
@@ -269,7 +282,7 @@ public class CameraModulePlugin extends Plugin {
|
|
|
269
282
|
.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
|
|
270
283
|
.build();
|
|
271
284
|
|
|
272
|
-
|
|
285
|
+
|
|
273
286
|
|
|
274
287
|
cameraProvider.unbindAll();
|
|
275
288
|
|
|
@@ -306,6 +319,11 @@ public class CameraModulePlugin extends Plugin {
|
|
|
306
319
|
previewView = null;
|
|
307
320
|
}
|
|
308
321
|
|
|
322
|
+
if (barcodeScanner != null) {
|
|
323
|
+
barcodeScanner.close();
|
|
324
|
+
barcodeScanner = null;
|
|
325
|
+
}
|
|
326
|
+
|
|
309
327
|
call.resolve();
|
|
310
328
|
});
|
|
311
329
|
}
|
|
@@ -355,6 +373,10 @@ public class CameraModulePlugin extends Plugin {
|
|
|
355
373
|
return;
|
|
356
374
|
}
|
|
357
375
|
|
|
376
|
+
if (savedCall != null) {
|
|
377
|
+
call.reject("Gallery already open");
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
358
380
|
savedCall = call;
|
|
359
381
|
|
|
360
382
|
Intent intent = new Intent(
|
|
@@ -404,11 +426,19 @@ public class CameraModulePlugin extends Plugin {
|
|
|
404
426
|
float ratio = (float) width / height;
|
|
405
427
|
|
|
406
428
|
if (width > height) {
|
|
407
|
-
if (width <= maxSize)
|
|
429
|
+
if (width <= maxSize && height <= maxSize) {
|
|
430
|
+
Bitmap.Config config =
|
|
431
|
+
bitmap.getConfig() != null ? bitmap.getConfig() : Bitmap.Config.ARGB_8888;
|
|
432
|
+
return bitmap.copy(config, false);
|
|
433
|
+
}
|
|
408
434
|
width = maxSize;
|
|
409
435
|
height = Math.round(width / ratio);
|
|
410
436
|
} else {
|
|
411
|
-
if (height <= maxSize)
|
|
437
|
+
if (height <= maxSize && width <= maxSize) {
|
|
438
|
+
Bitmap.Config config =
|
|
439
|
+
bitmap.getConfig() != null ? bitmap.getConfig() : Bitmap.Config.ARGB_8888;
|
|
440
|
+
return bitmap.copy(config, false);
|
|
441
|
+
}
|
|
412
442
|
height = maxSize;
|
|
413
443
|
width = Math.round(height * ratio);
|
|
414
444
|
}
|
|
@@ -548,107 +578,63 @@ public class CameraModulePlugin extends Plugin {
|
|
|
548
578
|
return;
|
|
549
579
|
}
|
|
550
580
|
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
Base64.encodeToString(
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
581
|
+
try {
|
|
582
|
+
File photoFile = File.createTempFile(
|
|
583
|
+
"photo_",
|
|
584
|
+
".jpg",
|
|
585
|
+
getContext().getCacheDir()
|
|
586
|
+
);
|
|
587
|
+
|
|
588
|
+
ImageCapture.OutputFileOptions options =
|
|
589
|
+
new ImageCapture.OutputFileOptions.Builder(photoFile).build();
|
|
590
|
+
|
|
591
|
+
imageCapture.takePicture(
|
|
592
|
+
options,
|
|
593
|
+
ContextCompat.getMainExecutor(getContext()),
|
|
594
|
+
new ImageCapture.OnImageSavedCallback() {
|
|
595
|
+
|
|
596
|
+
@Override
|
|
597
|
+
public void onImageSaved(
|
|
598
|
+
@NonNull ImageCapture.OutputFileResults output
|
|
599
|
+
) {
|
|
600
|
+
try {
|
|
601
|
+
Bitmap bitmap = BitmapFactory.decodeFile(photoFile.getAbsolutePath());
|
|
602
|
+
Bitmap resized = resizeBitmap(bitmap, 1024);
|
|
603
|
+
|
|
604
|
+
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
|
605
|
+
resized.compress(Bitmap.CompressFormat.JPEG, 80, out);
|
|
606
|
+
|
|
607
|
+
String base64 = Base64.encodeToString(
|
|
608
|
+
out.toByteArray(),
|
|
609
|
+
Base64.NO_WRAP
|
|
610
|
+
);
|
|
611
|
+
|
|
612
|
+
bitmap.recycle();
|
|
613
|
+
resized.recycle();
|
|
614
|
+
photoFile.delete();
|
|
615
|
+
|
|
616
|
+
JSObject ret = new JSObject();
|
|
617
|
+
ret.put("base64", base64);
|
|
618
|
+
ret.put("mimeType", "image/jpeg");
|
|
619
|
+
call.resolve(ret);
|
|
620
|
+
|
|
621
|
+
} catch (Exception e) {
|
|
622
|
+
call.reject("Error processing image", e);
|
|
623
|
+
}
|
|
589
624
|
}
|
|
590
|
-
}
|
|
591
625
|
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
call.reject("Capture failed", exception);
|
|
626
|
+
@Override
|
|
627
|
+
public void onError(@NonNull ImageCaptureException exception) {
|
|
628
|
+
call.reject("Capture failed", exception);
|
|
629
|
+
}
|
|
597
630
|
}
|
|
598
|
-
|
|
599
|
-
);
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
private Bitmap imageProxyToBitmap(ImageProxy image) {
|
|
603
|
-
ImageProxy.PlaneProxy[] planes = image.getPlanes();
|
|
604
|
-
ByteBuffer buffer = planes[0].getBuffer();
|
|
605
|
-
byte[] bytes = new byte[buffer.remaining()];
|
|
606
|
-
buffer.get(bytes);
|
|
607
|
-
|
|
608
|
-
return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
private Bitmap rotateBitmap(Bitmap bitmap, int rotationDegrees) {
|
|
613
|
-
if (rotationDegrees == 0) return bitmap;
|
|
614
|
-
|
|
615
|
-
Matrix matrix = new Matrix();
|
|
616
|
-
matrix.postRotate(rotationDegrees);
|
|
617
|
-
|
|
618
|
-
return Bitmap.createBitmap(
|
|
619
|
-
bitmap,
|
|
620
|
-
0,
|
|
621
|
-
0,
|
|
622
|
-
bitmap.getWidth(),
|
|
623
|
-
bitmap.getHeight(),
|
|
624
|
-
matrix,
|
|
625
|
-
true
|
|
626
|
-
);
|
|
627
|
-
}
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
private Bitmap mirrorBitmap(Bitmap bitmap) {
|
|
632
|
-
Matrix matrix = new Matrix();
|
|
633
|
-
matrix.preScale(-1, 1);
|
|
631
|
+
);
|
|
634
632
|
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
0,
|
|
639
|
-
bitmap.getWidth(),
|
|
640
|
-
bitmap.getHeight(),
|
|
641
|
-
matrix,
|
|
642
|
-
true
|
|
643
|
-
);
|
|
633
|
+
} catch (Exception e) {
|
|
634
|
+
call.reject("Error creating file", e);
|
|
635
|
+
}
|
|
644
636
|
}
|
|
645
637
|
|
|
646
|
-
private String bitmapToBase64(Bitmap bitmap) {
|
|
647
|
-
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
|
648
|
-
bitmap.compress(Bitmap.CompressFormat.JPEG, 80, outputStream);
|
|
649
|
-
byte[] bytes = outputStream.toByteArray();
|
|
650
|
-
return Base64.encodeToString(bytes, Base64.NO_WRAP);
|
|
651
|
-
}
|
|
652
638
|
|
|
653
639
|
@PluginMethod
|
|
654
640
|
public void startBarcodeScan(PluginCall call) {
|
|
@@ -673,6 +659,10 @@ public class CameraModulePlugin extends Plugin {
|
|
|
673
659
|
return;
|
|
674
660
|
}
|
|
675
661
|
|
|
662
|
+
barcodeScanner = BarcodeScanning.getClient();
|
|
663
|
+
|
|
664
|
+
call.setKeepAlive(true);
|
|
665
|
+
|
|
676
666
|
scanCall = call;
|
|
677
667
|
isScanning = true;
|
|
678
668
|
|
|
@@ -684,7 +674,7 @@ public class CameraModulePlugin extends Plugin {
|
|
|
684
674
|
.build();
|
|
685
675
|
|
|
686
676
|
imageAnalysis.setAnalyzer(
|
|
687
|
-
|
|
677
|
+
barcodeExecutor,
|
|
688
678
|
this::processBarcode
|
|
689
679
|
);
|
|
690
680
|
|
|
@@ -698,6 +688,10 @@ public class CameraModulePlugin extends Plugin {
|
|
|
698
688
|
.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
|
|
699
689
|
.build();
|
|
700
690
|
|
|
691
|
+
if (cameraSelector == null) {
|
|
692
|
+
cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA;
|
|
693
|
+
}
|
|
694
|
+
|
|
701
695
|
camera = cameraProvider.bindToLifecycle(
|
|
702
696
|
getActivity(),
|
|
703
697
|
cameraSelector,
|
|
@@ -705,9 +699,13 @@ public class CameraModulePlugin extends Plugin {
|
|
|
705
699
|
imageCapture,
|
|
706
700
|
imageAnalysis
|
|
707
701
|
);
|
|
702
|
+
|
|
703
|
+
call.resolve();
|
|
704
|
+
|
|
708
705
|
}
|
|
709
706
|
|
|
710
707
|
private void processBarcode(ImageProxy imageProxy) {
|
|
708
|
+
|
|
711
709
|
if (!isScanning) {
|
|
712
710
|
imageProxy.close();
|
|
713
711
|
return;
|
|
@@ -719,19 +717,26 @@ public class CameraModulePlugin extends Plugin {
|
|
|
719
717
|
return;
|
|
720
718
|
}
|
|
721
719
|
|
|
722
|
-
InputImage image =
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
);
|
|
727
|
-
|
|
728
|
-
BarcodeScanner scanner =
|
|
729
|
-
BarcodeScanning.getClient();
|
|
720
|
+
InputImage image = InputImage.fromMediaImage(
|
|
721
|
+
mediaImage,
|
|
722
|
+
imageProxy.getImageInfo().getRotationDegrees()
|
|
723
|
+
);
|
|
730
724
|
|
|
731
|
-
|
|
725
|
+
if (barcodeScanner == null) {
|
|
726
|
+
imageProxy.close();
|
|
727
|
+
return;
|
|
728
|
+
}
|
|
729
|
+
barcodeScanner.process(image)
|
|
732
730
|
.addOnSuccessListener(barcodes -> {
|
|
733
|
-
if (!barcodes.isEmpty() && isScanning) {
|
|
734
731
|
|
|
732
|
+
if (!isScanning) {
|
|
733
|
+
imageProxy.close();
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
if (!barcodes.isEmpty()) {
|
|
738
|
+
|
|
739
|
+
isScanning = false;
|
|
735
740
|
vibrateOnce();
|
|
736
741
|
|
|
737
742
|
Barcode barcode = barcodes.get(0);
|
|
@@ -740,36 +745,63 @@ public class CameraModulePlugin extends Plugin {
|
|
|
740
745
|
ret.put("rawValue", barcode.getRawValue());
|
|
741
746
|
ret.put("format", barcode.getFormat());
|
|
742
747
|
|
|
743
|
-
|
|
744
|
-
|
|
748
|
+
if (scanCall != null) {
|
|
749
|
+
scanCall.resolve(ret);
|
|
750
|
+
scanCall.setKeepAlive(false);
|
|
751
|
+
scanCall = null;
|
|
752
|
+
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
if (barcodeScanner != null) {
|
|
756
|
+
barcodeScanner.close();
|
|
757
|
+
barcodeScanner = null;
|
|
758
|
+
}
|
|
745
759
|
|
|
746
|
-
scanCall.resolve(ret);
|
|
747
|
-
scanCall = null;
|
|
748
760
|
|
|
749
761
|
stopBarcodeScanInternal();
|
|
750
|
-
} else {
|
|
751
|
-
imageProxy.close();
|
|
752
762
|
}
|
|
763
|
+
|
|
764
|
+
imageProxy.close();
|
|
753
765
|
})
|
|
754
766
|
.addOnFailureListener(e -> {
|
|
755
767
|
imageProxy.close();
|
|
756
768
|
});
|
|
757
769
|
}
|
|
758
770
|
|
|
771
|
+
|
|
759
772
|
private void stopBarcodeScanInternal() {
|
|
760
|
-
|
|
761
|
-
cameraProvider
|
|
762
|
-
|
|
763
|
-
|
|
773
|
+
getActivity().runOnUiThread(() -> {
|
|
774
|
+
if (cameraProvider != null) {
|
|
775
|
+
cameraProvider.unbindAll();
|
|
776
|
+
startCamera();
|
|
777
|
+
}
|
|
778
|
+
});
|
|
764
779
|
}
|
|
765
780
|
|
|
781
|
+
|
|
782
|
+
|
|
766
783
|
@PluginMethod
|
|
767
784
|
public void stopBarcodeScan(PluginCall call) {
|
|
768
785
|
isScanning = false;
|
|
786
|
+
imageAnalysis = null;
|
|
787
|
+
|
|
788
|
+
if (scanCall != null) {
|
|
789
|
+
scanCall.setKeepAlive(false);
|
|
790
|
+
scanCall = null;
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
if (barcodeScanner != null) {
|
|
794
|
+
barcodeScanner.close();
|
|
795
|
+
barcodeScanner = null;
|
|
796
|
+
}
|
|
797
|
+
|
|
769
798
|
stopBarcodeScanInternal();
|
|
799
|
+
|
|
770
800
|
call.resolve();
|
|
771
801
|
}
|
|
772
802
|
|
|
803
|
+
|
|
804
|
+
|
|
773
805
|
private void vibrateOnce() {
|
|
774
806
|
Vibrator vibrator =
|
|
775
807
|
(Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE);
|
|
@@ -788,5 +820,28 @@ public class CameraModulePlugin extends Plugin {
|
|
|
788
820
|
}
|
|
789
821
|
}
|
|
790
822
|
|
|
823
|
+
private void restartNormalPreview() {
|
|
824
|
+
if (cameraProvider == null) return;
|
|
825
|
+
|
|
826
|
+
cameraProvider.unbindAll();
|
|
827
|
+
|
|
828
|
+
Preview preview = new Preview.Builder().build();
|
|
829
|
+
preview.setSurfaceProvider(previewView.getSurfaceProvider());
|
|
830
|
+
|
|
831
|
+
imageCapture = new ImageCapture.Builder()
|
|
832
|
+
.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
|
|
833
|
+
.build();
|
|
834
|
+
|
|
835
|
+
CameraSelector cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA;
|
|
836
|
+
|
|
837
|
+
cameraProvider.bindToLifecycle(
|
|
838
|
+
getActivity(),
|
|
839
|
+
cameraSelector,
|
|
840
|
+
preview,
|
|
841
|
+
imageCapture
|
|
842
|
+
);
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
|
|
791
846
|
|
|
792
847
|
}
|