expo-camera 12.0.2 → 12.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/CHANGELOG.md +23 -2
  2. package/README.md +1 -1
  3. package/android/build.gradle +22 -19
  4. package/android/src/main/java/expo/modules/camera/CameraModule.kt +217 -0
  5. package/android/src/main/java/expo/modules/camera/CameraPackage.kt +10 -0
  6. package/android/src/main/java/expo/modules/camera/CameraViewHelper.kt +139 -0
  7. package/android/src/main/java/expo/modules/camera/CameraViewManager.kt +116 -0
  8. package/android/src/main/java/expo/modules/camera/Constants.kt +184 -0
  9. package/android/src/main/java/expo/modules/camera/ExpoCameraView.kt +329 -0
  10. package/android/src/main/java/expo/modules/camera/events/BarCodeScannedEvent.kt +50 -0
  11. package/android/src/main/java/expo/modules/camera/events/CameraMountErrorEvent.kt +33 -0
  12. package/android/src/main/java/expo/modules/camera/events/CameraReadyEvent.kt +23 -0
  13. package/android/src/main/java/expo/modules/camera/events/FaceDetectionErrorEvent.kt +39 -0
  14. package/android/src/main/java/expo/modules/camera/events/FacesDetectedEvent.kt +46 -0
  15. package/android/src/main/java/expo/modules/camera/events/PictureSavedEvent.kt +41 -0
  16. package/android/src/main/java/expo/modules/camera/tasks/BarCodeScannerAsyncTask.kt +26 -0
  17. package/android/src/main/java/expo/modules/camera/tasks/BarCodeScannerAsyncTaskDelegate.kt +8 -0
  18. package/android/src/main/java/expo/modules/camera/tasks/FaceDetectorAsyncTaskDelegate.kt +10 -0
  19. package/android/src/main/java/expo/modules/camera/tasks/FaceDetectorTask.kt +34 -0
  20. package/android/src/main/java/expo/modules/camera/tasks/PictureSavedDelegate.kt +7 -0
  21. package/android/src/main/java/expo/modules/camera/tasks/ResolveTakenPictureAsyncTask.kt +231 -0
  22. package/android/src/main/java/expo/modules/camera/utils/FileSystemUtils.kt +23 -0
  23. package/android/src/main/java/expo/modules/camera/utils/ImageDimensions.kt +14 -0
  24. package/build/ExponentCameraManager.web.js +3 -1
  25. package/build/ExponentCameraManager.web.js.map +1 -1
  26. package/ios/EXCamera.xcframework/ios-arm64/EXCamera.framework/EXCamera +0 -0
  27. package/ios/EXCamera.xcframework/ios-arm64/EXCamera.framework/Info.plist +0 -0
  28. package/ios/EXCamera.xcframework/ios-arm64_x86_64-simulator/EXCamera.framework/EXCamera +0 -0
  29. package/ios/EXCamera.xcframework/ios-arm64_x86_64-simulator/EXCamera.framework/Info.plist +0 -0
  30. package/package.json +7 -5
  31. package/plugin/build/withCamera.d.ts +2 -1
  32. package/plugin/build/withCamera.js +50 -30
  33. package/plugin/src/withCamera.ts +66 -27
  34. package/src/ExponentCameraManager.web.ts +3 -2
  35. package/src/{types → ts-declarations}/image-capture.d.ts +0 -0
  36. package/src/ts-declarations/lib.dom.d.ts +34 -0
  37. package/android/src/main/java/expo/modules/camera/CameraModule.java +0 -359
  38. package/android/src/main/java/expo/modules/camera/CameraPackage.java +0 -23
  39. package/android/src/main/java/expo/modules/camera/CameraViewHelper.java +0 -294
  40. package/android/src/main/java/expo/modules/camera/CameraViewManager.java +0 -142
  41. package/android/src/main/java/expo/modules/camera/ExpoCameraView.java +0 -376
  42. package/android/src/main/java/expo/modules/camera/events/BarCodeScannedEvent.java +0 -59
  43. package/android/src/main/java/expo/modules/camera/events/CameraMountErrorEvent.java +0 -38
  44. package/android/src/main/java/expo/modules/camera/events/CameraReadyEvent.java +0 -30
  45. package/android/src/main/java/expo/modules/camera/events/FaceDetectionErrorEvent.java +0 -50
  46. package/android/src/main/java/expo/modules/camera/events/FacesDetectedEvent.java +0 -63
  47. package/android/src/main/java/expo/modules/camera/events/PictureSavedEvent.java +0 -53
  48. package/android/src/main/java/expo/modules/camera/tasks/BarCodeScannerAsyncTask.java +0 -47
  49. package/android/src/main/java/expo/modules/camera/tasks/BarCodeScannerAsyncTaskDelegate.java +0 -8
  50. package/android/src/main/java/expo/modules/camera/tasks/FaceDetectorAsyncTaskDelegate.java +0 -13
  51. package/android/src/main/java/expo/modules/camera/tasks/FaceDetectorTask.java +0 -53
  52. package/android/src/main/java/expo/modules/camera/tasks/PictureSavedDelegate.java +0 -7
  53. package/android/src/main/java/expo/modules/camera/tasks/ResolveTakenPictureAsyncTask.java +0 -288
  54. package/android/src/main/java/expo/modules/camera/utils/FileSystemUtils.java +0 -21
  55. package/android/src/main/java/expo/modules/camera/utils/ImageDimensions.java +0 -64
