@capgo/camera-preview 7.4.0-beta.2 → 7.4.0-beta.4

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.
Files changed (31) hide show
  1. package/README.md +120 -30
  2. package/android/.gradle/8.14.2/checksums/checksums.lock +0 -0
  3. package/android/.gradle/8.14.2/checksums/md5-checksums.bin +0 -0
  4. package/android/.gradle/8.14.2/checksums/sha1-checksums.bin +0 -0
  5. package/android/.gradle/8.14.2/executionHistory/executionHistory.bin +0 -0
  6. package/android/.gradle/8.14.2/executionHistory/executionHistory.lock +0 -0
  7. package/android/.gradle/8.14.2/fileHashes/fileHashes.bin +0 -0
  8. package/android/.gradle/8.14.2/fileHashes/fileHashes.lock +0 -0
  9. package/android/.gradle/8.14.2/fileHashes/resourceHashesCache.bin +0 -0
  10. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  11. package/android/.gradle/file-system.probe +0 -0
  12. package/android/build.gradle +2 -1
  13. package/android/src/main/AndroidManifest.xml +1 -4
  14. package/android/src/main/java/com/ahm/capacitor/camera/preview/CameraPreview.java +111 -29
  15. package/android/src/main/java/com/ahm/capacitor/camera/preview/CameraXView.java +152 -17
  16. package/android/src/main/java/com/ahm/capacitor/camera/preview/GridOverlayView.java +80 -0
  17. package/android/src/main/java/com/ahm/capacitor/camera/preview/model/CameraSessionConfiguration.java +19 -5
  18. package/dist/docs.json +117 -4
  19. package/dist/esm/definitions.d.ts +52 -3
  20. package/dist/esm/definitions.js.map +1 -1
  21. package/dist/esm/web.d.ts +16 -2
  22. package/dist/esm/web.js +180 -78
  23. package/dist/esm/web.js.map +1 -1
  24. package/dist/plugin.cjs.js +178 -78
  25. package/dist/plugin.cjs.js.map +1 -1
  26. package/dist/plugin.js +178 -78
  27. package/dist/plugin.js.map +1 -1
  28. package/ios/Sources/CapgoCameraPreview/CameraController.swift +131 -13
  29. package/ios/Sources/CapgoCameraPreview/GridOverlayView.swift +65 -0
  30. package/ios/Sources/CapgoCameraPreview/Plugin.swift +176 -37
  31. package/package.json +1 -1
package/README.md CHANGED
@@ -92,6 +92,52 @@ Then run
92
92
  npx cap sync
93
93
  ```
94
94
 
95
+ ## Optional Configuration
96
+
97
+ To use certain features of this plugin, you will need to add the following permissions/keys to your native project configurations.
98
+
99
+ ### Android
100
+
101
+ In your `android/app/src/main/AndroidManifest.xml`:
102
+
103
+ - **Audio Recording** (`disableAudio: false`):
104
+ ```xml
105
+ <uses-permission android:name="android.permission.RECORD_AUDIO" />
106
+ ```
107
+
108
+ - **Saving to Gallery** (`saveToGallery: true`):
109
+ ```xml
110
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
111
+ ```
112
+
113
+ - **Location in EXIF Data** (`withExifLocation: true`):
114
+ ```xml
115
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
116
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
117
+ ```
118
+
119
+ ### iOS
120
+
121
+ In your `ios/App/App/Info.plist`, you must provide descriptions for the permissions your app requires. The keys are added automatically, but you need to provide the `string` values.
122
+
123
+ - **Audio Recording** (`disableAudio: false`):
124
+ ```xml
125
+ <key>NSMicrophoneUsageDescription</key>
126
+ <string>To record audio with videos</string>
127
+ ```
128
+
129
+ - **Saving to Gallery** (`saveToGallery: true`):
130
+ ```xml
131
+ <key>NSPhotoLibraryAddUsageDescription</key>
132
+ <string>To save photos to your gallery</string>
133
+ ```
134
+
135
+ - **Location in EXIF Data** (`withExifLocation: true`):
136
+ ```xml
137
+ <key>NSLocationWhenInUseUsageDescription</key>
138
+ <string>To add location data to your photos</string>
139
+ ```
140
+
95
141
  ## Extra Android installation steps
96
142
 
97
143
  **Important** `camera-preview` 3+ requires Gradle 7.
@@ -174,6 +220,8 @@ Documentation for the [uploader](https://github.com/Cap-go/capacitor-uploader)
174
220
  * [`capture(...)`](#capture)
175
221
  * [`captureSample(...)`](#capturesample)
176
222
  * [`getSupportedFlashModes()`](#getsupportedflashmodes)
223
+ * [`setAspectRatio(...)`](#setaspectratio)
224
+ * [`getAspectRatio()`](#getaspectratio)
177
225
  * [`getHorizontalFov()`](#gethorizontalfov)
178
226
  * [`getSupportedPictureSizes()`](#getsupportedpicturesizes)
179
227
  * [`setFlashMode(...)`](#setflashmode)
@@ -203,7 +251,7 @@ The main interface for the CameraPreview plugin.
203
251
  ### start(...)
204
252
 
205
253
  ```typescript
