@capgo/camera-preview 7.4.0-beta.6 → 7.4.0-beta.8

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/README.md CHANGED
@@ -222,6 +222,8 @@ Documentation for the [uploader](https://github.com/Cap-go/capacitor-uploader)
222
222
  * [`getSupportedFlashModes()`](#getsupportedflashmodes)
223
223
  * [`setAspectRatio(...)`](#setaspectratio)
224
224
  * [`getAspectRatio()`](#getaspectratio)
225
+ * [`setGridMode(...)`](#setgridmode)
226
+ * [`getGridMode()`](#getgridmode)
225
227
  * [`getHorizontalFov()`](#gethorizontalfov)
226
228
  * [`getSupportedPictureSizes()`](#getsupportedpicturesizes)
227
229
  * [`setFlashMode(...)`](#setflashmode)
@@ -237,6 +239,8 @@ Documentation for the [uploader](https://github.com/Cap-go/capacitor-uploader)
237
239
  * [`removeAllListeners()`](#removealllisteners)
238
240
  * [`setDeviceId(...)`](#setdeviceid)
239
241
  * [`getDeviceId()`](#getdeviceid)
242
+ * [`getPreviewSize()`](#getpreviewsize)
243
+ * [`setPreviewSize(...)`](#setpreviewsize)
240
244
  * [Interfaces](#interfaces)
241
245
  * [Type Aliases](#type-aliases)
242
246
  * [Enums](#enums)
@@ -336,14 +340,16 @@ Gets the flash modes supported by the active camera.
336
340
  ### setAspectRatio(...)
337
341
 
338
342
  ```typescript
339
- setAspectRatio(options: { aspectRatio: '4:3' | '16:9' | 'fill'; }) => Promise<void>
343
+ setAspectRatio(options: { aspectRatio: '4:3' | '16:9'; x?: number; y?: number; }) => Promise<{ width: number; height: number; x: number; y: number; }>
340
344
  ```
341
345
 
342
346
  Set the aspect ratio of the camera preview.
343
347
 
344
- | Param | Type | Description |
345
- | ------------- | -------------------------------------------------------- | --------------------------- |
346
- | **`options`** | <code>{ aspectRatio: '4:3' \| '16:9' \| 'fill'; }</code> | - The desired aspect ratio. |
348
+ | Param | Type | Description |
349
+ | ------------- | ---------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
350
+ | **`options`** | <code>{ aspectRatio: '4:3' \| '16:9'; x?: number; y?: number; }</code> | - The desired aspect ratio and optional position. - aspectRatio: The desired aspect ratio ('4:3' or '16:9') - x: Optional x coordinate for positioning. If not provided, view will be auto-centered horizontally. - y: Optional y coordinate for positioning. If not provided, view will be auto-centered vertically. |
351
+
352
+ **Returns:** <code>Promise&lt;{ width: number; height: number; x: number; y: number; }&gt;</code>
347
353
 
348
354
  **Since:** 7.4.0
349
355
 
@@ -353,18 +359,50 @@ Set the aspect ratio of the camera preview.
353
359
  ### getAspectRatio()
354
360
 
355
361
  ```typescript
356
- getAspectRatio() => Promise<{ aspectRatio: '4:3' | '16:9' | 'fill'; }>
362
+ getAspectRatio() => Promise<{ aspectRatio: '4:3' | '16:9'; }>
357
363
  ```
358
364
 
359
365
  Gets the current aspect ratio of the camera preview.
360
366
 
361
- **Returns:** <code>Promise&lt;{ aspectRatio: '4:3' | '16:9' | 'fill'; }&gt;</code>
367
+ **Returns:** <code>Promise&lt;{ aspectRatio: '4:3' | '16:9'; }&gt;</code>
362
368
 
363
369
  **Since:** 7.4.0
364
370
 
365
371
  --------------------
366
372
 
367
373
 
374
+ ### setGridMode(...)
375
+
376
+ ```typescript
377
+ setGridMode(options: { gridMode: GridMode; }) => Promise<void>
378
+ ```
379
+
380
+ Sets the grid mode of the camera preview overlay.
381
+
382
+ | Param | Type | Description |
383
+ | ------------- | ------------------------------------------------------------ | -------------------------------------------------- |
384
+ | **`options`** | <code>{ gridMode: <a href="#gridmode">GridMode</a>; }</code> | - The desired grid mode ('none', '3x3', or '4x4'). |
385
+
386
+ **Since:** 8.0.0
387
+
388
+ --------------------
389
+
390
+
391
+ ### getGridMode()
392
+
393
+ ```typescript
394
+ getGridMode() => Promise<{ gridMode: GridMode; }>
395
+ ```
396
+
397
+ Gets the current grid mode of the camera preview overlay.
398
+
399
+ **Returns:** <code>Promise&lt;{ gridMode: <a href="#gridmode">GridMode</a>; }&gt;</code>
400
+
401
+ **Since:** 8.0.0
402
+
403
+ --------------------
404
+
405
+
368
406
  ### getHorizontalFov()
369
407
 
370
408
  ```typescript
@@ -597,6 +635,36 @@ Gets the ID of the currently active camera device.
597
635
  --------------------
598
636
 
599
637
 
638
+ ### getPreviewSize()
639
+
640
+ ```typescript
641
+ getPreviewSize() => Promise<{ x: number; y: number; width: number; height: number; }>
642
+ ```
643
+
644
+ Gets the current preview size and position.
645
+
646
+ **Returns:** <code>Promise&lt;{ x: number; y: number; width: number; height: number; }&gt;</code>
647
+
648
+ --------------------
649
+
650
+
651
+ ### setPreviewSize(...)
652
+
653
+ ```typescript
654
+ setPreviewSize(options: { x: number; y: number; width: number; height: number; }) => Promise<{ width: number; height: number; x: number; y: number; }>
655
+ ```
656
+
657
+ Sets the preview size and position.
658
+
659
+ | Param | Type | Description |
660
+ | ------------- | --------------------------------------------------------------------- | -------------------------------- |
661
+ | **`options`** | <code>{ x: number; y: number; width: number; height: number; }</code> | The new position and dimensions. |
662
+
663
+ **Returns:** <code>Promise&lt;{ width: number; height: number; x: number; y: number; }&gt;</code>
664
+
665
+ --------------------
666
+
667
+
600
668
  ### Interfaces
601
669
 
602
670
 
@@ -604,30 +672,30 @@ Gets the ID of the currently active camera device.
604
672
 
605
673
  Defines the configuration options for starting the camera preview.
606
674
 
607
- | Prop | Type | Description | Default | Since |
608
- | ---------------------------------- | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | ------------------- | ----- |
609
- | **`parent`** | <code>string</code> | The parent element to attach the video preview to. | | |
610
- | **`className`** | <code>string</code> | A CSS class name to add to the preview element. | | |
611
- | **`width`** | <code>number</code> | The width of the preview in pixels. Defaults to the screen width. | | |
612
- | **`height`** | <code>number</code> | The height of the preview in pixels. Defaults to the screen height. | | |
613
- | **`x`** | <code>number</code> | The horizontal origin of the preview, in pixels. | | |
614
- | **`y`** | <code>number</code> | The vertical origin of the preview, in pixels. | | |
615
- | **`aspectRatio`** | <code>'4:3' \| '16:9' \| 'fill'</code> | The aspect ratio of the camera preview, '4:3' or '16:9'. If not set, the camera will use the default aspect ratio. | | 2.0.0 |
616
- | **`gridMode`** | <code><a href="#gridmode">GridMode</a></code> | The grid overlay to display on the camera preview. | <code>"none"</code> | 2.1.0 |
617
- | **`includeSafeAreaInsets`** | <code>boolean</code> | Adjusts the y-position to account for safe areas (e.g., notches). | <code>false</code> | |
618
- | **`toBack`** | <code>boolean</code> | If true, places the preview behind the webview. | <code>true</code> | |
619
- | **`paddingBottom`** | <code>number</code> | Bottom padding for the preview, in pixels. | | |
620
- | **`rotateWhenOrientationChanged`** | <code>boolean</code> | Whether to rotate the preview when the device orientation changes. | <code>true</code> | |
621
- | **`position`** | <code>string</code> | The camera to use. | <code>"rear"</code> | |
622
- | **`storeToFile`** | <code>boolean</code> | If true, saves the captured image to a file and returns the file path. If false, returns a base64 encoded string. | <code>false</code> | |
623
- | **`disableExifHeaderStripping`** | <code>boolean</code> | If true, prevents the plugin from rotating the image based on EXIF data. | <code>false</code> | |
624
- | **`enableHighResolution`** | <code>boolean</code> | If true, enables high-resolution image capture. | <code>false</code> | |
625
- | **`disableAudio`** | <code>boolean</code> | If true, disables the audio stream, preventing audio permission requests. | <code>true</code> | |
626
- | **`lockAndroidOrientation`** | <code>boolean</code> | If true, locks the device orientation while the camera is active. | <code>false</code> | |
627
- | **`enableOpacity`** | <code>boolean</code> | If true, allows the camera preview's opacity to be changed. | <code>false</code> | |
628
- | **`enableZoom`** | <code>boolean</code> | If true, enables pinch-to-zoom functionality on the preview. | <code>false</code> | |
629
- | **`enableVideoMode`** | <code>boolean</code> | If true, uses the video-optimized preset for the camera session. | <code>false</code> | |
630
- | **`deviceId`** | <code>string</code> | The `deviceId` of the camera to use. If provided, `position` is ignored. | | |
675
+ | Prop | Type | Description | Default | Since |
676
+ | ---------------------------------- | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | ----- |
677
+ | **`parent`** | <code>string</code> | The parent element to attach the video preview to. | | |
678
+ | **`className`** | <code>string</code> | A CSS class name to add to the preview element. | | |
679
+ | **`width`** | <code>number</code> | The width of the preview in pixels. Defaults to the screen width. | | |
680
+ | **`height`** | <code>number</code> | The height of the preview in pixels. Defaults to the screen height. | | |
681
+ | **`x`** | <code>number</code> | The horizontal origin of the preview, in pixels. | | |
682
+ | **`y`** | <code>number</code> | The vertical origin of the preview, in pixels. | | |
683
+ | **`aspectRatio`** | <code>'4:3' \| '16:9' \| 'fill'</code> | The aspect ratio of the camera preview, '4:3' or '16:9' or 'fill'. Cannot be set if width or height is provided, otherwise the call will be rejected. Use setPreviewSize to adjust size after starting. | | 2.0.0 |
684
+ | **`gridMode`** | <code><a href="#gridmode">GridMode</a></code> | The grid overlay to display on the camera preview. | <code>"none"</code> | 2.1.0 |
685
+ | **`includeSafeAreaInsets`** | <code>boolean</code> | Adjusts the y-position to account for safe areas (e.g., notches). | <code>false</code> | |
686
+ | **`toBack`** | <code>boolean</code> | If true, places the preview behind the webview. | <code>true</code> | |
687
+ | **`paddingBottom`** | <code>number</code> | Bottom padding for the preview, in pixels. | | |
688
+ | **`rotateWhenOrientationChanged`** | <code>boolean</code> | Whether to rotate the preview when the device orientation changes. | <code>true</code> | |
689
+ | **`position`** | <code>string</code> | The camera to use. | <code>"rear"</code> | |
690
+ | **`storeToFile`** | <code>boolean</code> | If true, saves the captured image to a file and returns the file path. If false, returns a base64 encoded string. | <code>false</code> | |
691
+ | **`disableExifHeaderStripping`** | <code>boolean</code> | If true, prevents the plugin from rotating the image based on EXIF data. | <code>false</code> | |
692
+ | **`enableHighResolution`** | <code>boolean</code> | If true, enables high-resolution image capture. | <code>false</code> | |
693
+ | **`disableAudio`** | <code>boolean</code> | If true, disables the audio stream, preventing audio permission requests. | <code>true</code> | |
694
+ | **`lockAndroidOrientation`** | <code>boolean</code> | If true, locks the device orientation while the camera is active. | <code>false</code> | |
695
+ | **`enableOpacity`** | <code>boolean</code> | If true, allows the camera preview's opacity to be changed. | <code>false</code> | |
696
+ | **`enableZoom`** | <code>boolean</code> | If true, enables pinch-to-zoom functionality on the preview. | <code>false</code> | |
697
+ | **`enableVideoMode`** | <code>boolean</code> | If true, uses the video-optimized preset for the camera session. | <code>false</code> | |
698
+ | **`deviceId`** | <code>string</code> | The `deviceId` of the camera to use. If provided, `position` is ignored. | | |
631
699
 
632
700
 
633
701
  #### ExifData
Binary file
@@ -50,6 +50,7 @@ dependencies {
50
50
  implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
51
51
  implementation 'androidx.exifinterface:exifinterface:1.4.1'
52
52
  implementation 'com.google.android.gms:play-services-location:21.3.0'
53
+ implementation 'androidx.coordinatorlayout:coordinatorlayout:1.3.0'
53
54
 
54
55
  // CameraX dependencies
55
56
  def camerax_version = "1.5.0-beta01"
@@ -6,7 +6,6 @@ import static android.Manifest.permission.RECORD_AUDIO;
6
6
  import android.Manifest;
7
7
  import android.content.pm.ActivityInfo;
8
8
  import android.util.DisplayMetrics;
9
- import android.util.TypedValue;
10
9
  import com.getcapacitor.JSArray;
11
10
  import com.getcapacitor.JSObject;
12
11
  import com.getcapacitor.PermissionState;
@@ -28,15 +27,10 @@ import com.google.android.gms.location.FusedLocationProviderClient;
28
27
  import com.google.android.gms.location.LocationServices;
29
28
  import org.json.JSONObject;
30
29
  import android.location.Location;
30
+ import android.view.ViewGroup;
31
+
31
32
  import com.getcapacitor.Logger;
32
33
 
33
- interface CameraPreviewListener {
34
- void onPictureTaken(String base64, JSONObject exif);
35
- void onPictureTakenError(String message);
36
- void onCameraStarted(int width, int height, int x, int y);
37
- void onCameraStopped();
38
- void onCaptureStarted();
39
- }
40
34
 
41
35
  @CapacitorPlugin(
42
36
  name = "CameraPreview",
@@ -57,7 +51,7 @@ interface CameraPreviewListener {
57
51
  )
58
52
  public class CameraPreview
59
53
  extends Plugin
60
- implements CameraPreviewListener {
54
+ implements CameraXView.CameraXViewListener {
61
55
 
62
56
  static final String CAMERA_WITH_AUDIO_PERMISSION_ALIAS = "cameraWithAudio";
63
57
  static final String CAMERA_ONLY_PERMISSION_ALIAS = "cameraOnly";
@@ -397,8 +391,14 @@ public class CameraPreview
397
391
  final boolean disableExifHeaderStripping = Boolean.TRUE.equals(call.getBoolean("disableExifHeaderStripping", false));
398
392
  final boolean lockOrientation = Boolean.TRUE.equals(call.getBoolean("lockAndroidOrientation", false));
399
393
  final boolean disableAudio = Boolean.TRUE.equals(call.getBoolean("disableAudio", true));
400
- final String aspectRatio = call.getString("aspectRatio", "fill");
394
+ final String aspectRatio = call.getString("aspectRatio", "4:3");
401
395
  final String gridMode = call.getString("gridMode", "none");
396
+
397
+ // Check for conflict between aspectRatio and size
398
+ if (call.getData().has("aspectRatio") && (call.getData().has("width") || call.getData().has("height"))) {
399
+ call.reject("Cannot set both aspectRatio and size (width/height). Use setPreviewSize after start.");
400
+ return;
401
+ }
402
402
 
403
403
  float targetZoom = 1.0f;
404
404
  // Check if the selected device is a physical ultra-wide
@@ -422,7 +422,7 @@ public class CameraPreview
422
422
 
423
423
  previousOrientationRequest = getBridge().getActivity().getRequestedOrientation();
424
424
  cameraXView = new CameraXView(getContext(), getBridge().getWebView());
425
- cameraXView.setListener((CameraXView.CameraXViewListener) this);
425
+ cameraXView.setListener(this);
426
426
 
427
427
  String finalDeviceId = deviceId;
428
428
  float finalTargetZoom = targetZoom;
@@ -431,11 +431,46 @@ public class CameraPreview
431
431
  if (lockOrientation) {
432
432
  getBridge().getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
433
433
  }
434
- int computedX = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, x, metrics);
435
- int computedY = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, y, metrics);
436
- int computedWidth = width != 0 ? (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, width, metrics) : getBridge().getWebView().getWidth();
437
- int computedHeight = height != 0 ? (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, height, metrics) : getBridge().getWebView().getHeight();
438
- computedHeight -= (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, paddingBottom, metrics);
434
+
435
+ // Debug: Let's check all the positioning information
436
+ ViewGroup webViewParent = (ViewGroup) getBridge().getWebView().getParent();
437
+
438
+ // Get webview position in different coordinate systems
439
+ int[] webViewLocationInWindow = new int[2];
440
+ int[] webViewLocationOnScreen = new int[2];
441
+ getBridge().getWebView().getLocationInWindow(webViewLocationInWindow);
442
+ getBridge().getWebView().getLocationOnScreen(webViewLocationOnScreen);
443
+
444
+ int webViewLeft = getBridge().getWebView().getLeft();
445
+ int webViewTop = getBridge().getWebView().getTop();
446
+
447
+ // Check parent position too
448
+ int[] parentLocationInWindow = new int[2];
449
+ int[] parentLocationOnScreen = new int[2];
450
+ webViewParent.getLocationInWindow(parentLocationInWindow);
451
+ webViewParent.getLocationOnScreen(parentLocationOnScreen);
452
+
453
+ // Calculate pixel ratio
454
+ float pixelRatio = metrics.density;
455
+
456
+ // Try using just the pixel ratio without any webview offset for now
457
+ int computedX = (int) (x * pixelRatio);
458
+ int computedY = (int) (y * pixelRatio);
459
+
460
+ Log.d("CameraPreview", "=== COORDINATE DEBUG ===");
461
+ Log.d("CameraPreview", "WebView getLeft/getTop: (" + webViewLeft + ", " + webViewTop + ")");
462
+ Log.d("CameraPreview", "WebView locationInWindow: (" + webViewLocationInWindow[0] + ", " + webViewLocationInWindow[1] + ")");
463
+ Log.d("CameraPreview", "WebView locationOnScreen: (" + webViewLocationOnScreen[0] + ", " + webViewLocationOnScreen[1] + ")");
464
+ Log.d("CameraPreview", "Parent locationInWindow: (" + parentLocationInWindow[0] + ", " + parentLocationInWindow[1] + ")");
465
+ Log.d("CameraPreview", "Parent locationOnScreen: (" + parentLocationOnScreen[0] + ", " + parentLocationOnScreen[1] + ")");
466
+ Log.d("CameraPreview", "Parent class: " + webViewParent.getClass().getSimpleName());
467
+ Log.d("CameraPreview", "Requested position (logical): (" + x + ", " + y + ")");
468
+ Log.d("CameraPreview", "Pixel ratio: " + pixelRatio);
469
+ Log.d("CameraPreview", "Final computed position (no offset): (" + computedX + ", " + computedY + ")");
470
+ Log.d("CameraPreview", "========================");
471
+ int computedWidth = width != 0 ? (int) (width * pixelRatio) : getBridge().getWebView().getWidth();
472
+ int computedHeight = height != 0 ? (int) (height * pixelRatio) : getBridge().getWebView().getHeight();
473
+ computedHeight -= (int) (paddingBottom * pixelRatio);
439
474
 
440
475
  CameraSessionConfiguration config = new CameraSessionConfiguration(finalDeviceId, position, computedX, computedY, computedWidth, computedHeight, paddingBottom, toBack, storeToFile, enableOpacity, enableZoom, disableExifHeaderStripping, disableAudio, 1.0f, aspectRatio, gridMode);
441
476
  config.setTargetZoom(finalTargetZoom);
@@ -472,20 +507,19 @@ public class CameraPreview
472
507
  bridge.releaseCall(pluginCall);
473
508
  }
474
509
 
475
- @Override
476
- public void onCaptureStarted() {
477
- Log.i("CameraPreview", "Capture started");
478
- }
479
-
480
510
  @Override
481
511
  public void onCameraStarted(int width, int height, int x, int y) {
482
512
  PluginCall call = bridge.getSavedCall(cameraStartCallbackId);
483
513
  if (call != null) {
514
+ // Convert pixel values back to logical units
515
+ DisplayMetrics metrics = getBridge().getActivity().getResources().getDisplayMetrics();
516
+ float pixelRatio = metrics.density;
517
+
484
518
  JSObject result = new JSObject();
485
- result.put("width", width);
486
- result.put("height", height);
487
- result.put("x", x);
488
- result.put("y", y);
519
+ result.put("width", width / pixelRatio);
520
+ result.put("height", height / pixelRatio);
521
+ result.put("x", x / pixelRatio);
522
+ result.put("y", y / pixelRatio);
489
523
  call.resolve(result);
490
524
  bridge.releaseCall(call);
491
525
  cameraStartCallbackId = null; // Prevent re-use
@@ -493,8 +527,25 @@ public class CameraPreview
493
527
  }
494
528
 
495
529
  @Override
496
- public void onCameraStopped() {
497
- // This method is no longer needed as onCameraStarted handles the promise resolution.
530
+ public void onSampleTaken(String result) {
531
+ // Handle sample taken if needed
532
+ Log.i("CameraPreview", "Sample taken: " + result);
533
+ }
534
+
535
+ @Override
536
+ public void onSampleTakenError(String message) {
537
+ // Handle sample taken error if needed
538
+ Log.e("CameraPreview", "Sample taken error: " + message);
539
+ }
540
+
541
+ @Override
542
+ public void onCameraStartError(String message) {
543
+ PluginCall call = bridge.getSavedCall(cameraStartCallbackId);
544
+ if (call != null) {
545
+ call.reject(message);
546
+ bridge.releaseCall(call);
547
+ cameraStartCallbackId = null;
548
+ }
498
549
  }
499
550
 
500
551
  @PluginMethod
@@ -503,9 +554,22 @@ public class CameraPreview
503
554
  call.reject("Camera is not running");
504
555
  return;
505
556
  }
506
- String aspectRatio = call.getString("aspectRatio", "fill");
507
- cameraXView.setAspectRatio(aspectRatio);
508
- call.resolve();
557
+ String aspectRatio = call.getString("aspectRatio", "4:3");
558
+ Float x = call.getFloat("x");
559
+ Float y = call.getFloat("y");
560
+
561
+ getActivity().runOnUiThread(() -> {
562
+ cameraXView.setAspectRatio(aspectRatio, x, y, () -> {
563
+ // Return the actual preview bounds after layout and camera operations are complete
564
+ int[] bounds = cameraXView.getCurrentPreviewBounds();
565
+ JSObject ret = new JSObject();
566
+ ret.put("x", bounds[0]);
567
+ ret.put("y", bounds[1]);
568
+ ret.put("width", bounds[2]);
569
+ ret.put("height", bounds[3]);
570
+ call.resolve(ret);
571
+ });
572
+ });
509
573
  }
510
574
 
511
575
  @PluginMethod
@@ -519,4 +583,80 @@ public class CameraPreview
519
583
  ret.put("aspectRatio", aspectRatio);
520
584
  call.resolve(ret);
521
585
  }
586
+
587
+ @PluginMethod
588
+ public void setGridMode(PluginCall call) {
589
+ if (cameraXView == null || !cameraXView.isRunning()) {
590
+ call.reject("Camera is not running");
591
+ return;
592
+ }
593
+ String gridMode = call.getString("gridMode", "none");
594
+ getActivity().runOnUiThread(() -> {
595
+ cameraXView.setGridMode(gridMode);
596
+ call.resolve();
597
+ });
598
+ }
599
+
600
+ @PluginMethod
601
+ public void getGridMode(PluginCall call) {
602
+ if (cameraXView == null || !cameraXView.isRunning()) {
603
+ call.reject("Camera is not running");
604
+ return;
605
+ }
606
+ JSObject ret = new JSObject();
607
+ ret.put("gridMode", cameraXView.getGridMode());
608
+ call.resolve(ret);
609
+ }
610
+
611
+ @PluginMethod
612
+ public void getPreviewSize(PluginCall call) {
613
+ if (cameraXView == null || !cameraXView.isRunning()) {
614
+ call.reject("Camera is not running");
615
+ return;
616
+ }
617
+
618
+ // Convert pixel values back to logical units
619
+ DisplayMetrics metrics = getBridge().getActivity().getResources().getDisplayMetrics();
620
+ float pixelRatio = metrics.density;
621
+
622
+ JSObject ret = new JSObject();
623
+ ret.put("x", cameraXView.getPreviewX() / pixelRatio);
624
+ ret.put("y", cameraXView.getPreviewY() / pixelRatio);
625
+ ret.put("width", cameraXView.getPreviewWidth() / pixelRatio);
626
+ ret.put("height", cameraXView.getPreviewHeight() / pixelRatio);
627
+ call.resolve(ret);
628
+ }
629
+ @PluginMethod
630
+ public void setPreviewSize(PluginCall call) {
631
+ if (cameraXView == null || !cameraXView.isRunning()) {
632
+ call.reject("Camera is not running");
633
+ return;
634
+ }
635
+
636
+ // Get values from call - null values will become 0
637
+ Integer xParam = call.getInt("x");
638
+ Integer yParam = call.getInt("y");
639
+ Integer widthParam = call.getInt("width");
640
+ Integer heightParam = call.getInt("height");
641
+
642
+ // Apply pixel ratio conversion to non-null values
643
+ DisplayMetrics metrics = getBridge().getActivity().getResources().getDisplayMetrics();
644
+ float pixelRatio = metrics.density;
645
+
646
+ int x = (xParam != null && xParam > 0) ? (int) (xParam * pixelRatio) : 0;
647
+ int y = (yParam != null && yParam > 0) ? (int) (yParam * pixelRatio) : 0;
648
+ int width = (widthParam != null && widthParam > 0) ? (int) (widthParam * pixelRatio) : 0;
649
+ int height = (heightParam != null && heightParam > 0) ? (int) (heightParam * pixelRatio) : 0;
650
+
651
+ cameraXView.setPreviewSize(x, y, width, height, () -> {
652
+ // Return the actual preview bounds after layout operations are complete
653
+ int[] bounds = cameraXView.getCurrentPreviewBounds();
654
+ JSObject ret = new JSObject();
655
+ ret.put("x", bounds[0]);
656
+ ret.put("y", bounds[1]);
657
+ ret.put("width", bounds[2]);
658
+ ret.put("height", bounds[3]);
659
+ call.resolve(ret);
660
+ });
661
+ }
522
662
  }