@capgo/camera-preview 8.11.9 → 8.11.11
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 +54 -1
- package/android/build.gradle +0 -1
- package/android/gradle/wrapper/gradle-wrapper.properties +1 -1
- package/android/src/main/java/app/capgo/capacitor/camera/preview/CameraPreview.java +111 -126
- package/android/src/main/java/app/capgo/capacitor/camera/preview/CameraXView.java +464 -163
- package/android/src/main/java/app/capgo/capacitor/camera/preview/GridOverlayView.java +2 -2
- package/dist/docs.json +97 -0
- package/dist/esm/definitions.d.ts +31 -0
- package/dist/esm/definitions.js.map +1 -1
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js.map +1 -1
- package/ios/Sources/CapgoCameraPreviewPlugin/AspectRatioLayout.swift +107 -0
- package/ios/Sources/CapgoCameraPreviewPlugin/CameraController.swift +271 -12
- package/ios/Sources/CapgoCameraPreviewPlugin/Plugin.swift +175 -55
- package/ios/Tests/CameraPreviewPluginTests/CameraPreviewPluginTests.swift +150 -9
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ Show a live camera preview inside your Capacitor app, behind or around your own
|
|
|
5
5
|
<a href="https://capgo.app/?ref=plugin_camera_preview"><img src="https://capgo.app/readme-banner.svg?repo=Cap-go/capacitor-camera-preview" alt="Capgo - Instant updates for Capacitor" /></a>
|
|
6
6
|
|
|
7
7
|
<div align="center">
|
|
8
|
-
<p><b>Capgo</b>:
|
|
8
|
+
<p><b>Capgo</b>: push fixes to your Capacitor users in minutes, build signed iOS and Android apps without a Mac, and roll back in one click.</p>
|
|
9
9
|
<h2><a href="https://capgo.app/register/?ref=plugin_camera_preview">➡️ Get started for free</a></h2>
|
|
10
10
|
<p>14-day unlimited free trial. No credit card required</p>
|
|
11
11
|
<p><a href="https://capgo.app/consulting/?ref=plugin_camera_preview">Missing a feature? We'll build the plugin for you 💪</a></p>
|
|
@@ -434,6 +434,8 @@ Documentation for the [uploader](https://github.com/Cap-go/capacitor-uploader)
|
|
|
434
434
|
* [`addListener('barcodeScanned', ...)`](#addlistenerbarcodescanned-)
|
|
435
435
|
* [`addListener('barcodeScanError', ...)`](#addlistenerbarcodescanerror-)
|
|
436
436
|
* [`addListener('recordingFinished', ...)`](#addlistenerrecordingfinished-)
|
|
437
|
+
* [`addListener('cameraInterrupted', ...)`](#addlistenercamerainterrupted-)
|
|
438
|
+
* [`addListener('cameraInterruptionEnded', ...)`](#addlistenercamerainterruptionended-)
|
|
437
439
|
* [`deleteFile(...)`](#deletefile)
|
|
438
440
|
* [`getSafeAreaInsets()`](#getsafeareainsets)
|
|
439
441
|
* [`getOrientation()`](#getorientation)
|
|
@@ -1259,6 +1261,47 @@ Adds a listener fired when a video recording finishes natively, including automa
|
|
|
1259
1261
|
--------------------
|
|
1260
1262
|
|
|
1261
1263
|
|
|
1264
|
+
### addListener('cameraInterrupted', ...)
|
|
1265
|
+
|
|
1266
|
+
```typescript
|
|
1267
|
+
addListener(eventName: 'cameraInterrupted', listenerFunc: (data: CameraInterruptedEvent) => void) => Promise<PluginListenerHandle>
|
|
1268
|
+
```
|
|
1269
|
+
|
|
1270
|
+
Adds a listener for capture session interruptions (for example an active phone call).
|
|
1271
|
+
|
|
1272
|
+
| Param | Type |
|
|
1273
|
+
| ------------------ | -------------------------------------------------------------------------------------------- |
|
|
1274
|
+
| **`eventName`** | <code>'cameraInterrupted'</code> |
|
|
1275
|
+
| **`listenerFunc`** | <code>(data: <a href="#camerainterruptedevent">CameraInterruptedEvent</a>) => void</code> |
|
|
1276
|
+
|
|
1277
|
+
**Returns:** <code>Promise<<a href="#pluginlistenerhandle">PluginListenerHandle</a>></code>
|
|
1278
|
+
|
|
1279
|
+
**Since:** 8.11.7
|
|
1280
|
+
|
|
1281
|
+
--------------------
|
|
1282
|
+
|
|
1283
|
+
|
|
1284
|
+
### addListener('cameraInterruptionEnded', ...)
|
|
1285
|
+
|
|
1286
|
+
```typescript
|
|
1287
|
+
addListener(eventName: 'cameraInterruptionEnded', listenerFunc: () => void) => Promise<PluginListenerHandle>
|
|
1288
|
+
```
|
|
1289
|
+
|
|
1290
|
+
Adds a listener fired when a capture session interruption ends.
|
|
1291
|
+
Native recovery may still be restarting the session; wait for preview frames before assuming the stream is live.
|
|
1292
|
+
|
|
1293
|
+
| Param | Type |
|
|
1294
|
+
| ------------------ | -------------------------------------- |
|
|
1295
|
+
| **`eventName`** | <code>'cameraInterruptionEnded'</code> |
|
|
1296
|
+
| **`listenerFunc`** | <code>() => void</code> |
|
|
1297
|
+
|
|
1298
|
+
**Returns:** <code>Promise<<a href="#pluginlistenerhandle">PluginListenerHandle</a>></code>
|
|
1299
|
+
|
|
1300
|
+
**Since:** 8.11.7
|
|
1301
|
+
|
|
1302
|
+
--------------------
|
|
1303
|
+
|
|
1304
|
+
|
|
1262
1305
|
### deleteFile(...)
|
|
1263
1306
|
|
|
1264
1307
|
```typescript
|
|
@@ -1724,6 +1767,16 @@ Represents the detailed information of the currently active lens.
|
|
|
1724
1767
|
| **`message`** | <code>string</code> | Native scanner error message. |
|
|
1725
1768
|
|
|
1726
1769
|
|
|
1770
|
+
#### CameraInterruptedEvent
|
|
1771
|
+
|
|
1772
|
+
Emitted when the native capture session is interrupted (for example during a phone call).
|
|
1773
|
+
|
|
1774
|
+
| Prop | Type | Description |
|
|
1775
|
+
| ------------------ | -------------------------------------------- | --------------------------------------------------------------------------------- |
|
|
1776
|
+
| **`reason`** | <code>'runtimeError' \| 'interrupted'</code> | Why the session was interrupted. |
|
|
1777
|
+
| **`audioDropped`** | <code>boolean</code> | When true, the plugin removed the microphone input and continued with video only. |
|
|
1778
|
+
|
|
1779
|
+
|
|
1727
1780
|
#### SafeAreaInsets
|
|
1728
1781
|
|
|
1729
1782
|
Represents safe area insets for devices.
|
package/android/build.gradle
CHANGED
|
@@ -68,7 +68,6 @@ dependencies {
|
|
|
68
68
|
implementation "androidx.camera:camera-lifecycle:${camerax_version}"
|
|
69
69
|
implementation "androidx.camera:camera-view:${camerax_version}"
|
|
70
70
|
implementation "androidx.camera:camera-extensions:${camerax_version}"
|
|
71
|
-
implementation 'com.google.guava:guava:33.7.2-android'
|
|
72
71
|
implementation 'com.google.android.gms:play-services-mlkit-barcode-scanning:18.3.1'
|
|
73
72
|
|
|
74
73
|
testImplementation "junit:junit:$junitVersion"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
distributionBase=GRADLE_USER_HOME
|
|
2
2
|
distributionPath=wrapper/dists
|
|
3
|
-
distributionUrl=https\://services.gradle.org/distributions/gradle-
|
|
3
|
+
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.5-bin.zip
|
|
4
4
|
networkTimeout=10000
|
|
5
5
|
validateDistributionUrl=true
|
|
6
6
|
zipStoreBase=GRADLE_USER_HOME
|
|
@@ -135,10 +135,9 @@ public class CameraPreview extends Plugin implements CameraXView.CameraXViewList
|
|
|
135
135
|
static final String CAMERA_WITH_LOCATION_PERMISSION_ALIAS = "cameraWithLocation";
|
|
136
136
|
static final String MICROPHONE_ONLY_PERMISSION_ALIAS = "microphoneOnly";
|
|
137
137
|
|
|
138
|
-
private
|
|
139
|
-
private
|
|
140
|
-
private
|
|
141
|
-
private PluginCall pendingStopRecordCall;
|
|
138
|
+
private String captureCallbackId = "";
|
|
139
|
+
private String sampleCallbackId = "";
|
|
140
|
+
private String cameraStartCallbackId = "";
|
|
142
141
|
private final Object pendingStartLock = new Object();
|
|
143
142
|
private PluginCall pendingStartCall;
|
|
144
143
|
private int previousOrientationRequest = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
|
|
@@ -490,23 +489,21 @@ public class CameraPreview extends Plugin implements CameraXView.CameraXViewList
|
|
|
490
489
|
if (fusedLocationClient == null) {
|
|
491
490
|
fusedLocationClient = LocationServices.getFusedLocationProviderClient(getContext());
|
|
492
491
|
}
|
|
493
|
-
fusedLocationClient
|
|
494
|
-
.
|
|
495
|
-
|
|
496
|
-
if (task.isCanceled()) {
|
|
497
|
-
Logger.warn("Location lookup cancelled. Capturing photo without location data.");
|
|
498
|
-
proceedWithCapture(call, null);
|
|
499
|
-
return;
|
|
500
|
-
}
|
|
501
|
-
if (task.isSuccessful()) {
|
|
502
|
-
lastLocation = task.getResult();
|
|
503
|
-
proceedWithCapture(call, lastLocation);
|
|
504
|
-
return;
|
|
505
|
-
}
|
|
506
|
-
Exception error = task.getException();
|
|
507
|
-
Logger.error("Failed to get location: " + (error != null ? error.getMessage() : "unknown error"));
|
|
492
|
+
fusedLocationClient.getLastLocation().addOnCompleteListener((task) -> {
|
|
493
|
+
if (task.isCanceled()) {
|
|
494
|
+
Logger.warn("Location lookup cancelled. Capturing photo without location data.");
|
|
508
495
|
proceedWithCapture(call, null);
|
|
509
|
-
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
if (task.isSuccessful()) {
|
|
499
|
+
lastLocation = task.getResult();
|
|
500
|
+
proceedWithCapture(call, lastLocation);
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
503
|
+
Exception error = task.getException();
|
|
504
|
+
Logger.error("Failed to get location: " + (error != null ? error.getMessage() : "unknown error"));
|
|
505
|
+
proceedWithCapture(call, null);
|
|
506
|
+
});
|
|
510
507
|
}
|
|
511
508
|
|
|
512
509
|
private void captureWithoutLocation(PluginCall call) {
|
|
@@ -514,8 +511,8 @@ public class CameraPreview extends Plugin implements CameraXView.CameraXViewList
|
|
|
514
511
|
}
|
|
515
512
|
|
|
516
513
|
private void proceedWithCapture(PluginCall call, Location location) {
|
|
517
|
-
|
|
518
|
-
|
|
514
|
+
bridge.saveCall(call);
|
|
515
|
+
captureCallbackId = call.getCallbackId();
|
|
519
516
|
|
|
520
517
|
Integer quality = Objects.requireNonNull(call.getInt("quality", 85));
|
|
521
518
|
final boolean saveToGallery = Boolean.TRUE.equals(call.getBoolean("saveToGallery"));
|
|
@@ -534,8 +531,8 @@ public class CameraPreview extends Plugin implements CameraXView.CameraXViewList
|
|
|
534
531
|
call.reject("Camera is not running");
|
|
535
532
|
return;
|
|
536
533
|
}
|
|
537
|
-
|
|
538
|
-
|
|
534
|
+
bridge.saveCall(call);
|
|
535
|
+
sampleCallbackId = call.getCallbackId();
|
|
539
536
|
Integer quality = Objects.requireNonNull(call.getInt("quality", 85));
|
|
540
537
|
final boolean mirrorFrontCamera = Boolean.TRUE.equals(call.getBoolean("mirrorFrontCamera"));
|
|
541
538
|
cameraXView.captureSample(quality, mirrorFrontCamera);
|
|
@@ -809,39 +806,37 @@ public class CameraPreview extends Plugin implements CameraXView.CameraXViewList
|
|
|
809
806
|
public void stop(final PluginCall call) {
|
|
810
807
|
boolean force = Boolean.TRUE.equals(call.getBoolean("force", false));
|
|
811
808
|
|
|
812
|
-
bridge
|
|
813
|
-
.getActivity()
|
|
814
|
-
.runOnUiThread(() -> {
|
|
815
|
-
getBridge().getActivity().setRequestedOrientation(previousOrientationRequest);
|
|
809
|
+
bridge.getActivity().runOnUiThread(() -> {
|
|
810
|
+
getBridge().getActivity().setRequestedOrientation(previousOrientationRequest);
|
|
816
811
|
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
812
|
+
// Disable and clear orientation listener
|
|
813
|
+
if (orientationListener != null) {
|
|
814
|
+
orientationListener.disable();
|
|
815
|
+
orientationListener = null;
|
|
816
|
+
lastOrientation = Configuration.ORIENTATION_UNDEFINED;
|
|
817
|
+
}
|
|
823
818
|
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
819
|
+
// Remove any rotation overlay if present
|
|
820
|
+
if (rotationOverlay != null && rotationOverlay.getParent() != null) {
|
|
821
|
+
((ViewGroup) rotationOverlay.getParent()).removeView(rotationOverlay);
|
|
822
|
+
rotationOverlay = null;
|
|
823
|
+
}
|
|
829
824
|
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
}
|
|
825
|
+
if (cameraXView != null) {
|
|
826
|
+
cameraXView.stopSession();
|
|
827
|
+
// If force is true, always drop the reference
|
|
828
|
+
// Otherwise only drop the reference if no deferred stop is pending
|
|
829
|
+
if (force || !cameraXView.isStopDeferred()) {
|
|
830
|
+
cameraXView = null;
|
|
837
831
|
}
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
832
|
+
}
|
|
833
|
+
// Manual stops should not trigger automatic resume with stale config
|
|
834
|
+
lastSessionConfig = null;
|
|
835
|
+
clearActiveBarcodeScanner();
|
|
836
|
+
toBackVisualStateActive = false;
|
|
837
|
+
restoreWebViewVisualState();
|
|
838
|
+
call.resolve();
|
|
839
|
+
});
|
|
845
840
|
}
|
|
846
841
|
|
|
847
842
|
@PluginMethod
|
|
@@ -1229,9 +1224,8 @@ public class CameraPreview extends Plugin implements CameraXView.CameraXViewList
|
|
|
1229
1224
|
result.put("microphone", mapPermissionState(audioState));
|
|
1230
1225
|
}
|
|
1231
1226
|
|
|
1232
|
-
boolean showSettingsAlert =
|
|
1233
|
-
? Boolean.TRUE.equals(call.getBoolean("showSettingsAlert"))
|
|
1234
|
-
: false;
|
|
1227
|
+
boolean showSettingsAlert =
|
|
1228
|
+
call.getBoolean("showSettingsAlert") != null ? Boolean.TRUE.equals(call.getBoolean("showSettingsAlert")) : false;
|
|
1235
1229
|
|
|
1236
1230
|
String cameraStateString = result.getString("camera");
|
|
1237
1231
|
boolean cameraNeedsSettings = "denied".equals(cameraStateString) || "prompt-with-rationale".equals(cameraStateString);
|
|
@@ -1279,12 +1273,10 @@ public class CameraPreview extends Plugin implements CameraXView.CameraXViewList
|
|
|
1279
1273
|
String originalDeviceId = call.getString("deviceId");
|
|
1280
1274
|
String deviceId = originalDeviceId; // Use a mutable variable
|
|
1281
1275
|
|
|
1282
|
-
final String position =
|
|
1283
|
-
|
|
1284
|
-
"
|
|
1285
|
-
"
|
|
1286
|
-
? "back"
|
|
1287
|
-
: "front";
|
|
1276
|
+
final String position =
|
|
1277
|
+
positionParam == null || positionParam.isEmpty() || "rear".equals(positionParam) || "back".equals(positionParam)
|
|
1278
|
+
? "back"
|
|
1279
|
+
: "front";
|
|
1288
1280
|
// Use -1 as default to indicate centering is needed when x/y not provided
|
|
1289
1281
|
final Integer xParam = call.getInt("x");
|
|
1290
1282
|
final Integer yParam = call.getInt("y");
|
|
@@ -1611,7 +1603,7 @@ public class CameraPreview extends Plugin implements CameraXView.CameraXViewList
|
|
|
1611
1603
|
Log.d("CameraPreview", "========================");
|
|
1612
1604
|
|
|
1613
1605
|
// Pass along whether we're centering so CameraXView knows not to add insets
|
|
1614
|
-
boolean isCentered =
|
|
1606
|
+
boolean isCentered = x == -1 || y == -1;
|
|
1615
1607
|
|
|
1616
1608
|
CameraSessionConfiguration config = new CameraSessionConfiguration(
|
|
1617
1609
|
finalDeviceId,
|
|
@@ -1643,8 +1635,8 @@ public class CameraPreview extends Plugin implements CameraXView.CameraXViewList
|
|
|
1643
1635
|
clearActiveBarcodeScanner();
|
|
1644
1636
|
}
|
|
1645
1637
|
|
|
1646
|
-
|
|
1647
|
-
|
|
1638
|
+
bridge.saveCall(call);
|
|
1639
|
+
cameraStartCallbackId = call.getCallbackId();
|
|
1648
1640
|
cameraXView.startSession(config);
|
|
1649
1641
|
|
|
1650
1642
|
// Setup orientation listener to mirror iOS screenResize emission
|
|
@@ -1828,24 +1820,21 @@ public class CameraPreview extends Plugin implements CameraXView.CameraXViewList
|
|
|
1828
1820
|
if (rotationOverlay != null && rotationOverlay.getParent() != null) {
|
|
1829
1821
|
// Shorter delay for faster transition
|
|
1830
1822
|
int delay = "4:3".equals(ar) ? 200 : 150;
|
|
1831
|
-
rotationOverlay.postDelayed(
|
|
1832
|
-
()
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
.
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
},
|
|
1847
|
-
delay
|
|
1848
|
-
);
|
|
1823
|
+
rotationOverlay.postDelayed(() -> {
|
|
1824
|
+
if (rotationOverlay != null && rotationOverlay.getParent() != null) {
|
|
1825
|
+
rotationOverlay
|
|
1826
|
+
.animate()
|
|
1827
|
+
.alpha(0f)
|
|
1828
|
+
.setDuration(100) // Faster fade out
|
|
1829
|
+
.withEndAction(() -> {
|
|
1830
|
+
if (rotationOverlay != null && rotationOverlay.getParent() != null) {
|
|
1831
|
+
((ViewGroup) rotationOverlay.getParent()).removeView(rotationOverlay);
|
|
1832
|
+
rotationOverlay = null;
|
|
1833
|
+
}
|
|
1834
|
+
})
|
|
1835
|
+
.start();
|
|
1836
|
+
}
|
|
1837
|
+
}, delay);
|
|
1849
1838
|
}
|
|
1850
1839
|
|
|
1851
1840
|
Log.d(TAG, "================================================================================");
|
|
@@ -1900,7 +1889,7 @@ public class CameraPreview extends Plugin implements CameraXView.CameraXViewList
|
|
|
1900
1889
|
|
|
1901
1890
|
@Override
|
|
1902
1891
|
public void onPictureTaken(String base64, JSONObject exif) {
|
|
1903
|
-
PluginCall pluginCall =
|
|
1892
|
+
PluginCall pluginCall = bridge.getSavedCall(captureCallbackId);
|
|
1904
1893
|
if (pluginCall == null) {
|
|
1905
1894
|
Log.e("CameraPreview", "onPictureTaken: captureCallbackId is null");
|
|
1906
1895
|
return;
|
|
@@ -1909,20 +1898,18 @@ public class CameraPreview extends Plugin implements CameraXView.CameraXViewList
|
|
|
1909
1898
|
result.put("value", base64);
|
|
1910
1899
|
result.put("exif", exif);
|
|
1911
1900
|
pluginCall.resolve(result);
|
|
1912
|
-
|
|
1913
|
-
pendingCaptureCall = null;
|
|
1901
|
+
bridge.releaseCall(pluginCall);
|
|
1914
1902
|
}
|
|
1915
1903
|
|
|
1916
1904
|
@Override
|
|
1917
1905
|
public void onPictureTakenError(String message) {
|
|
1918
|
-
PluginCall pluginCall =
|
|
1906
|
+
PluginCall pluginCall = bridge.getSavedCall(captureCallbackId);
|
|
1919
1907
|
if (pluginCall == null) {
|
|
1920
1908
|
Log.e("CameraPreview", "onPictureTakenError: captureCallbackId is null");
|
|
1921
1909
|
return;
|
|
1922
1910
|
}
|
|
1923
1911
|
pluginCall.reject(message);
|
|
1924
|
-
|
|
1925
|
-
pendingCaptureCall = null;
|
|
1912
|
+
bridge.releaseCall(pluginCall);
|
|
1926
1913
|
}
|
|
1927
1914
|
|
|
1928
1915
|
@Override
|
|
@@ -2105,7 +2092,7 @@ public class CameraPreview extends Plugin implements CameraXView.CameraXViewList
|
|
|
2105
2092
|
// Re-apply WebView transparency after the preview is bound (idempotent safety net for resume).
|
|
2106
2093
|
applyTransparentBackgroundsForToBack();
|
|
2107
2094
|
|
|
2108
|
-
PluginCall call =
|
|
2095
|
+
PluginCall call = bridge.getSavedCall(cameraStartCallbackId);
|
|
2109
2096
|
if (call != null) {
|
|
2110
2097
|
// Convert pixel values back to logical units
|
|
2111
2098
|
DisplayMetrics metrics = getBridge().getActivity().getResources().getDisplayMetrics();
|
|
@@ -2141,7 +2128,7 @@ public class CameraPreview extends Plugin implements CameraXView.CameraXViewList
|
|
|
2141
2128
|
Log.d("CameraPreview", "9. WEBVIEW INSET - " + webViewTopInset);
|
|
2142
2129
|
Log.d(
|
|
2143
2130
|
"CameraPreview",
|
|
2144
|
-
"9b. SAFE AREA - " + (lastIncludeSafeAreaInsets ?
|
|
2131
|
+
"9b. SAFE AREA - " + (lastIncludeSafeAreaInsets ? "ENABLED (inset=" + safeAreaTopInsetPx + ")" : "DISABLED")
|
|
2145
2132
|
);
|
|
2146
2133
|
Log.d(
|
|
2147
2134
|
"CameraPreview",
|
|
@@ -2150,13 +2137,13 @@ public class CameraPreview extends Plugin implements CameraXView.CameraXViewList
|
|
|
2150
2137
|
Log.d(
|
|
2151
2138
|
"CameraPreview",
|
|
2152
2139
|
"11. RETURNED (logical) - x=" +
|
|
2153
|
-
|
|
2140
|
+
x / pixelRatio +
|
|
2154
2141
|
", y=" +
|
|
2155
|
-
|
|
2142
|
+
relativeY / pixelRatio +
|
|
2156
2143
|
", width=" +
|
|
2157
|
-
|
|
2144
|
+
width / pixelRatio +
|
|
2158
2145
|
", height=" +
|
|
2159
|
-
|
|
2146
|
+
height / pixelRatio
|
|
2160
2147
|
);
|
|
2161
2148
|
Log.d("CameraPreview", "12. PIXEL RATIO - " + pixelRatio);
|
|
2162
2149
|
Log.d("CameraPreview", "========================");
|
|
@@ -2275,27 +2262,27 @@ public class CameraPreview extends Plugin implements CameraXView.CameraXViewList
|
|
|
2275
2262
|
|
|
2276
2263
|
private void resolveCameraStartCall(PluginCall call, JSObject result) {
|
|
2277
2264
|
call.resolve(result);
|
|
2278
|
-
|
|
2279
|
-
|
|
2265
|
+
bridge.releaseCall(call);
|
|
2266
|
+
cameraStartCallbackId = null; // Prevent re-use
|
|
2280
2267
|
resetPendingStartBarcodeScanner();
|
|
2281
2268
|
}
|
|
2282
2269
|
|
|
2283
2270
|
private void rejectCameraStartCall(PluginCall call, String message) {
|
|
2284
2271
|
call.reject(message);
|
|
2285
|
-
|
|
2286
|
-
|
|
2272
|
+
bridge.releaseCall(call);
|
|
2273
|
+
cameraStartCallbackId = null;
|
|
2287
2274
|
resetPendingStartBarcodeScanner();
|
|
2288
2275
|
}
|
|
2289
2276
|
|
|
2290
2277
|
@Override
|
|
2291
2278
|
public void onSampleTaken(String result) {
|
|
2292
|
-
PluginCall call =
|
|
2279
|
+
PluginCall call = bridge.getSavedCall(sampleCallbackId);
|
|
2293
2280
|
if (call != null) {
|
|
2294
2281
|
JSObject ret = new JSObject();
|
|
2295
2282
|
ret.put("value", result);
|
|
2296
2283
|
call.resolve(ret);
|
|
2297
|
-
|
|
2298
|
-
|
|
2284
|
+
bridge.releaseCall(call);
|
|
2285
|
+
sampleCallbackId = null;
|
|
2299
2286
|
} else {
|
|
2300
2287
|
Log.w("CameraPreview", "onSampleTaken: no pending call to resolve");
|
|
2301
2288
|
}
|
|
@@ -2303,11 +2290,11 @@ public class CameraPreview extends Plugin implements CameraXView.CameraXViewList
|
|
|
2303
2290
|
|
|
2304
2291
|
@Override
|
|
2305
2292
|
public void onSampleTakenError(String message) {
|
|
2306
|
-
PluginCall call =
|
|
2293
|
+
PluginCall call = bridge.getSavedCall(sampleCallbackId);
|
|
2307
2294
|
if (call != null) {
|
|
2308
2295
|
call.reject(message);
|
|
2309
|
-
|
|
2310
|
-
|
|
2296
|
+
bridge.releaseCall(call);
|
|
2297
|
+
sampleCallbackId = null;
|
|
2311
2298
|
} else {
|
|
2312
2299
|
Log.e("CameraPreview", "Sample taken error (no pending call): " + message);
|
|
2313
2300
|
}
|
|
@@ -2353,11 +2340,11 @@ public class CameraPreview extends Plugin implements CameraXView.CameraXViewList
|
|
|
2353
2340
|
}
|
|
2354
2341
|
}
|
|
2355
2342
|
|
|
2356
|
-
PluginCall call =
|
|
2343
|
+
PluginCall call = bridge.getSavedCall(cameraStartCallbackId);
|
|
2357
2344
|
if (call != null) {
|
|
2358
2345
|
call.reject(message);
|
|
2359
|
-
|
|
2360
|
-
|
|
2346
|
+
bridge.releaseCall(call);
|
|
2347
|
+
cameraStartCallbackId = null;
|
|
2361
2348
|
resetPendingStartBarcodeScanner();
|
|
2362
2349
|
}
|
|
2363
2350
|
|
|
@@ -2515,8 +2502,8 @@ public class CameraPreview extends Plugin implements CameraXView.CameraXViewList
|
|
|
2515
2502
|
final int safeAreaTopInsetPx = lastIncludeSafeAreaInsets ? getSafeAreaTopInsetPx() : 0;
|
|
2516
2503
|
final float pixelRatioFinal = pixelRatio;
|
|
2517
2504
|
|
|
2518
|
-
int x =
|
|
2519
|
-
int y =
|
|
2505
|
+
int x = xParam != null && xParam > 0 ? (int) (xParam * pixelRatio) : 0;
|
|
2506
|
+
int y = yParam != null && yParam > 0 ? (int) (yParam * pixelRatio) : 0;
|
|
2520
2507
|
|
|
2521
2508
|
// Add inset to Y for coordinate conversion if needed.
|
|
2522
2509
|
// - If the WebView is already offset from the screen top, use that.
|
|
@@ -2526,8 +2513,8 @@ public class CameraPreview extends Plugin implements CameraXView.CameraXViewList
|
|
|
2526
2513
|
} else if (!isWebViewOffset && lastIncludeSafeAreaInsets && safeAreaTopInsetPx > 0 && y > 0) {
|
|
2527
2514
|
y += safeAreaTopInsetPx;
|
|
2528
2515
|
}
|
|
2529
|
-
int width =
|
|
2530
|
-
int height =
|
|
2516
|
+
int width = widthParam != null && widthParam > 0 ? (int) (widthParam * pixelRatio) : 0;
|
|
2517
|
+
int height = heightParam != null && heightParam > 0 ? (int) (heightParam * pixelRatio) : 0;
|
|
2531
2518
|
|
|
2532
2519
|
cameraXView.setPreviewSize(x, y, width, height, () -> {
|
|
2533
2520
|
// Return the actual preview bounds after layout operations are complete
|
|
@@ -2597,9 +2584,10 @@ public class CameraPreview extends Plugin implements CameraXView.CameraXViewList
|
|
|
2597
2584
|
|
|
2598
2585
|
@PluginMethod
|
|
2599
2586
|
public void getSupportedVideoQualities(PluginCall call) {
|
|
2600
|
-
List<String> qualities =
|
|
2601
|
-
|
|
2602
|
-
|
|
2587
|
+
List<String> qualities =
|
|
2588
|
+
cameraXView != null
|
|
2589
|
+
? cameraXView.getSupportedVideoQualities()
|
|
2590
|
+
: Arrays.asList("low", "medium", "high", "2160p", "1080p", "720p", "480p", "4:3");
|
|
2603
2591
|
JSONArray arr = new JSONArray();
|
|
2604
2592
|
for (String quality : qualities) {
|
|
2605
2593
|
arr.put(quality);
|
|
@@ -2717,9 +2705,8 @@ public class CameraPreview extends Plugin implements CameraXView.CameraXViewList
|
|
|
2717
2705
|
return;
|
|
2718
2706
|
}
|
|
2719
2707
|
|
|
2720
|
-
boolean disableAudio =
|
|
2721
|
-
? Boolean.TRUE.equals(call.getBoolean("disableAudio"))
|
|
2722
|
-
: this.lastDisableAudio;
|
|
2708
|
+
boolean disableAudio =
|
|
2709
|
+
call.getBoolean("disableAudio") != null ? Boolean.TRUE.equals(call.getBoolean("disableAudio")) : this.lastDisableAudio;
|
|
2723
2710
|
this.lastDisableAudio = disableAudio;
|
|
2724
2711
|
String permissionAlias = disableAudio ? CAMERA_ONLY_PERMISSION_ALIAS : CAMERA_WITH_AUDIO_PERMISSION_ALIAS;
|
|
2725
2712
|
|
|
@@ -2738,30 +2725,28 @@ public class CameraPreview extends Plugin implements CameraXView.CameraXViewList
|
|
|
2738
2725
|
}
|
|
2739
2726
|
|
|
2740
2727
|
try {
|
|
2741
|
-
|
|
2742
|
-
|
|
2728
|
+
bridge.saveCall(call);
|
|
2729
|
+
final String cbId = call.getCallbackId();
|
|
2743
2730
|
cameraXView.stopRecordVideo(
|
|
2744
2731
|
new CameraXView.VideoRecordingCallback() {
|
|
2745
2732
|
@Override
|
|
2746
2733
|
public void onSuccess(String filePath, String reason) {
|
|
2747
|
-
PluginCall saved =
|
|
2748
|
-
pendingStopRecordCall = null;
|
|
2734
|
+
PluginCall saved = bridge.getSavedCall(cbId);
|
|
2749
2735
|
if (saved != null) {
|
|
2750
2736
|
JSObject result = new JSObject();
|
|
2751
2737
|
result.put("videoFilePath", filePath);
|
|
2752
2738
|
result.put("reason", reason);
|
|
2753
2739
|
saved.resolve(result);
|
|
2754
|
-
|
|
2740
|
+
bridge.releaseCall(saved);
|
|
2755
2741
|
}
|
|
2756
2742
|
}
|
|
2757
2743
|
|
|
2758
2744
|
@Override
|
|
2759
2745
|
public void onError(String message) {
|
|
2760
|
-
PluginCall saved =
|
|
2761
|
-
pendingStopRecordCall = null;
|
|
2746
|
+
PluginCall saved = bridge.getSavedCall(cbId);
|
|
2762
2747
|
if (saved != null) {
|
|
2763
2748
|
saved.reject("Failed to stop video recording: " + message);
|
|
2764
|
-
|
|
2749
|
+
bridge.releaseCall(saved);
|
|
2765
2750
|
}
|
|
2766
2751
|
}
|
|
2767
2752
|
}
|