expo-camera 13.9.0 → 14.0.0
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/CHANGELOG.md +10 -0
- package/android/build.gradle +3 -3
- package/android/src/main/java/expo/modules/camera/Events.kt +1 -1
- package/android/src/main/java/expo/modules/camera/ExpoCameraView.kt +2 -2
- package/android/src/main/java/expo/modules/camera/next/CameraViewNextModule.kt +14 -5
- package/android/src/main/java/expo/modules/camera/next/ExpoCameraView.kt +56 -88
- package/android/src/main/java/expo/modules/camera/next/Options.kt +2 -2
- package/android/src/main/java/expo/modules/camera/next/analyzers/BarcodeAnalyzer.kt +1 -1
- package/android/src/main/java/expo/modules/camera/next/records/CameraRecords.kt +24 -1
- package/build/Camera.d.ts +4 -4
- package/build/Camera.d.ts.map +1 -1
- package/build/Camera.js +7 -7
- package/build/Camera.js.map +1 -1
- package/build/next/Camera.types.d.ts +42 -34
- package/build/next/Camera.types.d.ts.map +1 -1
- package/build/next/Camera.types.js +0 -12
- package/build/next/Camera.types.js.map +1 -1
- package/build/next/{Camera.d.ts → CameraView.d.ts} +8 -52
- package/build/next/CameraView.d.ts.map +1 -0
- package/build/next/{Camera.js → CameraView.js} +23 -92
- package/build/next/CameraView.js.map +1 -0
- package/build/next/index.d.ts +50 -2
- package/build/next/index.d.ts.map +1 -1
- package/build/next/index.js +71 -2
- package/build/next/index.js.map +1 -1
- package/build/next/utils/props.js +2 -2
- package/build/next/utils/props.js.map +1 -1
- package/ios/CameraRecordingOptions.swift +0 -1
- package/ios/CameraView.swift +8 -12
- package/ios/CameraViewModule.swift +4 -6
- package/ios/CameraViewNextModule.swift +73 -20
- package/ios/Next/BarcodeScanner.swift +61 -17
- package/ios/Next/CameraRecordingOptionsNext.swift +1 -0
- package/ios/Next/CameraViewNext.swift +48 -31
- package/package.json +2 -2
- package/src/Camera.tsx +7 -7
- package/src/next/Camera.types.ts +41 -33
- package/src/next/{Camera.tsx → CameraView.tsx} +27 -118
- package/src/next/index.ts +79 -5
- package/src/next/utils/props.ts +2 -2
- package/build/next/Camera.d.ts.map +0 -1
- package/build/next/Camera.js.map +0 -1
- package/ios/Next/Scanner+Delegates.swift +0 -52
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,16 @@
|
|
|
10
10
|
|
|
11
11
|
### 💡 Others
|
|
12
12
|
|
|
13
|
+
## 14.0.0 — 2023-12-12
|
|
14
|
+
|
|
15
|
+
### 🎉 New features
|
|
16
|
+
|
|
17
|
+
- Methods `stopRecording`, `pausePreview` and `resumePreview` have been updated to return promises. ([#25737](https://github.com/expo/expo/pull/25737) by [@lukmccall](https://github.com/lukmccall))
|
|
18
|
+
|
|
19
|
+
### 💡 Others
|
|
20
|
+
|
|
21
|
+
- [iOS] Replace legacy `FileSystem` interfaces usage with core `FileSystemUtilities`. ([#25495](https://github.com/expo/expo/pull/25495) by [@alanhughes](https://github.com/alanjhughes))
|
|
22
|
+
|
|
13
23
|
## 13.9.0 — 2023-11-14
|
|
14
24
|
|
|
15
25
|
### 🛠 Breaking changes
|
package/android/build.gradle
CHANGED
|
@@ -3,7 +3,7 @@ apply plugin: 'kotlin-android'
|
|
|
3
3
|
apply plugin: 'maven-publish'
|
|
4
4
|
|
|
5
5
|
group = 'host.exp.exponent'
|
|
6
|
-
version = '
|
|
6
|
+
version = '14.0.0'
|
|
7
7
|
|
|
8
8
|
def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
|
|
9
9
|
if (expoModulesCorePlugin.exists()) {
|
|
@@ -94,7 +94,7 @@ android {
|
|
|
94
94
|
namespace "expo.modules.camera"
|
|
95
95
|
defaultConfig {
|
|
96
96
|
versionCode 32
|
|
97
|
-
versionName "
|
|
97
|
+
versionName "14.0.0"
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
100
|
|
|
@@ -111,7 +111,7 @@ dependencies {
|
|
|
111
111
|
implementation project(':expo-modules-core')
|
|
112
112
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${getKotlinVersion()}"
|
|
113
113
|
}
|
|
114
|
-
def camerax_version = "1.
|
|
114
|
+
def camerax_version = "1.4.0-alpha02"
|
|
115
115
|
|
|
116
116
|
api "androidx.exifinterface:exifinterface:1.3.6"
|
|
117
117
|
api 'com.google.android:cameraview:1.0.0'
|
|
@@ -63,7 +63,7 @@ class ExpoCameraView(
|
|
|
63
63
|
|
|
64
64
|
private val onCameraReady by EventDispatcher<Unit>()
|
|
65
65
|
private val onMountError by EventDispatcher<CameraMountErrorEvent>()
|
|
66
|
-
private val onBarCodeScanned by EventDispatcher<
|
|
66
|
+
private val onBarCodeScanned by EventDispatcher<BarcodeScannedEvent>(
|
|
67
67
|
/**
|
|
68
68
|
* We want every distinct barcode to be reported to the JS listener.
|
|
69
69
|
* If we return some static value as a coalescing key there may be two barcode events
|
|
@@ -273,7 +273,7 @@ class ExpoCameraView(
|
|
|
273
273
|
transformBarCodeScannerResultToViewCoordinates(barCode)
|
|
274
274
|
val (cornerPoints, boundingBox) = getCornerPointsAndBoundingBox(barCode.cornerPoints, barCode.boundingBox)
|
|
275
275
|
onBarCodeScanned(
|
|
276
|
-
|
|
276
|
+
BarcodeScannedEvent(
|
|
277
277
|
target = id,
|
|
278
278
|
data = barCode.value,
|
|
279
279
|
type = barCode.type,
|
|
@@ -2,10 +2,11 @@ package expo.modules.camera.next
|
|
|
2
2
|
|
|
3
3
|
import android.Manifest
|
|
4
4
|
import android.util.Log
|
|
5
|
-
import expo.modules.camera.next.records.
|
|
5
|
+
import expo.modules.camera.next.records.BarcodeSettings
|
|
6
6
|
import expo.modules.camera.next.records.CameraMode
|
|
7
7
|
import expo.modules.camera.next.records.CameraType
|
|
8
8
|
import expo.modules.camera.next.records.FlashMode
|
|
9
|
+
import expo.modules.camera.next.records.VideoQuality
|
|
9
10
|
import expo.modules.camera.next.tasks.ResolveTakenPicture
|
|
10
11
|
import expo.modules.core.errors.ModuleDestroyedException
|
|
11
12
|
import expo.modules.core.utilities.EmulatorUtilities
|
|
@@ -24,7 +25,7 @@ import java.io.File
|
|
|
24
25
|
val cameraEvents = arrayOf(
|
|
25
26
|
"onCameraReady",
|
|
26
27
|
"onMountError",
|
|
27
|
-
"
|
|
28
|
+
"onBarcodeScanned",
|
|
28
29
|
"onFacesDetected",
|
|
29
30
|
"onFaceDetectionError",
|
|
30
31
|
"onPictureSaved"
|
|
@@ -104,15 +105,23 @@ class CameraViewNextModule : Module() {
|
|
|
104
105
|
view.mute = muted ?: false
|
|
105
106
|
}
|
|
106
107
|
|
|
107
|
-
Prop("
|
|
108
|
+
Prop("videoQuality") { view, quality: VideoQuality? ->
|
|
109
|
+
if (quality != null) {
|
|
110
|
+
view.videoQuality = quality
|
|
111
|
+
} else {
|
|
112
|
+
view.videoQuality = VideoQuality.VIDEO1080P
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
Prop("barcodeScannerSettings") { view, settings: BarcodeSettings? ->
|
|
108
117
|
if (settings == null) {
|
|
109
118
|
return@Prop
|
|
110
119
|
}
|
|
111
120
|
view.setBarCodeScannerSettings(settings)
|
|
112
121
|
}
|
|
113
122
|
|
|
114
|
-
Prop("
|
|
115
|
-
view.
|
|
123
|
+
Prop("barcodeScannerEnabled") { view, barCodeScannerEnabled: Boolean? ->
|
|
124
|
+
view.setShouldScanBarcodes(barCodeScannerEnabled ?: false)
|
|
116
125
|
}
|
|
117
126
|
|
|
118
127
|
AsyncFunction("takePicture") { view: ExpoCameraView, options: PictureOptions, promise: Promise ->
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
package expo.modules.camera.next
|
|
2
2
|
|
|
3
|
+
import android.Manifest
|
|
3
4
|
import android.annotation.SuppressLint
|
|
4
5
|
import android.content.Context
|
|
5
|
-
import android.
|
|
6
|
+
import android.content.pm.PackageManager
|
|
6
7
|
import android.graphics.SurfaceTexture
|
|
7
8
|
import android.hardware.camera2.CameraCharacteristics
|
|
8
|
-
import android.hardware.camera2.CameraMetadata
|
|
9
9
|
import android.os.Bundle
|
|
10
10
|
import android.util.Log
|
|
11
11
|
import android.view.View
|
|
@@ -14,36 +14,35 @@ import androidx.appcompat.app.AppCompatActivity
|
|
|
14
14
|
import androidx.camera.camera2.interop.Camera2CameraInfo
|
|
15
15
|
import androidx.camera.core.Camera
|
|
16
16
|
import androidx.camera.core.CameraInfo
|
|
17
|
+
import androidx.camera.core.CameraSelector
|
|
17
18
|
import androidx.camera.core.CameraState
|
|
18
19
|
import androidx.camera.core.ImageAnalysis
|
|
19
20
|
import androidx.camera.core.ImageCapture
|
|
20
21
|
import androidx.camera.core.ImageCaptureException
|
|
21
22
|
import androidx.camera.core.ImageProxy
|
|
22
|
-
import androidx.camera.core.MirrorMode
|
|
23
23
|
import androidx.camera.core.Preview
|
|
24
24
|
import androidx.camera.core.UseCaseGroup
|
|
25
|
-
import androidx.camera.core.resolutionselector.AspectRatioStrategy
|
|
26
|
-
import androidx.camera.core.resolutionselector.ResolutionSelector
|
|
27
25
|
import androidx.camera.lifecycle.ProcessCameraProvider
|
|
28
26
|
import androidx.camera.video.FileOutputOptions
|
|
29
|
-
import androidx.camera.video.Quality
|
|
30
27
|
import androidx.camera.video.QualitySelector
|
|
31
28
|
import androidx.camera.video.Recorder
|
|
32
29
|
import androidx.camera.video.Recording
|
|
33
30
|
import androidx.camera.video.VideoCapture
|
|
34
31
|
import androidx.camera.video.VideoRecordEvent
|
|
35
32
|
import androidx.camera.view.PreviewView
|
|
33
|
+
import androidx.core.app.ActivityCompat
|
|
36
34
|
import androidx.core.content.ContextCompat
|
|
37
|
-
import expo.modules.camera.
|
|
35
|
+
import expo.modules.camera.BarcodeScannedEvent
|
|
38
36
|
import expo.modules.camera.CameraMountErrorEvent
|
|
39
37
|
import expo.modules.camera.PictureSavedEvent
|
|
40
38
|
import expo.modules.camera.next.analyzers.BarcodeAnalyzer
|
|
41
39
|
import expo.modules.camera.next.analyzers.toByteArray
|
|
42
|
-
import expo.modules.camera.next.records.
|
|
40
|
+
import expo.modules.camera.next.records.BarcodeSettings
|
|
43
41
|
import expo.modules.camera.next.records.BarcodeType
|
|
44
42
|
import expo.modules.camera.next.records.CameraMode
|
|
45
43
|
import expo.modules.camera.next.records.CameraType
|
|
46
44
|
import expo.modules.camera.next.records.FlashMode
|
|
45
|
+
import expo.modules.camera.next.records.VideoQuality
|
|
47
46
|
import expo.modules.camera.next.tasks.ResolveTakenPicture
|
|
48
47
|
import expo.modules.camera.next.utils.FileSystemUtils
|
|
49
48
|
import expo.modules.camera.utils.mapX
|
|
@@ -78,6 +77,7 @@ class ExpoCameraView(
|
|
|
78
77
|
var camera: Camera? = null
|
|
79
78
|
var activeRecording: Recording? = null
|
|
80
79
|
|
|
80
|
+
private val providerFuture = ProcessCameraProvider.getInstance(context)
|
|
81
81
|
private var imageCaptureUseCase: ImageCapture? = null
|
|
82
82
|
private var imageAnalysisUseCase: ImageAnalysis? = null
|
|
83
83
|
private var recorder: Recorder? = null
|
|
@@ -98,11 +98,17 @@ class ExpoCameraView(
|
|
|
98
98
|
createCamera()
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
+
var videoQuality: VideoQuality = VideoQuality.VIDEO1080P
|
|
102
|
+
set(value) {
|
|
103
|
+
field = value
|
|
104
|
+
createCamera()
|
|
105
|
+
}
|
|
106
|
+
|
|
101
107
|
var mute: Boolean = false
|
|
102
108
|
|
|
103
109
|
private val onCameraReady by EventDispatcher<Unit>()
|
|
104
110
|
private val onMountError by EventDispatcher<CameraMountErrorEvent>()
|
|
105
|
-
private val
|
|
111
|
+
private val onBarcodeScanned by EventDispatcher<BarcodeScannedEvent>(
|
|
106
112
|
/**
|
|
107
113
|
* We want every distinct barcode to be reported to the JS listener.
|
|
108
114
|
* If we return some static value as a coalescing key there may be two barcode events
|
|
@@ -121,46 +127,22 @@ class ExpoCameraView(
|
|
|
121
127
|
)
|
|
122
128
|
|
|
123
129
|
// Scanning-related properties
|
|
124
|
-
private var
|
|
130
|
+
private var shouldScanBarcodes = false
|
|
125
131
|
|
|
126
132
|
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
|
|
127
133
|
val width = right - left
|
|
128
134
|
val height = bottom - top
|
|
129
135
|
|
|
130
136
|
previewView.layout(0, 0, width, height)
|
|
131
|
-
|
|
132
|
-
if (changed) {
|
|
133
|
-
createCamera()
|
|
134
|
-
}
|
|
137
|
+
postInvalidate(left, top, right, bottom)
|
|
135
138
|
}
|
|
136
139
|
|
|
137
140
|
override fun onViewAdded(child: View) {
|
|
138
|
-
// react adds children to containers at the beginning of children list and that moves pre-react added preview to the end of that list
|
|
139
|
-
// above would cause preview (TextureView that covers all available space) to be rendered at the top of children stack
|
|
140
|
-
// while we need this preview to be rendered last beneath all other children
|
|
141
|
-
|
|
142
|
-
// child is not preview
|
|
143
141
|
if (previewView === child) {
|
|
144
142
|
return
|
|
145
143
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
val childrenToBeReordered = mutableListOf<View>()
|
|
149
|
-
for (i in 0 until this.childCount) {
|
|
150
|
-
val childView = getChildAt(i)
|
|
151
|
-
if (i == 0 && childView === previewView) {
|
|
152
|
-
// preview is already first in children list - do not reorder anything
|
|
153
|
-
return
|
|
154
|
-
}
|
|
155
|
-
if (childView !== previewView) {
|
|
156
|
-
childrenToBeReordered.add(childView)
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
for (childView in childrenToBeReordered) {
|
|
160
|
-
bringChildToFront(childView)
|
|
161
|
-
}
|
|
162
|
-
previewView.requestLayout()
|
|
163
|
-
previewView.invalidate()
|
|
144
|
+
removeView(previewView)
|
|
145
|
+
addView(previewView, 0)
|
|
164
146
|
}
|
|
165
147
|
|
|
166
148
|
fun takePicture(options: PictureOptions, promise: Promise, cacheDirectory: File) {
|
|
@@ -195,7 +177,9 @@ class ExpoCameraView(
|
|
|
195
177
|
}
|
|
196
178
|
|
|
197
179
|
fun setTorchEnabled(enabled: Boolean) {
|
|
198
|
-
camera?.
|
|
180
|
+
if (camera?.cameraInfo?.hasFlashUnit() == true) {
|
|
181
|
+
camera?.cameraControl?.enableTorch(enabled)
|
|
182
|
+
}
|
|
199
183
|
}
|
|
200
184
|
|
|
201
185
|
fun record(options: RecordingOptions, promise: Promise, cacheDirectory: File) {
|
|
@@ -204,9 +188,12 @@ class ExpoCameraView(
|
|
|
204
188
|
.setFileSizeLimit(options.maxFileSize.toLong())
|
|
205
189
|
.setDurationLimitMillis(options.maxDuration.toLong())
|
|
206
190
|
.build()
|
|
207
|
-
|
|
208
191
|
recorder?.let {
|
|
192
|
+
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
|
|
193
|
+
return
|
|
194
|
+
}
|
|
209
195
|
activeRecording = it.prepareRecording(context, fileOutputOptions)
|
|
196
|
+
.withAudioEnabled()
|
|
210
197
|
.start(ContextCompat.getMainExecutor(context)) { event ->
|
|
211
198
|
when (event) {
|
|
212
199
|
is VideoRecordEvent.Finalize -> {
|
|
@@ -235,8 +222,6 @@ class ExpoCameraView(
|
|
|
235
222
|
|
|
236
223
|
@SuppressLint("UnsafeOptInUsageError")
|
|
237
224
|
private fun createCamera() {
|
|
238
|
-
val providerFuture = ProcessCameraProvider.getInstance(context)
|
|
239
|
-
|
|
240
225
|
providerFuture.addListener(
|
|
241
226
|
{
|
|
242
227
|
val cameraProvider: ProcessCameraProvider = providerFuture.get()
|
|
@@ -247,7 +232,9 @@ class ExpoCameraView(
|
|
|
247
232
|
it.setSurfaceProvider(previewView.surfaceProvider)
|
|
248
233
|
}
|
|
249
234
|
|
|
250
|
-
val cameraSelector =
|
|
235
|
+
val cameraSelector = CameraSelector.Builder()
|
|
236
|
+
.requireLensFacing(lenFacing.mapToCharacteristic())
|
|
237
|
+
.build()
|
|
251
238
|
|
|
252
239
|
imageCaptureUseCase = ImageCapture.Builder()
|
|
253
240
|
.build()
|
|
@@ -255,7 +242,7 @@ class ExpoCameraView(
|
|
|
255
242
|
val cameraInfo = cameraProvider.availableCameraInfos.filter {
|
|
256
243
|
Camera2CameraInfo
|
|
257
244
|
.from(it)
|
|
258
|
-
.getCameraCharacteristic(CameraCharacteristics.LENS_FACING) ==
|
|
245
|
+
.getCameraCharacteristic(CameraCharacteristics.LENS_FACING) == lenFacing.mapToCharacteristic()
|
|
259
246
|
}
|
|
260
247
|
|
|
261
248
|
val videoCapture = createVideoCapture(cameraInfo)
|
|
@@ -294,18 +281,13 @@ class ExpoCameraView(
|
|
|
294
281
|
private fun createImageAnalyzer(): ImageAnalysis =
|
|
295
282
|
ImageAnalysis.Builder()
|
|
296
283
|
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
|
|
297
|
-
.setResolutionSelector(
|
|
298
|
-
ResolutionSelector.Builder()
|
|
299
|
-
.setAspectRatioStrategy(AspectRatioStrategy.RATIO_16_9_FALLBACK_AUTO_STRATEGY)
|
|
300
|
-
.build()
|
|
301
|
-
)
|
|
302
284
|
.build()
|
|
303
285
|
.also { analyzer ->
|
|
304
|
-
if (
|
|
286
|
+
if (shouldScanBarcodes) {
|
|
305
287
|
analyzer.setAnalyzer(
|
|
306
288
|
ContextCompat.getMainExecutor(context),
|
|
307
289
|
BarcodeAnalyzer(lenFacing, barcodeFormats) {
|
|
308
|
-
|
|
290
|
+
onBarcodeScanned(it)
|
|
309
291
|
}
|
|
310
292
|
)
|
|
311
293
|
}
|
|
@@ -313,9 +295,9 @@ class ExpoCameraView(
|
|
|
313
295
|
|
|
314
296
|
private fun createVideoCapture(info: List<CameraInfo>): VideoCapture<Recorder> {
|
|
315
297
|
val supportedQualities = QualitySelector.getSupportedQualities(info[0])
|
|
316
|
-
|
|
317
|
-
val filteredQualities = arrayListOf(Quality.UHD, Quality.FHD, Quality.HD, Quality.SD)
|
|
298
|
+
val filteredQualities = arrayListOf(videoQuality.mapToQuality())
|
|
318
299
|
.filter { supportedQualities.contains(it) }
|
|
300
|
+
|
|
319
301
|
val qualitySelector = QualitySelector.fromOrderedList(filteredQualities)
|
|
320
302
|
|
|
321
303
|
val recorder = Recorder.Builder()
|
|
@@ -327,7 +309,7 @@ class ExpoCameraView(
|
|
|
327
309
|
}
|
|
328
310
|
|
|
329
311
|
return VideoCapture.Builder(recorder)
|
|
330
|
-
.
|
|
312
|
+
.setVideoStabilizationEnabled(true)
|
|
331
313
|
.build()
|
|
332
314
|
}
|
|
333
315
|
|
|
@@ -337,29 +319,26 @@ class ExpoCameraView(
|
|
|
337
319
|
CameraState.Type.OPEN -> {
|
|
338
320
|
onCameraReady(Unit)
|
|
339
321
|
}
|
|
322
|
+
|
|
340
323
|
else -> {}
|
|
341
324
|
}
|
|
342
325
|
}
|
|
343
326
|
}
|
|
344
327
|
|
|
345
|
-
fun
|
|
346
|
-
this.
|
|
328
|
+
fun setShouldScanBarcodes(shouldScanBarCodes: Boolean) {
|
|
329
|
+
this.shouldScanBarcodes = shouldScanBarCodes
|
|
347
330
|
createCamera()
|
|
348
331
|
}
|
|
349
332
|
|
|
350
|
-
fun setBarCodeScannerSettings(settings:
|
|
333
|
+
fun setBarCodeScannerSettings(settings: BarcodeSettings?) {
|
|
351
334
|
barcodeFormats = settings?.barcodeTypes ?: emptyList()
|
|
352
|
-
createCamera()
|
|
353
335
|
}
|
|
354
336
|
|
|
355
337
|
private fun getDeviceOrientation() =
|
|
356
338
|
(context.getSystemService(Context.WINDOW_SERVICE) as WindowManager).defaultDisplay.rotation
|
|
357
339
|
|
|
358
|
-
private fun
|
|
359
|
-
val cornerPoints =
|
|
360
|
-
|
|
361
|
-
val cameraWidth = barCode.referenceImageHeight
|
|
362
|
-
val cameraHeight = barCode.referenceImageWidth
|
|
340
|
+
private fun transformBarcodeScannerResultToViewCoordinates(barcode: BarCodeScannerResult) {
|
|
341
|
+
val cornerPoints = barcode.cornerPoints
|
|
363
342
|
val previewWidth = previewView.width
|
|
364
343
|
val previewHeight = previewView.height
|
|
365
344
|
|
|
@@ -368,33 +347,24 @@ class ExpoCameraView(
|
|
|
368
347
|
val landscape = getDeviceOrientation() % 2 != 0
|
|
369
348
|
|
|
370
349
|
if (facingFront && portrait) {
|
|
371
|
-
cornerPoints.mapY {
|
|
350
|
+
cornerPoints.mapY { barcode.referenceImageHeight - cornerPoints[it] }
|
|
372
351
|
}
|
|
373
352
|
if (facingFront && landscape) {
|
|
374
|
-
cornerPoints.mapX {
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
val scaleX = if (portrait) {
|
|
378
|
-
previewWidth / cameraHeight.toFloat()
|
|
379
|
-
} else {
|
|
380
|
-
previewWidth / cameraWidth.toFloat()
|
|
381
|
-
}
|
|
382
|
-
val scaleY = if (portrait) {
|
|
383
|
-
previewHeight / cameraWidth.toFloat()
|
|
384
|
-
} else {
|
|
385
|
-
previewHeight / cameraHeight.toFloat()
|
|
353
|
+
cornerPoints.mapX { barcode.referenceImageWidth - cornerPoints[it] }
|
|
386
354
|
}
|
|
387
355
|
|
|
388
356
|
cornerPoints.mapX {
|
|
389
|
-
(cornerPoints[it] *
|
|
357
|
+
(cornerPoints[it] * previewWidth / barcode.referenceImageWidth.toFloat())
|
|
390
358
|
.roundToInt()
|
|
391
359
|
}
|
|
392
360
|
cornerPoints.mapY {
|
|
393
|
-
(cornerPoints[it] *
|
|
361
|
+
(cornerPoints[it] * previewHeight / barcode.referenceImageHeight.toFloat())
|
|
394
362
|
.roundToInt()
|
|
395
363
|
}
|
|
396
364
|
|
|
397
|
-
|
|
365
|
+
barcode.cornerPoints = cornerPoints
|
|
366
|
+
barcode.referenceImageHeight = height
|
|
367
|
+
barcode.referenceImageWidth = width
|
|
398
368
|
}
|
|
399
369
|
|
|
400
370
|
private fun getCornerPointsAndBoundingBox(cornerPoints: List<Int>, boundingBox: BoundingBox): Pair<ArrayList<Bundle>, Bundle> {
|
|
@@ -429,15 +399,15 @@ class ExpoCameraView(
|
|
|
429
399
|
return convertedCornerPoints to boundingBoxBundle
|
|
430
400
|
}
|
|
431
401
|
|
|
432
|
-
private fun
|
|
433
|
-
if (
|
|
434
|
-
|
|
435
|
-
val (cornerPoints, boundingBox) = getCornerPointsAndBoundingBox(
|
|
436
|
-
|
|
437
|
-
|
|
402
|
+
private fun onBarcodeScanned(barcode: BarCodeScannerResult) {
|
|
403
|
+
if (shouldScanBarcodes) {
|
|
404
|
+
transformBarcodeScannerResultToViewCoordinates(barcode)
|
|
405
|
+
val (cornerPoints, boundingBox) = getCornerPointsAndBoundingBox(barcode.cornerPoints, barcode.boundingBox)
|
|
406
|
+
onBarcodeScanned(
|
|
407
|
+
BarcodeScannedEvent(
|
|
438
408
|
target = id,
|
|
439
|
-
data =
|
|
440
|
-
type =
|
|
409
|
+
data = barcode.value,
|
|
410
|
+
type = barcode.type,
|
|
441
411
|
cornerPoints = cornerPoints,
|
|
442
412
|
boundingBox = boundingBox
|
|
443
413
|
)
|
|
@@ -450,7 +420,6 @@ class ExpoCameraView(
|
|
|
450
420
|
override fun getPreviewSizeAsArray() = intArrayOf(previewView.width, previewView.height)
|
|
451
421
|
|
|
452
422
|
init {
|
|
453
|
-
isChildrenDrawingOrderEnabled = true
|
|
454
423
|
previewView.setOnHierarchyChangeListener(object : OnHierarchyChangeListener {
|
|
455
424
|
override fun onChildViewRemoved(parent: View?, child: View?) = Unit
|
|
456
425
|
override fun onChildViewAdded(parent: View?, child: View?) {
|
|
@@ -462,7 +431,6 @@ class ExpoCameraView(
|
|
|
462
431
|
}
|
|
463
432
|
})
|
|
464
433
|
addView(previewView)
|
|
465
|
-
createCamera()
|
|
466
434
|
}
|
|
467
435
|
|
|
468
436
|
fun onPictureSaved(response: Bundle) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
package expo.modules.camera.next
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import expo.modules.camera.next.records.VideoQuality
|
|
4
4
|
import expo.modules.kotlin.records.Field
|
|
5
5
|
import expo.modules.kotlin.records.Record
|
|
6
6
|
|
|
@@ -18,5 +18,5 @@ data class PictureOptions(
|
|
|
18
18
|
data class RecordingOptions(
|
|
19
19
|
@Field val maxDuration: Int = 0,
|
|
20
20
|
@Field val maxFileSize: Int = 0,
|
|
21
|
-
@Field val quality:
|
|
21
|
+
@Field val quality: VideoQuality?
|
|
22
22
|
) : Record
|
|
@@ -16,7 +16,7 @@ import expo.modules.interfaces.barcodescanner.BarCodeScannerResult
|
|
|
16
16
|
import java.nio.ByteBuffer
|
|
17
17
|
|
|
18
18
|
@OptIn(ExperimentalGetImage::class)
|
|
19
|
-
class BarcodeAnalyzer(private val lensFacing: CameraType,
|
|
19
|
+
class BarcodeAnalyzer(private val lensFacing: CameraType, formats: List<BarcodeType>, val onComplete: (BarCodeScannerResult) -> Unit) : ImageAnalysis.Analyzer {
|
|
20
20
|
private val barcodeFormats = if (formats.isEmpty()) 0 else formats.map { it.mapToBarcode() }.reduce { acc, it ->
|
|
21
21
|
acc or it
|
|
22
22
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
package expo.modules.camera.next.records
|
|
2
2
|
|
|
3
|
+
import android.hardware.camera2.CameraMetadata
|
|
3
4
|
import androidx.camera.core.CameraSelector
|
|
4
5
|
import androidx.camera.core.ImageCapture
|
|
6
|
+
import androidx.camera.video.Quality
|
|
5
7
|
import com.google.mlkit.vision.barcode.common.Barcode
|
|
6
8
|
import expo.modules.kotlin.records.Record
|
|
7
9
|
import expo.modules.kotlin.types.Enumerable
|
|
@@ -14,6 +16,27 @@ enum class CameraType(val value: String) : Enumerable {
|
|
|
14
16
|
FRONT -> CameraSelector.DEFAULT_FRONT_CAMERA
|
|
15
17
|
BACK -> CameraSelector.DEFAULT_BACK_CAMERA
|
|
16
18
|
}
|
|
19
|
+
|
|
20
|
+
fun mapToCharacteristic() = when (this) {
|
|
21
|
+
FRONT -> CameraMetadata.LENS_FACING_FRONT
|
|
22
|
+
BACK -> CameraMetadata.LENS_FACING_BACK
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
enum class VideoQuality(val value: String) : Enumerable {
|
|
27
|
+
VIDEO2160P("2160p"),
|
|
28
|
+
VIDEO1080P("1080p"),
|
|
29
|
+
VIDEO720P("720p"),
|
|
30
|
+
VIDEO480P("480p"),
|
|
31
|
+
VIDEO4X3("4:3");
|
|
32
|
+
|
|
33
|
+
fun mapToQuality(): Quality = when (this) {
|
|
34
|
+
VIDEO2160P -> Quality.UHD
|
|
35
|
+
VIDEO1080P -> Quality.FHD
|
|
36
|
+
VIDEO720P -> Quality.HD
|
|
37
|
+
VIDEO480P -> Quality.SD
|
|
38
|
+
VIDEO4X3 -> Quality.LOWEST
|
|
39
|
+
}
|
|
17
40
|
}
|
|
18
41
|
|
|
19
42
|
enum class FlashMode(val value: String) : Enumerable {
|
|
@@ -33,7 +56,7 @@ enum class CameraMode(val value: String) : Enumerable {
|
|
|
33
56
|
VIDEO("video")
|
|
34
57
|
}
|
|
35
58
|
|
|
36
|
-
data class
|
|
59
|
+
data class BarcodeSettings(
|
|
37
60
|
val barcodeTypes: List<BarcodeType>,
|
|
38
61
|
val interval: Double?
|
|
39
62
|
) : Record
|
package/build/Camera.d.ts
CHANGED
|
@@ -102,7 +102,7 @@ export default class Camera extends React.Component<CameraProps> {
|
|
|
102
102
|
* for an `Image` element for example. `exif` is included if the `exif` option was truthy, and is an object containing EXIF
|
|
103
103
|
* data for the image--the names of its properties are EXIF tags and their values are the values for those tags.
|
|
104
104
|
*
|
|
105
|
-
* > On native platforms, the local image URI is temporary. Use [`FileSystem.copyAsync`](filesystem
|
|
105
|
+
* > On native platforms, the local image URI is temporary. Use [`FileSystem.copyAsync`](filesystem/#filesystemcachedirectory)
|
|
106
106
|
* > to make a permanent copy of the image.
|
|
107
107
|
*/
|
|
108
108
|
takePictureAsync(options?: CameraPictureOptions): Promise<CameraCapturedPicture>;
|
|
@@ -134,15 +134,15 @@ export default class Camera extends React.Component<CameraProps> {
|
|
|
134
134
|
/**
|
|
135
135
|
* Stops recording if any is in progress.
|
|
136
136
|
*/
|
|
137
|
-
stopRecording(): void
|
|
137
|
+
stopRecording(): Promise<void>;
|
|
138
138
|
/**
|
|
139
139
|
* Pauses the camera preview. It is not recommended to use `takePictureAsync` when preview is paused.
|
|
140
140
|
*/
|
|
141
|
-
pausePreview(): void
|
|
141
|
+
pausePreview(): Promise<void>;
|
|
142
142
|
/**
|
|
143
143
|
* Resumes the camera preview.
|
|
144
144
|
*/
|
|
145
|
-
resumePreview(): void
|
|
145
|
+
resumePreview(): Promise<void>;
|
|
146
146
|
_onCameraReady: () => void;
|
|
147
147
|
_onMountError: ({ nativeEvent }: {
|
|
148
148
|
nativeEvent: {
|
package/build/Camera.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Camera.d.ts","sourceRoot":"","sources":["../src/Camera.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,oBAAoB,EACpB,WAAW,EACX,sBAAsB,EACtB,UAAU,EACV,aAAa,EACb,kBAAkB,EAClB,UAAU,EACX,MAAM,gBAAgB,CAAC;AAoDxB,MAAM,CAAC,OAAO,OAAO,MAAO,SAAQ,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC;IAC9D;;;;;OAKG;WACU,gBAAgB,IAAI,OAAO,CAAC,OAAO,CAAC;IAQjD;;;OAGG;WACU,4BAA4B,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;IASlE;;;;OAIG;WACU,4BAA4B,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;IAQlE,MAAM,CAAC,SAAS,EAAE,aAAa,CAQ7B;IAGF,MAAM,CAAC,gBAAgB;;;;;MAAoB;IAE3C,MAAM,CAAC,YAAY,EAAE,WAAW,CAS9B;IAGF;;;OAGG;WACU,mBAAmB,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAQ/D;;;;;OAKG;WACU,uBAAuB,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAQnE;;;OAGG;WACU,yBAAyB,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAKrE;;;;OAIG;WACU,6BAA6B,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAKzE;;;;;;;;OAQG;IACH,MAAM,CAAC,oBAAoB,yLAGxB;IAGH;;;OAGG;WACU,6BAA6B,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAKzE;;;;OAIG;WACU,iCAAiC,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAK7E;;;;;;;;OAQG;IACH,MAAM,CAAC,wBAAwB,yLAG5B;IAEH,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC;IACpC,WAAW,EAAE;QAAE,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAM;IAClD,gBAAgB,EAAE;QAAE,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAM;IAGrD;;;;;;;;;;;;;;;OAeG;IACG,gBAAgB,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAMtF;;;;OAIG;IACG,uBAAuB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAQlD;;;;;OAKG;IACG,6BAA6B,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAOrE;;;;;;;;OAQG;IACG,WAAW,CAAC,OAAO,CAAC,EAAE,sBAAsB,GAAG,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IAS7E;;OAEG;
|
|
1
|
+
{"version":3,"file":"Camera.d.ts","sourceRoot":"","sources":["../src/Camera.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,oBAAoB,EACpB,WAAW,EACX,sBAAsB,EACtB,UAAU,EACV,aAAa,EACb,kBAAkB,EAClB,UAAU,EACX,MAAM,gBAAgB,CAAC;AAoDxB,MAAM,CAAC,OAAO,OAAO,MAAO,SAAQ,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC;IAC9D;;;;;OAKG;WACU,gBAAgB,IAAI,OAAO,CAAC,OAAO,CAAC;IAQjD;;;OAGG;WACU,4BAA4B,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;IASlE;;;;OAIG;WACU,4BAA4B,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;IAQlE,MAAM,CAAC,SAAS,EAAE,aAAa,CAQ7B;IAGF,MAAM,CAAC,gBAAgB;;;;;MAAoB;IAE3C,MAAM,CAAC,YAAY,EAAE,WAAW,CAS9B;IAGF;;;OAGG;WACU,mBAAmB,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAQ/D;;;;;OAKG;WACU,uBAAuB,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAQnE;;;OAGG;WACU,yBAAyB,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAKrE;;;;OAIG;WACU,6BAA6B,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAKzE;;;;;;;;OAQG;IACH,MAAM,CAAC,oBAAoB,yLAGxB;IAGH;;;OAGG;WACU,6BAA6B,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAKzE;;;;OAIG;WACU,iCAAiC,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAK7E;;;;;;;;OAQG;IACH,MAAM,CAAC,wBAAwB,yLAG5B;IAEH,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC;IACpC,WAAW,EAAE;QAAE,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAM;IAClD,gBAAgB,EAAE;QAAE,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAM;IAGrD;;;;;;;;;;;;;;;OAeG;IACG,gBAAgB,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAMtF;;;;OAIG;IACG,uBAAuB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAQlD;;;;;OAKG;IACG,6BAA6B,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAOrE;;;;;;;;OAQG;IACG,WAAW,CAAC,OAAO,CAAC,EAAE,sBAAsB,GAAG,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IAS7E;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAQpC;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAQnC;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAQpC,cAAc,aAIZ;IAEF,aAAa;qBAAoC;YAAE,OAAO,EAAE,MAAM,CAAA;SAAE;eAIlE;IAEF,+BAA+B;qBAGhB;YAAE,aAAa,iBAAiB,CAAA;SAAE;eAK/C;IAEF,iBAAiB,cACH,QAAQ;qBACa,GAAG;eAgBlC;IAEJ,aAAa,SAAU,MAAM,SAAS,UAapC;IAEF,MAAM;CAsBP;AAED,eAAO,MACL,SAAS,iBACT,mBAAmB,qCACnB,uBAAuB,yCACvB,yBAAyB,2CACzB,6BAA6B,+CAC7B,6BAA6B,+CAC7B,iCAAiC,iDACzB,CAAC"}
|
package/build/Camera.js
CHANGED
|
@@ -194,7 +194,7 @@ export default class Camera extends React.Component {
|
|
|
194
194
|
* for an `Image` element for example. `exif` is included if the `exif` option was truthy, and is an object containing EXIF
|
|
195
195
|
* data for the image--the names of its properties are EXIF tags and their values are the values for those tags.
|
|
196
196
|
*
|
|
197
|
-
* > On native platforms, the local image URI is temporary. Use [`FileSystem.copyAsync`](filesystem
|
|
197
|
+
* > On native platforms, the local image URI is temporary. Use [`FileSystem.copyAsync`](filesystem/#filesystemcachedirectory)
|
|
198
198
|
* > to make a permanent copy of the image.
|
|
199
199
|
*/
|
|
200
200
|
async takePictureAsync(options) {
|
|
@@ -243,29 +243,29 @@ export default class Camera extends React.Component {
|
|
|
243
243
|
/**
|
|
244
244
|
* Stops recording if any is in progress.
|
|
245
245
|
*/
|
|
246
|
-
stopRecording() {
|
|
246
|
+
async stopRecording() {
|
|
247
247
|
if (!CameraManager.stopRecording) {
|
|
248
248
|
throw new UnavailabilityError('Camera', 'stopRecording');
|
|
249
249
|
}
|
|
250
|
-
CameraManager.stopRecording(this._cameraHandle);
|
|
250
|
+
return await CameraManager.stopRecording(this._cameraHandle);
|
|
251
251
|
}
|
|
252
252
|
/**
|
|
253
253
|
* Pauses the camera preview. It is not recommended to use `takePictureAsync` when preview is paused.
|
|
254
254
|
*/
|
|
255
|
-
pausePreview() {
|
|
255
|
+
async pausePreview() {
|
|
256
256
|
if (!CameraManager.pausePreview) {
|
|
257
257
|
throw new UnavailabilityError('Camera', 'pausePreview');
|
|
258
258
|
}
|
|
259
|
-
CameraManager.pausePreview(this._cameraHandle);
|
|
259
|
+
return await CameraManager.pausePreview(this._cameraHandle);
|
|
260
260
|
}
|
|
261
261
|
/**
|
|
262
262
|
* Resumes the camera preview.
|
|
263
263
|
*/
|
|
264
|
-
resumePreview() {
|
|
264
|
+
async resumePreview() {
|
|
265
265
|
if (!CameraManager.resumePreview) {
|
|
266
266
|
throw new UnavailabilityError('Camera', 'resumePreview');
|
|
267
267
|
}
|
|
268
|
-
CameraManager.resumePreview(this._cameraHandle);
|
|
268
|
+
return await CameraManager.resumePreview(this._cameraHandle);
|
|
269
269
|
}
|
|
270
270
|
_onCameraReady = () => {
|
|
271
271
|
if (this.props.onCameraReady) {
|