206
- start(options: CameraPreviewOptions) => Promise<void>
254
+ start(options: CameraPreviewOptions) => Promise<{ width: number; height: number; x: number; y: number; }>
207
255
  ```
208
256
 
209
257
  Starts the camera preview.
@@ -212,6 +260,8 @@ Starts the camera preview.
212
260
  | ------------- | --------------------------------------------------------------------- | ------------------------------------------- |
213
261
  | **`options`** | <code><a href="#camerapreviewoptions">CameraPreviewOptions</a></code> | - The configuration for the camera preview. |
214
262
 
263
+ **Returns:** <code>Promise&lt;{ width: number; height: number; x: number; y: number; }&gt;</code>
264
+
215
265
  **Since:** 0.0.1
216
266
 
217
267
  --------------------
@@ -283,6 +333,38 @@ Gets the flash modes supported by the active camera.
283
333
  --------------------
284
334
 
285
335
 
336
+ ### setAspectRatio(...)
337
+
338
+ ```typescript
339
+ setAspectRatio(options: { aspectRatio: '4:3' | '16:9' | 'fill'; }) => Promise<void>
340
+ ```
341
+
342
+ Set the aspect ratio of the camera preview.
343
+
344
+ | Param | Type | Description |
345
+ | ------------- | -------------------------------------------------------- | --------------------------- |
346
+ | **`options`** | <code>{ aspectRatio: '4:3' \| '16:9' \| 'fill'; }</code> | - The desired aspect ratio. |
347
+
348
+ **Since:** 7.4.0
349
+
350
+ --------------------
351
+
352
+
353
+ ### getAspectRatio()
354
+
355
+ ```typescript
356
+ getAspectRatio() => Promise<{ aspectRatio: '4:3' | '16:9' | 'fill'; }>
357
+ ```
358
+
359
+ Gets the current aspect ratio of the camera preview.
360
+
361
+ **Returns:** <code>Promise&lt;{ aspectRatio: '4:3' | '16:9' | 'fill'; }&gt;</code>
362
+
363
+ **Since:** 7.4.0
364
+
365
+ --------------------
366
+
367
+
286
368
  ### getHorizontalFov()
287
369
 
288
370
  ```typescript
@@ -522,28 +604,30 @@ Gets the ID of the currently active camera device.
522
604
 
523
605
  Defines the configuration options for starting the camera preview.
524
606
 
