@capgo/camera-preview 7.4.0-alpha.24 → 7.4.0-alpha.27
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.
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
package com.ahm.capacitor.camera.preview;
|
|
2
2
|
|
|
3
|
+
import static androidx.core.content.ContextCompat.getSystemService;
|
|
4
|
+
|
|
3
5
|
import android.content.Context;
|
|
4
6
|
import android.content.res.Configuration;
|
|
5
7
|
import android.graphics.Bitmap;
|
|
@@ -21,10 +23,13 @@ import android.util.Size;
|
|
|
21
23
|
import android.view.MotionEvent;
|
|
22
24
|
import android.view.View;
|
|
23
25
|
import android.view.ViewGroup;
|
|
26
|
+
import android.view.WindowManager;
|
|
27
|
+
import android.view.WindowMetrics;
|
|
24
28
|
import android.webkit.WebView;
|
|
25
29
|
import android.widget.FrameLayout;
|
|
26
30
|
import androidx.annotation.NonNull;
|
|
27
31
|
import androidx.annotation.OptIn;
|
|
32
|
+
import androidx.annotation.RequiresApi;
|
|
28
33
|
import androidx.camera.camera2.interop.Camera2CameraInfo;
|
|
29
34
|
import androidx.camera.camera2.interop.ExperimentalCamera2Interop;
|
|
30
35
|
import androidx.camera.core.AspectRatio;
|
|
@@ -447,10 +452,29 @@ public class CameraXView implements LifecycleOwner, LifecycleObserver {
|
|
|
447
452
|
String aspectRatio = sessionConfig.getAspectRatio();
|
|
448
453
|
|
|
449
454
|
// Get comprehensive display information
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
455
|
+
int screenWidthPx, screenHeightPx;
|
|
456
|
+
float density;
|
|
457
|
+
|
|
458
|
+
// Get density using DisplayMetrics (available on all API levels)
|
|
459
|
+
WindowManager windowManager = (WindowManager) this.context.getSystemService(
|
|
460
|
+
Context.WINDOW_SERVICE
|
|
461
|
+
);
|
|
462
|
+
DisplayMetrics displayMetrics = new DisplayMetrics();
|
|
463
|
+
windowManager.getDefaultDisplay().getMetrics(displayMetrics);
|
|
464
|
+
density = displayMetrics.density;
|
|
465
|
+
|
|
466
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
|
467
|
+
// API 30+ (Android 11+) - use WindowMetrics for screen dimensions
|
|
468
|
+
WindowMetrics metrics = windowManager.getCurrentWindowMetrics();
|
|
469
|
+
Rect bounds = metrics.getBounds();
|
|
470
|
+
screenWidthPx = bounds.width();
|
|
471
|
+
screenHeightPx = bounds.height();
|
|
472
|
+
} else {
|
|
473
|
+
// API < 30 - use legacy DisplayMetrics for screen dimensions
|
|
474
|
+
screenWidthPx = displayMetrics.widthPixels;
|
|
475
|
+
screenHeightPx = displayMetrics.heightPixels;
|
|
476
|
+
}
|
|
477
|
+
|
|
454
478
|
int screenWidthDp = (int) (screenWidthPx / density);
|
|
455
479
|
int screenHeightDp = (int) (screenHeightPx / density);
|
|
456
480
|
|
|
@@ -544,8 +568,8 @@ public class CameraXView implements LifecycleOwner, LifecycleObserver {
|
|
|
544
568
|
);
|
|
545
569
|
|
|
546
570
|
// For centered mode with aspect ratio, calculate maximum size that fits
|
|
547
|
-
int availableWidth =
|
|
548
|
-
int availableHeight =
|
|
571
|
+
int availableWidth = screenWidthPx;
|
|
572
|
+
int availableHeight = screenHeightPx;
|
|
549
573
|
|
|
550
574
|
Log.d(
|
|
551
575
|
TAG,
|
|
@@ -3091,10 +3115,28 @@ public class CameraXView implements LifecycleOwner, LifecycleObserver {
|
|
|
3091
3115
|
);
|
|
3092
3116
|
|
|
3093
3117
|
// Get comprehensive display information
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3118
|
+
WindowManager windowManager = (WindowManager) this.context.getSystemService(
|
|
3119
|
+
Context.WINDOW_SERVICE
|
|
3120
|
+
);
|
|
3121
|
+
int screenWidthPx, screenHeightPx;
|
|
3122
|
+
float density;
|
|
3123
|
+
|
|
3124
|
+
// Get density using DisplayMetrics (available on all API levels)
|
|
3125
|
+
DisplayMetrics displayMetrics = new DisplayMetrics();
|
|
3126
|
+
windowManager.getDefaultDisplay().getMetrics(displayMetrics);
|
|
3127
|
+
density = displayMetrics.density;
|
|
3128
|
+
|
|
3129
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
|
3130
|
+
// API 30+ (Android 11+) - use WindowMetrics for screen dimensions
|
|
3131
|
+
WindowMetrics metrics = windowManager.getCurrentWindowMetrics();
|
|
3132
|
+
Rect bounds = metrics.getBounds();
|
|
3133
|
+
screenWidthPx = bounds.width();
|
|
3134
|
+
screenHeightPx = bounds.height();
|
|
3135
|
+
} else {
|
|
3136
|
+
// API < 30 - use legacy DisplayMetrics for screen dimensions
|
|
3137
|
+
screenWidthPx = displayMetrics.widthPixels;
|
|
3138
|
+
screenHeightPx = displayMetrics.heightPixels;
|
|
3139
|
+
}
|
|
3098
3140
|
|
|
3099
3141
|
// Get WebView dimensions
|
|
3100
3142
|
int webViewWidth = webView.getWidth();
|
|
@@ -504,23 +504,23 @@ extension CameraController {
|
|
|
504
504
|
dataOutput?.connections.forEach { $0.videoOrientation = videoOrientation }
|
|
505
505
|
photoOutput?.connections.forEach { $0.videoOrientation = videoOrientation }
|
|
506
506
|
}
|
|
507
|
-
|
|
507
|
+
|
|
508
508
|
private func setDefaultZoomAfterFlip() {
|
|
509
509
|
let device = (currentCameraPosition == .rear) ? rearCamera : frontCamera
|
|
510
510
|
guard let device = device else {
|
|
511
511
|
print("[CameraPreview] No device available for default zoom after flip")
|
|
512
512
|
return
|
|
513
513
|
}
|
|
514
|
-
|
|
514
|
+
|
|
515
515
|
// Set zoom to 1.0x in UI terms, accounting for display multiplier
|
|
516
516
|
let multiplier = self.getDisplayZoomMultiplier()
|
|
517
517
|
let targetUIZoom: Float = 1.0 // We want 1.0x in the UI
|
|
518
518
|
let nativeZoom = multiplier != 1.0 ? (targetUIZoom / multiplier) : targetUIZoom
|
|
519
|
-
|
|
519
|
+
|
|
520
520
|
let minZoom = device.minAvailableVideoZoomFactor
|
|
521
521
|
let maxZoom = min(device.maxAvailableVideoZoomFactor, saneMaxZoomFactor)
|
|
522
522
|
let clampedZoom = max(minZoom, min(CGFloat(nativeZoom), maxZoom))
|
|
523
|
-
|
|
523
|
+
|
|
524
524
|
do {
|
|
525
525
|
try device.lockForConfiguration()
|
|
526
526
|
device.videoZoomFactor = clampedZoom
|
|
@@ -621,7 +621,7 @@ extension CameraController {
|
|
|
621
621
|
|
|
622
622
|
// Update video orientation
|
|
623
623
|
self.updateVideoOrientation()
|
|
624
|
-
|
|
624
|
+
|
|
625
625
|
// Set default 1.0 zoom level after camera switch to prevent iOS 18+ zoom jumps
|
|
626
626
|
DispatchQueue.main.async { [weak self] in
|
|
627
627
|
self?.setDefaultZoomAfterFlip()
|
|
@@ -170,18 +170,62 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
|
|
|
170
170
|
}
|
|
171
171
|
|
|
172
172
|
var values: [Float] = []
|
|
173
|
-
if hasUltraWide {
|
|
173
|
+
if hasUltraWide {
|
|
174
|
+
values.append(0.5)
|
|
175
|
+
}
|
|
174
176
|
if hasWide {
|
|
175
177
|
values.append(1.0)
|
|
176
|
-
|
|
178
|
+
if self.isProModelSupportingOptical2x() {
|
|
179
|
+
values.append(2.0)
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
if hasTele {
|
|
183
|
+
// Use the virtual device's switch-over zoom factors when available
|
|
184
|
+
let displayMultiplier = self.cameraController.getDisplayZoomMultiplier()
|
|
185
|
+
var teleStep: Float
|
|
186
|
+
|
|
187
|
+
if #available(iOS 13.0, *) {
|
|
188
|
+
let switchFactors = device.virtualDeviceSwitchOverVideoZoomFactors
|
|
189
|
+
if !switchFactors.isEmpty {
|
|
190
|
+
// Choose the highest switch-over factor (typically the wide->tele threshold)
|
|
191
|
+
let maxSwitch = switchFactors.map { $0.floatValue }.max() ?? Float(device.maxAvailableVideoZoomFactor)
|
|
192
|
+
teleStep = maxSwitch * displayMultiplier
|
|
193
|
+
} else {
|
|
194
|
+
teleStep = Float(device.maxAvailableVideoZoomFactor) * displayMultiplier
|
|
195
|
+
}
|
|
196
|
+
} else {
|
|
197
|
+
teleStep = Float(device.maxAvailableVideoZoomFactor) * displayMultiplier
|
|
198
|
+
}
|
|
199
|
+
values.append(teleStep)
|
|
177
200
|
}
|
|
178
|
-
if hasTele { values.append(3.0) }
|
|
179
201
|
|
|
180
202
|
// Deduplicate and sort
|
|
181
203
|
let uniqueSorted = Array(Set(values)).sorted()
|
|
182
204
|
call.resolve(["values": uniqueSorted])
|
|
183
205
|
}
|
|
184
206
|
|
|
207
|
+
private func isProModelSupportingOptical2x() -> Bool {
|
|
208
|
+
// Detects iPhone 14 Pro/Pro Max, 15 Pro/Pro Max, and 16 Pro/Pro Max
|
|
209
|
+
var systemInfo = utsname()
|
|
210
|
+
uname(&systemInfo)
|
|
211
|
+
let mirror = Mirror(reflecting: systemInfo.machine)
|
|
212
|
+
let identifier = mirror.children.reduce("") { partialResult, element in
|
|
213
|
+
guard let value = element.value as? Int8, value != 0 else { return partialResult }
|
|
214
|
+
return partialResult + String(UnicodeScalar(UInt8(value)))
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Known identifiers: 14 Pro (iPhone15,2), 14 Pro Max (iPhone15,3),
|
|
218
|
+
// 15 Pro (iPhone16,1), 15 Pro Max (iPhone16,2),
|
|
219
|
+
// 16 Pro (iPhone17,1), 16 Pro Max (iPhone17,2),
|
|
220
|
+
// 17 Pro (iPhone18,1), 17 Pro Max (iPhone18,2)
|
|
221
|
+
let supportedIdentifiers: Set<String> = [
|
|
222
|
+
"iPhone15,2", "iPhone15,3", // 14 Pro / 14 Pro Max
|
|
223
|
+
"iPhone16,1", "iPhone16,2", // 15 Pro / 15 Pro Max
|
|
224
|
+
"iPhone17,1", "iPhone17,2" // 16 Pro / 16 Pro Max
|
|
225
|
+
]
|
|
226
|
+
return supportedIdentifiers.contains(identifier)
|
|
227
|
+
}
|
|
228
|
+
|
|
185
229
|
@objc func rotated() {
|
|
186
230
|
guard let previewView = self.previewView,
|
|
187
231
|
let posX = self.posX,
|