package/CHANGELOG.md CHANGED
@@ -10,9 +10,29 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
- ## 12.0.2 — 2021-10-15
13
+ ## 12.1.2 — 2022-02-04
14
14
 
15
- _This version does not introduce any user-facing changes._
15
+ ### 🐛 Bug fixes
16
+
17
+ - Fix `Plugin with id 'maven' not found` build error from Android Gradle 7. ([#16080](https://github.com/expo/expo/pull/16080) by [@kudo](https://github.com/kudo))
18
+ - Fix null pointer exception when barcode scanner or face detector are not installed. ([#16167](https://github.com/expo/expo/pull/16167) by [@tsapeta](https://github.com/tsapeta))
19
+
20
+ ## 12.1.1 — 2022-02-01
21
+
22
+ ### 🐛 Bug fixes
23
+
24
+ - Fix `Plugin with id 'maven' not found` build error from Android Gradle 7. ([#16080](https://github.com/expo/expo/pull/16080) by [@kudo](https://github.com/kudo))
25
+
26
+ ## 12.1.0 — 2021-12-03
27
+
28
+ ### 🐛 Bug fixes
29
+
30
+ - 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))
31
+
32
+ ### 💡 Others
33
+
34
+ - Rewrite module to Kotlin. ([#14717](https://github.com/expo/expo/pull/14717) by [@mstach60161](https://github.com/mstach60161))
35
+ - [plugin] Use more specific gradle variable name. ([#14966](https://github.com/expo/expo/pull/14966) by [@EvanBacon](https://github.com/EvanBacon))
16
36
 
17
37
  ## 12.0.1 — 2021-10-01
18
38
 
@@ -28,6 +48,7 @@ _This version does not introduce any user-facing changes._
28
48
  ### 🎉 New features
29
49
 
30
50
  - Add `useCameraPermissions` and `useMicrophonePermissions` hooks from modules factory. ([#13855](https://github.com/expo/expo/pull/13855) by [@bycedric](https://github.com/bycedric))
51
+ - [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))
31
52
 
32
53
  ### 🐛 Bug fixes
33
54
 
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 `react-native-unimodules` package](https://github.com/expo/expo/tree/master/packages/react-native-unimodules) before continuing.
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
 
@@ -1,9 +1,9 @@
1
1
  apply plugin: 'com.android.library'
2
2
  apply plugin: 'kotlin-android'
3
- apply plugin: 'maven'
3
+ apply plugin: 'maven-publish'
4
4
 
5
5
  group = 'host.exp.exponent'
6
- version = '12.0.2'
6
+ version = '12.1.2'
7
7
 
8
8
  buildscript {
9
9
  // Simple helper that allows the root project to override versions declared by this library.
@@ -20,27 +20,25 @@ buildscript {
20
20
  }
21
21
  }
22
22
 
23
- //Upload android library to maven with javadoc and android sources
24
- configurations {
25
- deployerJars
26
- }
27
-
28
- //Creating sources with comments
23
+ // Creating sources with comments
29
24
  task androidSourcesJar(type: Jar) {
30
25
  classifier = 'sources'
31
26
  from android.sourceSets.main.java.srcDirs
32
27
  }
33
28
 
34
- //Put the androidSources and javadoc to the artifacts
35
- artifacts {
36
- archives androidSourcesJar
37
- }
38
-
39
- uploadArchives {
40
- repositories {
41
- mavenDeployer {
42
- configuration = configurations.deployerJars
43
- repository(url: mavenLocal().url)
29
+ afterEvaluate {
30
+ publishing {
31
+ publications {
32
+ release(MavenPublication) {
33
+ from components.release
34
+ // Add additional sourcesJar to artifacts
35
+ artifact(androidSourcesJar)
36
+ }
37
+ }
38
+ repositories {
39
+ maven {
40
+ url = mavenLocal().url
41
+ }
44
42
  }
45
43
  }
46
44
  }
@@ -57,8 +55,13 @@ android {
57
55
  minSdkVersion safeExtGet("minSdkVersion", 21)
58
56
  targetSdkVersion safeExtGet("targetSdkVersion", 30)
59
57
  versionCode 32
60
- versionName "12.0.2"
58
+ versionName "12.1.2"
59
+ }
60
+
61
+ kotlinOptions {
62
+ jvmTarget = JavaVersion.VERSION_1_8
61
63
  }
64
+
62
65
  lintOptions {
63
66
  abortOnError false
64
67
  }
@@ -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
+ }