525
- | Prop | Type | Description | Default |
526
- | ---------------------------------- | -------------------- | ----------------------------------------------------------------------------------------------------------------- | ------------------- |
527
- | **`parent`** | <code>string</code> | The parent element to attach the video preview to. | |
528
- | **`className`** | <code>string</code> | A CSS class name to add to the preview element. | |
529
- | **`width`** | <code>number</code> | The width of the preview in pixels. Defaults to the screen width. | |
530
- | **`height`** | <code>number</code> | The height of the preview in pixels. Defaults to the screen height. | |
531
- | **`x`** | <code>number</code> | The horizontal origin of the preview, in pixels. | |
532
- | **`y`** | <code>number</code> | The vertical origin of the preview, in pixels. | |
533
- | **`includeSafeAreaInsets`** | <code>boolean</code> | Adjusts the y-position to account for safe areas (e.g., notches). | <code>false</code> |
534
- | **`toBack`** | <code>boolean</code> | If true, places the preview behind the webview. | <code>true</code> |
535
- | **`paddingBottom`** | <code>number</code> | Bottom padding for the preview, in pixels. | |
536
- | **`rotateWhenOrientationChanged`** | <code>boolean</code> | Whether to rotate the preview when the device orientation changes. | <code>true</code> |
537
- | **`position`** | <code>string</code> | The camera to use. | <code>"rear"</code> |
538
- | **`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> |
539
- | **`disableExifHeaderStripping`** | <code>boolean</code> | If true, prevents the plugin from rotating the image based on EXIF data. | <code>false</code> |
540
- | **`enableHighResolution`** | <code>boolean</code> | If true, enables high-resolution image capture. | <code>false</code> |
541
- | **`disableAudio`** | <code>boolean</code> | If true, disables the audio stream, preventing audio permission requests. | <code>false</code> |
542
- | **`lockAndroidOrientation`** | <code>boolean</code> | If true, locks the device orientation while the camera is active. | <code>false</code> |
543
- | **`enableOpacity`** | <code>boolean</code> | If true, allows the camera preview's opacity to be changed. | <code>false</code> |
544
- | **`enableZoom`** | <code>boolean</code> | If true, enables pinch-to-zoom functionality on the preview. | <code>false</code> |
545
- | **`enableVideoMode`** | <code>boolean</code> | If true, uses the video-optimized preset for the camera session. | <code>false</code> |
546
- | **`deviceId`** | <code>string</code> | The `deviceId` of the camera to use. If provided, `position` is ignored. | |
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. | | |
547
631
 
548
632
 
549
633
  #### ExifData
@@ -555,13 +639,14 @@ Represents EXIF data extracted from an image.
555
639
 
556
640
  Defines the options for capturing a picture.
557
641
 
558
- | Prop | Type | Description | Default | Since |
559
- | ------------------- | ------------------------------------------------------- | ----------------------------------------------------------------------------------------- | ------------------- | ----- |
560
- | **`height`** | <code>number</code> | The desired height of the picture in pixels. If not provided, the device default is used. | | |
561
- | **`width`** | <code>number</code> | The desired width of the picture in pixels. If not provided, the device default is used. | | |
562
- | **`quality`** | <code>number</code> | The quality of the captured image, from 0 to 100. Does not apply to `png` format. | <code>85</code> | |
563
- | **`format`** | <code><a href="#pictureformat">PictureFormat</a></code> | The format of the captured image. | <code>"jpeg"</code> | |
564
- | **`saveToGallery`** | <code>boolean</code> | If true, the captured image will be saved to the user's gallery. | <code>false</code> | 7.5.0 |
642
+ | Prop | Type | Description | Default | Since |
643
+ | ---------------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | ------------------- | ----- |
644
+ | **`height`** | <code>number</code> | The desired height of the picture in pixels. If not provided, the device default is used. | | |
645
+ | **`width`** | <code>number</code> | The desired width of the picture in pixels. If not provided, the device default is used. | | |
646
+ | **`quality`** | <code>number</code> | The quality of the captured image, from 0 to 100. Does not apply to `png` format. | <code>85</code> | |
647
+ | **`format`** | <code><a href="#pictureformat">PictureFormat</a></code> | The format of the captured image. | <code>"jpeg"</code> | |
648
+ | **`saveToGallery`** | <code>boolean</code> | If true, the captured image will be saved to the user's gallery. | <code>false</code> | 7.5.0 |
649
+ | **`withExifLocation`** | <code>boolean</code> | If true, the plugin will attempt to add GPS location data to the image's EXIF metadata. This may prompt the user for location permissions. | <code>false</code> | 7.6.0 |
565
650
 
566
651
 
567
652
  #### CameraSampleOptions
@@ -646,6 +731,11 @@ Represents the detailed information of the currently active lens.
646
731
  ### Type Aliases
647
732
 
648
733
 
734
+ #### GridMode
735
+
736
+ <code>"none" | "3x3" | "4x4"</code>
737
+
738
+
649
739
  #### CameraPosition
650
740
 
651
741
  <code>"rear" | "front"</code>
Binary file
@@ -49,7 +49,8 @@ dependencies {
49
49
  implementation project(':capacitor-android')
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
+
53
54
  // CameraX dependencies
54
55
  def camerax_version = "1.5.0-beta01"
55
56
  implementation "androidx.camera:camera-core:${camerax_version}"
@@ -1,10 +1,7 @@
1
1
 
2
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
3
- >
2
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
4
3
  <uses-permission android:name="android.permission.CAMERA" />
5
4
  <uses-permission android:name="android.permission.RECORD_AUDIO" />
6
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
7
5
  <uses-feature android:name="android.hardware.camera" />
8
6
  <uses-feature android:name="android.hardware.camera.autofocus" />
9
7
  </manifest>
10
-
@@ -3,6 +3,7 @@ package com.ahm.capacitor.camera.preview;
3
3
  import static android.Manifest.permission.CAMERA;
4
4
  import static android.Manifest.permission.RECORD_AUDIO;
5
5
 
6
+ import android.Manifest;
6
7
  import android.content.pm.ActivityInfo;
7
8
  import android.util.DisplayMetrics;
8
9
  import android.util.TypedValue;
@@ -23,8 +24,19 @@ import java.util.Objects;
23
24
  import android.util.Size;
24
25
  import android.util.Log;
25
26
  import com.ahm.capacitor.camera.preview.model.LensInfo;
26
-
27
+ import com.google.android.gms.location.FusedLocationProviderClient;
28
+ import com.google.android.gms.location.LocationServices;
27
29
  import org.json.JSONObject;
30
+ import android.location.Location;
31
+ import com.getcapacitor.Logger;
32
+
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
+ }
28
40
 
29
41
  @CapacitorPlugin(
30
42
  name = "CameraPreview",
@@ -37,20 +49,27 @@ import org.json.JSONObject;
37
49
  strings = { CAMERA },
38
50
  alias = CameraPreview.CAMERA_ONLY_PERMISSION_ALIAS
39
51
  ),
52
+ @Permission(
53
+ strings = { Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION },
54
+ alias = CameraPreview.CAMERA_WITH_LOCATION_PERMISSION_ALIAS
55
+ )
40
56
  }
41
57
  )
42
58
  public class CameraPreview
43
59
  extends Plugin
44
- implements CameraXView.CameraXViewListener {
60
+ implements CameraPreviewListener {
45
61
 
46
62
  static final String CAMERA_WITH_AUDIO_PERMISSION_ALIAS = "cameraWithAudio";
47
63
  static final String CAMERA_ONLY_PERMISSION_ALIAS = "cameraOnly";
64
+ static final String CAMERA_WITH_LOCATION_PERMISSION_ALIAS = "cameraWithLocation";
48
65
 
49
66
  private String captureCallbackId = "";
50
67
  private String snapshotCallbackId = "";
51
68
  private String cameraStartCallbackId = "";
52
69
  private int previousOrientationRequest = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
53
70
  private CameraXView cameraXView;
71
+ private FusedLocationProviderClient fusedLocationClient;
72
+ private Location lastLocation;
54
73
 
55
74
  @PluginMethod
56
75
  public void start(PluginCall call) {
@@ -87,12 +106,56 @@ public class CameraPreview
87
106
  return;
88
107
  }
89
108
 
109
+ final boolean withExifLocation = call.getBoolean("withExifLocation", false);
110
+
111
+ if (withExifLocation) {
112
+ if (getPermissionState(CAMERA_WITH_LOCATION_PERMISSION_ALIAS) != PermissionState.GRANTED) {
113
+ requestPermissionForAlias(CAMERA_WITH_LOCATION_PERMISSION_ALIAS, call, "captureWithLocationPermission");
114
+ } else {
115
+ getLocationAndCapture(call);
116
+ }
117
+ } else {
118
+ captureWithoutLocation(call);
119
+ }
120
+ }
121
+
122
+ @PermissionCallback
123
+ private void captureWithLocationPermission(PluginCall call) {
124
+ if (getPermissionState(CAMERA_WITH_LOCATION_PERMISSION_ALIAS) == PermissionState.GRANTED) {
125
+ getLocationAndCapture(call);
126
+ } else {
127
+ Logger.warn("Location permission denied. Capturing photo without location data.");
128
+ captureWithoutLocation(call);
129
+ }
130
+ }
131
+
132
+ private void getLocationAndCapture(PluginCall call) {
133
+ if (fusedLocationClient == null) {
134
+ fusedLocationClient = LocationServices.getFusedLocationProviderClient(getContext());
135
+ }
136
+ fusedLocationClient.getLastLocation().addOnSuccessListener(getActivity(), location -> {
137
+ lastLocation = location;
138
+ proceedWithCapture(call, lastLocation);
139
+ }).addOnFailureListener(e -> {
140
+ Logger.error("Failed to get location: " + e.getMessage());
141
+ proceedWithCapture(call, null);
142
+ });
143
+ }
144
+
145
+ private void captureWithoutLocation(PluginCall call) {
146
+ proceedWithCapture(call, null);
147
+ }
148
+
149
+ private void proceedWithCapture(PluginCall call, Location location) {
90
150
  bridge.saveCall(call);
91
151
  captureCallbackId = call.getCallbackId();
92
152
 
93
153
  Integer quality = Objects.requireNonNull(call.getInt("quality", 85));
94
- final boolean saveToGallery = Boolean.TRUE.equals(call.getBoolean("saveToGallery", false));
95
- cameraXView.capturePhoto(quality, saveToGallery);
154
+ final boolean saveToGallery = call.getBoolean("saveToGallery", false);
155
+ Integer width = call.getInt("width");
156
+ Integer height = call.getInt("height");
157
+
158
+ cameraXView.capturePhoto(quality, saveToGallery, width, height, location);
96
159
  }
97
160
 
98
161
  @PluginMethod
@@ -236,7 +299,7 @@ public class CameraPreview
236
299
  }
237
300
  rear.put("supportedPictureSizes", rearSizesJs);
238
301
  supportedPictureSizesResult.put(rear);
239
-
302
+
240
303
  List<Size> frontSizes = CameraXView.getSupportedPictureSizes("front");
241
304
  JSObject front = new JSObject();
242
305
  front.put("facing", "front");
@@ -249,7 +312,7 @@ public class CameraPreview
249
312
  }
250
313
  front.put("supportedPictureSizes", frontSizesJs);
251
314
  supportedPictureSizesResult.put(front);
252
-
315
+
253
316
  JSObject ret = new JSObject();
254
317
  ret.put("supportedPictureSizes", supportedPictureSizesResult);
255
318
  call.resolve(ret);
@@ -334,7 +397,9 @@ public class CameraPreview
334
397
  final boolean disableExifHeaderStripping = Boolean.TRUE.equals(call.getBoolean("disableExifHeaderStripping", false));
335
398
  final boolean lockOrientation = Boolean.TRUE.equals(call.getBoolean("lockAndroidOrientation", false));
336
399
  final boolean disableAudio = Boolean.TRUE.equals(call.getBoolean("disableAudio", true));
337
-
400
+ final String aspectRatio = call.getString("aspectRatio", "fill");
401
+ final String gridMode = call.getString("gridMode", "none");
402
+
338
403
  float targetZoom = 1.0f;
339
404
  // Check if the selected device is a physical ultra-wide
340
405
  if (originalDeviceId != null) {
@@ -346,7 +411,7 @@ public class CameraPreview
346
411
  Log.d("CameraPreview", "Ultra-wide lens selected. Targeting 0.5x zoom on logical camera.");
347
412
  targetZoom = 0.5f;
348
413
  // Force the use of the logical camera by clearing the specific deviceId
349
- deviceId = null;
414
+ deviceId = null;
350
415
  break;
351
416
  }
352
417
  }
@@ -357,7 +422,7 @@ public class CameraPreview
357
422
 
358
423
  previousOrientationRequest = getBridge().getActivity().getRequestedOrientation();
359
424
  cameraXView = new CameraXView(getContext(), getBridge().getWebView());
360
- cameraXView.setListener(this);
425
+ cameraXView.setListener((CameraXView.CameraXViewListener) this);
361
426
 
362
427
  String finalDeviceId = deviceId;
363
428
  float finalTargetZoom = targetZoom;
@@ -372,9 +437,9 @@ public class CameraPreview
372
437
  int computedHeight = height != 0 ? (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, height, metrics) : getBridge().getWebView().getHeight();
373
438
  computedHeight -= (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, paddingBottom, metrics);
374
439
 
375
- CameraSessionConfiguration config = new CameraSessionConfiguration(finalDeviceId, position, computedX, computedY, computedWidth, computedHeight, paddingBottom, toBack, storeToFile, enableOpacity, enableZoom, disableExifHeaderStripping, disableAudio, 1.0f);
440
+ CameraSessionConfiguration config = new CameraSessionConfiguration(finalDeviceId, position, computedX, computedY, computedWidth, computedHeight, paddingBottom, toBack, storeToFile, enableOpacity, enableZoom, disableExifHeaderStripping, disableAudio, 1.0f, aspectRatio, gridMode);
376
441
  config.setTargetZoom(finalTargetZoom);
377
-
442
+
378
443
  bridge.saveCall(call);
379
444
  cameraStartCallbackId = call.getCallbackId();
380
445
  cameraXView.startSession(config);
@@ -408,33 +473,50 @@ public class CameraPreview
408
473
  }
409
474
 
410
475
  @Override
411
- public void onSampleTaken(String result) {
412
- JSObject jsObject = new JSObject();
413
- jsObject.put("value", result);
414
- bridge.getSavedCall(snapshotCallbackId).resolve(jsObject);
476
+ public void onCaptureStarted() {
477
+ Log.i("CameraPreview", "Capture started");
415
478
  }
416
479
 
417
480
  @Override
418
- public void onSampleTakenError(String message) {
419
- bridge.getSavedCall(snapshotCallbackId).reject(message);
481
+ public void onCameraStarted(int width, int height, int x, int y) {
482
+ PluginCall call = bridge.getSavedCall(cameraStartCallbackId);
483
+ if (call != null) {
484
+ JSObject result = new JSObject();
485
+ result.put("width", width);
486
+ result.put("height", height);
487
+ result.put("x", x);
488
+ result.put("y", y);
489
+ call.resolve(result);
490
+ bridge.releaseCall(call);
491
+ cameraStartCallbackId = null; // Prevent re-use
492
+ }
420
493
  }
421
494
 
422
495
  @Override
423
- public void onCameraStarted() {
424
- PluginCall pluginCall = bridge.getSavedCall(cameraStartCallbackId);
425
- if (pluginCall != null) {
426
- pluginCall.resolve();
427
- bridge.releaseCall(pluginCall);
428
- }
496
+ public void onCameraStopped() {
497
+ // This method is no longer needed as onCameraStarted handles the promise resolution.
429
498
  }
430
499
 
431
- @Override
432
- public void onCameraStartError(String message) {
433
- PluginCall pluginCall = bridge.getSavedCall(cameraStartCallbackId);
434
- if (pluginCall != null) {
435
- pluginCall.reject(message);
436
- bridge.releaseCall(pluginCall);
500
+ @PluginMethod
501
+ public void setAspectRatio(PluginCall call) {
502
+ if (cameraXView == null || !cameraXView.isRunning()) {
503
+ call.reject("Camera is not running");
504
+ return;
437
505
  }
506
+ String aspectRatio = call.getString("aspectRatio", "fill");
507
+ cameraXView.setAspectRatio(aspectRatio);
508
+ call.resolve();
438
509
  }
439
510
 
511
+ @PluginMethod
512
+ public void getAspectRatio(PluginCall call) {
513
+ if (cameraXView == null || !cameraXView.isRunning()) {
514
+ call.reject("Camera is not running");
515
+ return;
516
+ }
517
+ String aspectRatio = cameraXView.getAspectRatio();
518
+ JSObject ret = new JSObject();
519
+ ret.put("aspectRatio", aspectRatio);
520
+ call.resolve(ret);
521
+ }
440
522
  }