expo-camera 12.0.0 → 12.1.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 +16 -0
- package/README.md +1 -1
- package/android/build.gradle +7 -2
- package/android/src/main/java/expo/modules/camera/CameraModule.kt +217 -0
- package/android/src/main/java/expo/modules/camera/CameraPackage.kt +10 -0
- package/android/src/main/java/expo/modules/camera/CameraViewHelper.kt +139 -0
- package/android/src/main/java/expo/modules/camera/CameraViewManager.kt +116 -0
- package/android/src/main/java/expo/modules/camera/Constants.kt +184 -0
- package/android/src/main/java/expo/modules/camera/ExpoCameraView.kt +329 -0
- package/android/src/main/java/expo/modules/camera/events/BarCodeScannedEvent.kt +50 -0
- package/android/src/main/java/expo/modules/camera/events/CameraMountErrorEvent.kt +33 -0
- package/android/src/main/java/expo/modules/camera/events/CameraReadyEvent.kt +23 -0
- package/android/src/main/java/expo/modules/camera/events/FaceDetectionErrorEvent.kt +39 -0
- package/android/src/main/java/expo/modules/camera/events/FacesDetectedEvent.kt +46 -0
- package/android/src/main/java/expo/modules/camera/events/PictureSavedEvent.kt +41 -0
- package/android/src/main/java/expo/modules/camera/tasks/BarCodeScannerAsyncTask.kt +26 -0
- package/android/src/main/java/expo/modules/camera/tasks/BarCodeScannerAsyncTaskDelegate.kt +8 -0
- package/android/src/main/java/expo/modules/camera/tasks/FaceDetectorAsyncTaskDelegate.kt +10 -0
- package/android/src/main/java/expo/modules/camera/tasks/FaceDetectorTask.kt +34 -0
- package/android/src/main/java/expo/modules/camera/tasks/PictureSavedDelegate.kt +7 -0
- package/android/src/main/java/expo/modules/camera/tasks/ResolveTakenPictureAsyncTask.kt +231 -0
- package/android/src/main/java/expo/modules/camera/utils/FileSystemUtils.kt +23 -0
- package/android/src/main/java/expo/modules/camera/utils/ImageDimensions.kt +14 -0
- package/build/ExponentCameraManager.web.js +3 -1
- package/build/ExponentCameraManager.web.js.map +1 -1
- package/ios/EXCamera.xcframework/Info.plist +5 -5
- package/ios/EXCamera.xcframework/ios-arm64/EXCamera.framework/EXCamera +0 -0
- package/ios/EXCamera.xcframework/ios-arm64/EXCamera.framework/Info.plist +0 -0
- package/ios/EXCamera.xcframework/ios-arm64_x86_64-simulator/EXCamera.framework/EXCamera +0 -0
- package/ios/EXCamera.xcframework/ios-arm64_x86_64-simulator/EXCamera.framework/Info.plist +0 -0
- package/package.json +7 -5
- package/plugin/build/withCamera.d.ts +2 -1
- package/plugin/build/withCamera.js +50 -30
- package/plugin/src/withCamera.ts +66 -27
- package/src/ExponentCameraManager.web.ts +3 -2
- package/src/{types → ts-declarations}/image-capture.d.ts +0 -0
- package/src/ts-declarations/lib.dom.d.ts +34 -0
- package/android/src/main/java/expo/modules/camera/CameraModule.java +0 -359
- package/android/src/main/java/expo/modules/camera/CameraPackage.java +0 -23
- package/android/src/main/java/expo/modules/camera/CameraViewHelper.java +0 -294
- package/android/src/main/java/expo/modules/camera/CameraViewManager.java +0 -142
- package/android/src/main/java/expo/modules/camera/ExpoCameraView.java +0 -376
- package/android/src/main/java/expo/modules/camera/events/BarCodeScannedEvent.java +0 -59
- package/android/src/main/java/expo/modules/camera/events/CameraMountErrorEvent.java +0 -38
- package/android/src/main/java/expo/modules/camera/events/CameraReadyEvent.java +0 -30
- package/android/src/main/java/expo/modules/camera/events/FaceDetectionErrorEvent.java +0 -50
- package/android/src/main/java/expo/modules/camera/events/FacesDetectedEvent.java +0 -63
- package/android/src/main/java/expo/modules/camera/events/PictureSavedEvent.java +0 -53
- package/android/src/main/java/expo/modules/camera/tasks/BarCodeScannerAsyncTask.java +0 -47
- package/android/src/main/java/expo/modules/camera/tasks/BarCodeScannerAsyncTaskDelegate.java +0 -8
- package/android/src/main/java/expo/modules/camera/tasks/FaceDetectorAsyncTaskDelegate.java +0 -13
- package/android/src/main/java/expo/modules/camera/tasks/FaceDetectorTask.java +0 -53
- package/android/src/main/java/expo/modules/camera/tasks/PictureSavedDelegate.java +0 -7
- package/android/src/main/java/expo/modules/camera/tasks/ResolveTakenPictureAsyncTask.java +0 -288
- package/android/src/main/java/expo/modules/camera/utils/FileSystemUtils.java +0 -21
- package/android/src/main/java/expo/modules/camera/utils/ImageDimensions.java +0 -64
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,21 @@
|
|
|
10
10
|
|
|
11
11
|
### 💡 Others
|
|
12
12
|
|
|
13
|
+
## 12.1.0 — 2021-12-03
|
|
14
|
+
|
|
15
|
+
### 🐛 Bug fixes
|
|
16
|
+
|
|
17
|
+
- Fix Gradle error when running Gradle from outside of the project directory. ([#15109](https://github.com/expo/expo/pull/15109) by [@kudo](https://github.com/kudo))
|
|
18
|
+
|
|
19
|
+
### 💡 Others
|
|
20
|
+
|
|
21
|
+
- Rewrite module to Kotlin. ([#14717](https://github.com/expo/expo/pull/14717) by [@mstach60161](https://github.com/mstach60161))
|
|
22
|
+
- [plugin] Use more specific gradle variable name. ([#14966](https://github.com/expo/expo/pull/14966) by [@EvanBacon](https://github.com/EvanBacon))
|
|
23
|
+
|
|
24
|
+
## 12.0.1 — 2021-10-01
|
|
25
|
+
|
|
26
|
+
_This version does not introduce any user-facing changes._
|
|
27
|
+
|
|
13
28
|
## 12.0.0 — 2021-09-28
|
|
14
29
|
|
|
15
30
|
### 🛠 Breaking changes
|
|
@@ -20,6 +35,7 @@
|
|
|
20
35
|
### 🎉 New features
|
|
21
36
|
|
|
22
37
|
- Add `useCameraPermissions` and `useMicrophonePermissions` hooks from modules factory. ([#13855](https://github.com/expo/expo/pull/13855) by [@bycedric](https://github.com/bycedric))
|
|
38
|
+
- [plugin] Add monorepo support to Android config plugin for Gradle import. ([#14521](https://github.com/expo/expo/pull/14521) by [@EvanBacon](https://github.com/EvanBacon))
|
|
23
39
|
|
|
24
40
|
### 🐛 Bug fixes
|
|
25
41
|
|
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ For managed [managed](https://docs.expo.io/versions/latest/introduction/managed-
|
|
|
13
13
|
|
|
14
14
|
# Installation in bare React Native projects
|
|
15
15
|
|
|
16
|
-
For bare React Native projects, you must ensure that you have [installed and configured the `
|
|
16
|
+
For bare React Native projects, you must ensure that you have [installed and configured the `expo` package](https://docs.expo.dev/bare/installing-expo-modules/) before continuing.
|
|
17
17
|
|
|
18
18
|
### Add the package to your npm dependencies
|
|
19
19
|
|
package/android/build.gradle
CHANGED
|
@@ -3,7 +3,7 @@ apply plugin: 'kotlin-android'
|
|
|
3
3
|
apply plugin: 'maven'
|
|
4
4
|
|
|
5
5
|
group = 'host.exp.exponent'
|
|
6
|
-
version = '12.
|
|
6
|
+
version = '12.1.0'
|
|
7
7
|
|
|
8
8
|
buildscript {
|
|
9
9
|
// Simple helper that allows the root project to override versions declared by this library.
|
|
@@ -57,8 +57,13 @@ android {
|
|
|
57
57
|
minSdkVersion safeExtGet("minSdkVersion", 21)
|
|
58
58
|
targetSdkVersion safeExtGet("targetSdkVersion", 30)
|
|
59
59
|
versionCode 32
|
|
60
|
-
versionName "12.
|
|
60
|
+
versionName "12.1.0"
|
|
61
61
|
}
|
|
62
|
+
|
|
63
|
+
kotlinOptions {
|
|
64
|
+
jvmTarget = JavaVersion.VERSION_1_8
|
|
65
|
+
}
|
|
66
|
+
|
|
62
67
|
lintOptions {
|
|
63
68
|
abortOnError false
|
|
64
69
|
}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
package expo.modules.camera
|
|
2
|
+
|
|
3
|
+
import android.Manifest
|
|
4
|
+
import android.content.Context
|
|
5
|
+
import android.os.Build
|
|
6
|
+
|
|
7
|
+
import com.google.android.cameraview.AspectRatio
|
|
8
|
+
|
|
9
|
+
import expo.modules.camera.tasks.ResolveTakenPictureAsyncTask
|
|
10
|
+
import expo.modules.core.ExportedModule
|
|
11
|
+
import expo.modules.core.ModuleRegistry
|
|
12
|
+
import expo.modules.core.interfaces.ExpoMethod
|
|
13
|
+
import expo.modules.core.ModuleRegistryDelegate
|
|
14
|
+
import expo.modules.core.Promise
|
|
15
|
+
import expo.modules.core.interfaces.services.UIManager
|
|
16
|
+
import expo.modules.interfaces.permissions.Permissions
|
|
17
|
+
|
|
18
|
+
import java.lang.Exception
|
|
19
|
+
|
|
20
|
+
class CameraModule(
|
|
21
|
+
context: Context,
|
|
22
|
+
private val moduleRegistryDelegate: ModuleRegistryDelegate = ModuleRegistryDelegate()
|
|
23
|
+
) : ExportedModule(context) {
|
|
24
|
+
|
|
25
|
+
private inline fun <reified T> moduleRegistry() = moduleRegistryDelegate.getFromModuleRegistry<T>()
|
|
26
|
+
private val permissionsManager: Permissions by moduleRegistry()
|
|
27
|
+
private val uIManager: UIManager by moduleRegistry()
|
|
28
|
+
|
|
29
|
+
override fun onCreate(moduleRegistry: ModuleRegistry) {
|
|
30
|
+
moduleRegistryDelegate.onCreate(moduleRegistry)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
override fun getName() = TAG
|
|
34
|
+
|
|
35
|
+
override fun getConstants() = mapOf(
|
|
36
|
+
"Type" to typeConstants,
|
|
37
|
+
"FlashMode" to flashModeConstants,
|
|
38
|
+
"AutoFocus" to autoFocusConstants,
|
|
39
|
+
"WhiteBalance" to whiteBalanceConstants,
|
|
40
|
+
"VideoQuality" to videoQualityConstants,
|
|
41
|
+
"FaceDetection" to emptyMap<String, Any>(),
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
@ExpoMethod
|
|
45
|
+
fun pausePreview(viewTag: Int, promise: Promise) {
|
|
46
|
+
addUIBlock(
|
|
47
|
+
viewTag,
|
|
48
|
+
object : UIManager.UIBlock<ExpoCameraView> {
|
|
49
|
+
override fun resolve(view: ExpoCameraView) {
|
|
50
|
+
try {
|
|
51
|
+
if (view.isCameraOpened) {
|
|
52
|
+
view.pausePreview()
|
|
53
|
+
}
|
|
54
|
+
} catch (e: Exception) {
|
|
55
|
+
promise.reject(ERROR_TAG, "pausePreview -- exception occurred -- " + e.message, e)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
override fun reject(throwable: Throwable) = promise.reject(ERROR_TAG, throwable)
|
|
59
|
+
}
|
|
60
|
+
)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
@ExpoMethod
|
|
64
|
+
fun resumePreview(viewTag: Int, promise: Promise) {
|
|
65
|
+
addUIBlock(
|
|
66
|
+
viewTag,
|
|
67
|
+
object : UIManager.UIBlock<ExpoCameraView> {
|
|
68
|
+
override fun resolve(view: ExpoCameraView) {
|
|
69
|
+
try {
|
|
70
|
+
if (view.isCameraOpened) {
|
|
71
|
+
view.resumePreview()
|
|
72
|
+
}
|
|
73
|
+
} catch (e: Exception) {
|
|
74
|
+
promise.reject(ERROR_TAG, "resumePreview -- exception occurred -- " + e.message, e)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
override fun reject(throwable: Throwable) = promise.reject(ERROR_TAG, throwable)
|
|
78
|
+
}
|
|
79
|
+
)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
@ExpoMethod
|
|
83
|
+
fun takePicture(options: Map<String, Any>, viewTag: Int, promise: Promise) {
|
|
84
|
+
val cacheDirectory = context.cacheDir
|
|
85
|
+
addUIBlock(
|
|
86
|
+
viewTag,
|
|
87
|
+
object : UIManager.UIBlock<ExpoCameraView> {
|
|
88
|
+
override fun resolve(view: ExpoCameraView) {
|
|
89
|
+
if (!Build.FINGERPRINT.contains("generic")) {
|
|
90
|
+
if (view.isCameraOpened) {
|
|
91
|
+
view.takePicture(options, promise, cacheDirectory)
|
|
92
|
+
} else {
|
|
93
|
+
promise.reject("E_CAMERA_UNAVAILABLE", "Camera is not running")
|
|
94
|
+
}
|
|
95
|
+
} else {
|
|
96
|
+
val image = CameraViewHelper.generateSimulatorPhoto(view.width, view.height)
|
|
97
|
+
ResolveTakenPictureAsyncTask(image, promise, options, cacheDirectory, view).execute()
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
override fun reject(throwable: Throwable) = promise.reject(ERROR_TAG, throwable)
|
|
101
|
+
}
|
|
102
|
+
)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
@ExpoMethod
|
|
106
|
+
fun record(options: Map<String?, Any?>, viewTag: Int, promise: Promise) {
|
|
107
|
+
if (permissionsManager.hasGrantedPermissions(Manifest.permission.RECORD_AUDIO)) {
|
|
108
|
+
val cacheDirectory = context.cacheDir
|
|
109
|
+
addUIBlock(
|
|
110
|
+
viewTag,
|
|
111
|
+
object : UIManager.UIBlock<ExpoCameraView> {
|
|
112
|
+
override fun resolve(view: ExpoCameraView) {
|
|
113
|
+
if (view.isCameraOpened) {
|
|
114
|
+
view.record(options, promise, cacheDirectory)
|
|
115
|
+
} else {
|
|
116
|
+
promise.reject("E_CAMERA_UNAVAILABLE", "Camera is not running")
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
override fun reject(throwable: Throwable) = promise.reject(ERROR_TAG, throwable)
|
|
120
|
+
}
|
|
121
|
+
)
|
|
122
|
+
} else {
|
|
123
|
+
promise.reject(SecurityException("User rejected audio permissions"))
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
@ExpoMethod
|
|
128
|
+
fun stopRecording(viewTag: Int, promise: Promise) {
|
|
129
|
+
addUIBlock(
|
|
130
|
+
viewTag,
|
|
131
|
+
object : UIManager.UIBlock<ExpoCameraView> {
|
|
132
|
+
override fun resolve(view: ExpoCameraView) {
|
|
133
|
+
if (view.isCameraOpened) {
|
|
134
|
+
view.stopRecording()
|
|
135
|
+
promise.resolve(true)
|
|
136
|
+
} else {
|
|
137
|
+
promise.reject(ERROR_TAG, "Camera is not open")
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
override fun reject(throwable: Throwable) = promise.reject(ERROR_TAG, throwable)
|
|
141
|
+
}
|
|
142
|
+
)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
@ExpoMethod
|
|
146
|
+
fun getSupportedRatios(viewTag: Int, promise: Promise) {
|
|
147
|
+
addUIBlock(
|
|
148
|
+
viewTag,
|
|
149
|
+
object : UIManager.UIBlock<ExpoCameraView> {
|
|
150
|
+
override fun resolve(view: ExpoCameraView) {
|
|
151
|
+
if (view.isCameraOpened) {
|
|
152
|
+
promise.resolve(view.supportedAspectRatios.map { it.toString() })
|
|
153
|
+
} else {
|
|
154
|
+
promise.reject(ERROR_TAG, "Camera is not running")
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
override fun reject(throwable: Throwable) = promise.reject(ERROR_TAG, throwable)
|
|
158
|
+
}
|
|
159
|
+
)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
@ExpoMethod
|
|
163
|
+
fun getAvailablePictureSizes(ratio: String?, viewTag: Int, promise: Promise) {
|
|
164
|
+
addUIBlock(
|
|
165
|
+
viewTag,
|
|
166
|
+
object : UIManager.UIBlock<ExpoCameraView> {
|
|
167
|
+
override fun resolve(view: ExpoCameraView) {
|
|
168
|
+
if (view.isCameraOpened) {
|
|
169
|
+
try {
|
|
170
|
+
val sizes = view.getAvailablePictureSizes(AspectRatio.parse(ratio))
|
|
171
|
+
promise.resolve(sizes.map { it.toString() })
|
|
172
|
+
} catch (e: Exception) {
|
|
173
|
+
promise.reject(ERROR_TAG, "getAvailablePictureSizes -- unexpected error -- " + e.message, e)
|
|
174
|
+
}
|
|
175
|
+
} else {
|
|
176
|
+
promise.reject(ERROR_TAG, "Camera is not running")
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
override fun reject(throwable: Throwable) = promise.reject(ERROR_TAG, throwable)
|
|
180
|
+
}
|
|
181
|
+
)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
private fun addUIBlock(viewTag: Int, block: UIManager.UIBlock<ExpoCameraView>) {
|
|
185
|
+
uIManager.addUIBlock(viewTag, block, ExpoCameraView::class.java)
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
@ExpoMethod
|
|
189
|
+
fun requestPermissionsAsync(promise: Promise) {
|
|
190
|
+
permissionsManager.askForPermissionsWithPromise(promise, Manifest.permission.CAMERA)
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
@ExpoMethod
|
|
194
|
+
fun requestCameraPermissionsAsync(promise: Promise) {
|
|
195
|
+
permissionsManager.askForPermissionsWithPromise(promise, Manifest.permission.CAMERA)
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
@ExpoMethod
|
|
199
|
+
fun requestMicrophonePermissionsAsync(promise: Promise) {
|
|
200
|
+
permissionsManager.askForPermissionsWithPromise(promise, Manifest.permission.RECORD_AUDIO)
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
@ExpoMethod
|
|
204
|
+
fun getPermissionsAsync(promise: Promise) {
|
|
205
|
+
permissionsManager.getPermissionsWithPromise(promise, Manifest.permission.CAMERA)
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
@ExpoMethod
|
|
209
|
+
fun getCameraPermissionsAsync(promise: Promise) {
|
|
210
|
+
permissionsManager.getPermissionsWithPromise(promise, Manifest.permission.CAMERA)
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
@ExpoMethod
|
|
214
|
+
fun getMicrophonePermissionsAsync(promise: Promise) {
|
|
215
|
+
permissionsManager.getPermissionsWithPromise(promise, Manifest.permission.RECORD_AUDIO)
|
|
216
|
+
}
|
|
217
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
package expo.modules.camera
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import expo.modules.core.BasePackage
|
|
5
|
+
|
|
6
|
+
class CameraPackage : BasePackage() {
|
|
7
|
+
override fun createExportedModules(context: Context) = listOf(CameraModule(context))
|
|
8
|
+
|
|
9
|
+
override fun createViewManagers(context: Context) = listOf(CameraViewManager())
|
|
10
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
package expo.modules.camera
|
|
2
|
+
|
|
3
|
+
import androidx.exifinterface.media.ExifInterface
|
|
4
|
+
import android.graphics.Bitmap
|
|
5
|
+
import android.graphics.Canvas
|
|
6
|
+
import android.graphics.Color
|
|
7
|
+
import android.graphics.Paint
|
|
8
|
+
import android.media.CamcorderProfile
|
|
9
|
+
import android.os.Bundle
|
|
10
|
+
import android.view.ViewGroup
|
|
11
|
+
|
|
12
|
+
import com.google.android.cameraview.CameraView
|
|
13
|
+
|
|
14
|
+
import expo.modules.camera.events.CameraMountErrorEvent
|
|
15
|
+
import expo.modules.camera.events.CameraReadyEvent
|
|
16
|
+
import expo.modules.interfaces.barcodescanner.BarCodeScannerResult
|
|
17
|
+
import expo.modules.core.interfaces.services.EventEmitter
|
|
18
|
+
import expo.modules.camera.events.FacesDetectedEvent
|
|
19
|
+
import expo.modules.interfaces.facedetector.FaceDetectorInterface
|
|
20
|
+
import expo.modules.camera.events.FaceDetectionErrorEvent
|
|
21
|
+
import expo.modules.camera.events.PictureSavedEvent
|
|
22
|
+
import expo.modules.camera.events.BarCodeScannedEvent
|
|
23
|
+
import java.io.IOException
|
|
24
|
+
import java.text.SimpleDateFormat
|
|
25
|
+
import java.util.*
|
|
26
|
+
|
|
27
|
+
object CameraViewHelper {
|
|
28
|
+
// Mount error event
|
|
29
|
+
@JvmStatic
|
|
30
|
+
fun emitMountErrorEvent(emitter: EventEmitter, view: ViewGroup, message: String) {
|
|
31
|
+
val event = CameraMountErrorEvent.obtain(message)
|
|
32
|
+
emitter.emit(view.id, event)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Camera ready event
|
|
36
|
+
@JvmStatic
|
|
37
|
+
fun emitCameraReadyEvent(emitter: EventEmitter, view: ViewGroup) {
|
|
38
|
+
val event = CameraReadyEvent.obtain()
|
|
39
|
+
emitter.emit(view.id, event)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Bar code read event
|
|
43
|
+
@JvmStatic
|
|
44
|
+
fun emitBarCodeReadEvent(emitter: EventEmitter, view: ViewGroup, barCode: BarCodeScannerResult) {
|
|
45
|
+
val event = BarCodeScannedEvent.obtain(view.id, barCode)
|
|
46
|
+
emitter.emit(view.id, event)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Face detection events
|
|
50
|
+
@JvmStatic
|
|
51
|
+
fun emitFacesDetectedEvent(emitter: EventEmitter, view: ViewGroup, faces: List<Bundle>) {
|
|
52
|
+
val event = FacesDetectedEvent.obtain(view.id, faces)
|
|
53
|
+
emitter.emit(view.id, event)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
@JvmStatic
|
|
57
|
+
fun emitFaceDetectionErrorEvent(emitter: EventEmitter, view: ViewGroup, faceDetector: FaceDetectorInterface) {
|
|
58
|
+
val event = FaceDetectionErrorEvent.obtain(faceDetector)
|
|
59
|
+
emitter.emit(view.id, event)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Picture saved
|
|
63
|
+
@JvmStatic
|
|
64
|
+
fun emitPictureSavedEvent(emitter: EventEmitter, view: ViewGroup, info: Bundle) {
|
|
65
|
+
val event = PictureSavedEvent.obtain(info)
|
|
66
|
+
emitter.emit(view.id, event)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Utilities
|
|
70
|
+
@JvmStatic
|
|
71
|
+
fun getCorrectCameraRotation(rotation: Int, facing: Int) =
|
|
72
|
+
if (facing == CameraView.FACING_FRONT) (rotation - 90 + 360) % 360
|
|
73
|
+
else (-rotation + 90 + 360) % 360
|
|
74
|
+
|
|
75
|
+
@JvmStatic
|
|
76
|
+
fun getCamcorderProfile(cameraId: Int, quality: Int): CamcorderProfile {
|
|
77
|
+
var profile = CamcorderProfile.get(cameraId, CamcorderProfile.QUALITY_HIGH)
|
|
78
|
+
when (quality) {
|
|
79
|
+
VIDEO_2160P -> profile = CamcorderProfile.get(cameraId, CamcorderProfile.QUALITY_2160P)
|
|
80
|
+
VIDEO_1080P -> profile = CamcorderProfile.get(cameraId, CamcorderProfile.QUALITY_1080P)
|
|
81
|
+
VIDEO_720P -> profile = CamcorderProfile.get(cameraId, CamcorderProfile.QUALITY_720P)
|
|
82
|
+
VIDEO_480P -> profile = CamcorderProfile.get(cameraId, CamcorderProfile.QUALITY_480P)
|
|
83
|
+
VIDEO_4x3 -> {
|
|
84
|
+
profile = CamcorderProfile.get(cameraId, CamcorderProfile.QUALITY_480P)
|
|
85
|
+
profile.videoFrameWidth = 640
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return profile
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
@JvmStatic
|
|
92
|
+
fun getExifData(exifInterface: ExifInterface): Bundle {
|
|
93
|
+
val exifMap = Bundle()
|
|
94
|
+
for ((type, name) in exifTags) {
|
|
95
|
+
if (exifInterface.getAttribute(name) != null) {
|
|
96
|
+
when (type) {
|
|
97
|
+
"string" -> exifMap.putString(name, exifInterface.getAttribute(name))
|
|
98
|
+
"int" -> exifMap.putInt(name, exifInterface.getAttributeInt(name, 0))
|
|
99
|
+
"double" -> exifMap.putDouble(name, exifInterface.getAttributeDouble(name, 0.0))
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
exifInterface.latLong?.let {
|
|
104
|
+
exifMap.putDouble(ExifInterface.TAG_GPS_LATITUDE, it[0])
|
|
105
|
+
exifMap.putDouble(ExifInterface.TAG_GPS_LONGITUDE, it[1])
|
|
106
|
+
exifMap.putDouble(ExifInterface.TAG_GPS_ALTITUDE, exifInterface.getAltitude(0.0))
|
|
107
|
+
}
|
|
108
|
+
return exifMap
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
@JvmStatic
|
|
112
|
+
@Throws(IOException::class)
|
|
113
|
+
fun addExifData(baseExif: ExifInterface, additionalExif: ExifInterface) {
|
|
114
|
+
for (tagInfo in exifTags) {
|
|
115
|
+
val name = tagInfo[1]
|
|
116
|
+
additionalExif.getAttribute(name)?.let {
|
|
117
|
+
baseExif.setAttribute(name, it)
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
baseExif.saveAttributes()
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
fun generateSimulatorPhoto(width: Int, height: Int): Bitmap {
|
|
124
|
+
val fakePhoto = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
|
|
125
|
+
val canvas = Canvas(fakePhoto)
|
|
126
|
+
val background = Paint().apply {
|
|
127
|
+
color = Color.BLACK
|
|
128
|
+
}
|
|
129
|
+
canvas.drawRect(0f, 0f, width.toFloat(), height.toFloat(), background)
|
|
130
|
+
val textPaint = Paint().apply {
|
|
131
|
+
color = Color.YELLOW
|
|
132
|
+
textSize = 35f
|
|
133
|
+
}
|
|
134
|
+
val calendar = Calendar.getInstance()
|
|
135
|
+
val simpleDateFormat = SimpleDateFormat("dd.MM.yy HH:mm:ss", Locale.US)
|
|
136
|
+
canvas.drawText(simpleDateFormat.format(calendar.time), width * 0.1f, height * 0.9f, textPaint)
|
|
137
|
+
return fakePhoto
|
|
138
|
+
}
|
|
139
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
package expo.modules.camera
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
|
|
5
|
+
import com.google.android.cameraview.AspectRatio
|
|
6
|
+
import com.google.android.cameraview.Size
|
|
7
|
+
|
|
8
|
+
import expo.modules.core.interfaces.ExpoProp
|
|
9
|
+
import expo.modules.core.interfaces.services.UIManager
|
|
10
|
+
import expo.modules.core.ModuleRegistry
|
|
11
|
+
import expo.modules.core.ModuleRegistryDelegate
|
|
12
|
+
import expo.modules.core.ViewManager
|
|
13
|
+
import expo.modules.interfaces.barcodescanner.BarCodeScannerSettings
|
|
14
|
+
|
|
15
|
+
class CameraViewManager(
|
|
16
|
+
private val moduleRegistryDelegate: ModuleRegistryDelegate = ModuleRegistryDelegate()
|
|
17
|
+
) : ViewManager<ExpoCameraView>() {
|
|
18
|
+
|
|
19
|
+
private inline fun <reified T> moduleRegistry() = moduleRegistryDelegate.getFromModuleRegistry<T>()
|
|
20
|
+
|
|
21
|
+
enum class Events(private val eventsName: String) {
|
|
22
|
+
EVENT_CAMERA_READY("onCameraReady"),
|
|
23
|
+
EVENT_ON_MOUNT_ERROR("onMountError"),
|
|
24
|
+
EVENT_ON_BAR_CODE_SCANNED("onBarCodeScanned"),
|
|
25
|
+
EVENT_ON_FACES_DETECTED("onFacesDetected"),
|
|
26
|
+
EVENT_ON_FACE_DETECTION_ERROR("onFaceDetectionError"),
|
|
27
|
+
EVENT_ON_PICTURE_SAVED("onPictureSaved");
|
|
28
|
+
override fun toString() = eventsName
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
override fun onCreate(moduleRegistry: ModuleRegistry) {
|
|
32
|
+
moduleRegistryDelegate.onCreate(moduleRegistry)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
override fun onDropViewInstance(view: ExpoCameraView) {
|
|
36
|
+
val uIManager: UIManager by moduleRegistry()
|
|
37
|
+
uIManager.unregisterLifecycleEventListener(view)
|
|
38
|
+
view.stop()
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
override fun getName() = REACT_CLASS
|
|
42
|
+
|
|
43
|
+
override fun getViewManagerType() = ViewManagerType.GROUP
|
|
44
|
+
|
|
45
|
+
override fun createViewInstance(context: Context) =
|
|
46
|
+
ExpoCameraView(context, moduleRegistryDelegate)
|
|
47
|
+
|
|
48
|
+
override fun getExportedEventNames() = Events.values().map {
|
|
49
|
+
it.toString()
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
@ExpoProp(name = "type")
|
|
53
|
+
fun setType(view: ExpoCameraView, type: Int) {
|
|
54
|
+
view.facing = type
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
@ExpoProp(name = "ratio")
|
|
58
|
+
fun setRatio(view: ExpoCameraView, ratio: String?) {
|
|
59
|
+
view.setAspectRatio(AspectRatio.parse(ratio))
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
@ExpoProp(name = "flashMode")
|
|
63
|
+
fun setFlashMode(view: ExpoCameraView, torchMode: Int) {
|
|
64
|
+
view.flash = torchMode
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
@ExpoProp(name = "autoFocus")
|
|
68
|
+
fun setAutoFocus(view: ExpoCameraView, autoFocus: Boolean) {
|
|
69
|
+
view.autoFocus = autoFocus
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
@ExpoProp(name = "focusDepth")
|
|
73
|
+
fun setFocusDepth(view: ExpoCameraView, depth: Float) {
|
|
74
|
+
view.focusDepth = depth
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
@ExpoProp(name = "zoom")
|
|
78
|
+
fun setZoom(view: ExpoCameraView, zoom: Float) {
|
|
79
|
+
view.zoom = zoom
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
@ExpoProp(name = "whiteBalance")
|
|
83
|
+
fun setWhiteBalance(view: ExpoCameraView, whiteBalance: Int) {
|
|
84
|
+
view.whiteBalance = whiteBalance
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
@ExpoProp(name = "pictureSize")
|
|
88
|
+
fun setPictureSize(view: ExpoCameraView, size: String?) {
|
|
89
|
+
view.pictureSize = Size.parse(size)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
@ExpoProp(name = "barCodeScannerSettings")
|
|
93
|
+
fun setBarCodeScannerSettings(view: ExpoCameraView, settings: Map<String?, Any?>?) {
|
|
94
|
+
view.setBarCodeScannerSettings(BarCodeScannerSettings(settings))
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
@ExpoProp(name = "useCamera2Api")
|
|
98
|
+
fun setUseCamera2Api(view: ExpoCameraView, useCamera2Api: Boolean) {
|
|
99
|
+
view.setUsingCamera2Api(useCamera2Api)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
@ExpoProp(name = "barCodeScannerEnabled")
|
|
103
|
+
fun setBarCodeScanning(view: ExpoCameraView, barCodeScannerEnabled: Boolean) {
|
|
104
|
+
view.setShouldScanBarCodes(barCodeScannerEnabled)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
@ExpoProp(name = "faceDetectorEnabled")
|
|
108
|
+
fun setFaceDetectorEnabled(view: ExpoCameraView, faceDetectorEnabled: Boolean) {
|
|
109
|
+
view.setShouldDetectFaces(faceDetectorEnabled)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
@ExpoProp(name = "faceDetectorSettings")
|
|
113
|
+
fun setFaceDetectorSettings(view: ExpoCameraView, settings: Map<String, Any>?) {
|
|
114
|
+
view.setFaceDetectorSettings(settings)
|
|
115
|
+
}
|
|
116
|
+
}
|