Menardi 3850491b9f
fix: Fix takeSnapshot not working on Android (#961)
Accessing previewView.bitmap was throwing an error because it wasn't being done on the main thread.
Any access to previewView needs to be done on the main (UI) thread. This commit fixes the issue by
ensuring this access is now run on the main thread.

Fixes #547
2022-04-04 11:03:08 +02:00

61 lines
2.0 KiB
Kotlin

package com.mrousavy.camera
import android.graphics.Bitmap
import androidx.exifinterface.media.ExifInterface
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.bridge.WritableMap
import com.mrousavy.camera.utils.buildMetadataMap
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.withContext
import java.io.File
import java.io.FileOutputStream
import kotlinx.coroutines.guava.await
suspend fun CameraView.takeSnapshot(options: ReadableMap): WritableMap = coroutineScope {
val camera = camera ?: throw com.mrousavy.camera.CameraNotReadyError()
val enableFlash = options.getString("flash") == "on"
try {
if (enableFlash) {
camera.cameraControl.enableTorch(true).await()
}
val bitmap = withContext(coroutineScope.coroutineContext) {
previewView.bitmap ?: throw CameraNotReadyError()
}
val quality = if (options.hasKey("quality")) options.getInt("quality") else 100
val file: File
val exif: ExifInterface
@Suppress("BlockingMethodInNonBlockingContext")
withContext(Dispatchers.IO) {
file = File.createTempFile("mrousavy", ".jpg", context.cacheDir).apply { deleteOnExit() }
FileOutputStream(file).use { stream ->
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, stream)
}
exif = ExifInterface(file)
}
val map = Arguments.createMap()
map.putString("path", file.absolutePath)
map.putInt("width", bitmap.width)
map.putInt("height", bitmap.height)
map.putBoolean("isRawPhoto", false)
val skipMetadata =
if (options.hasKey("skipMetadata")) options.getBoolean("skipMetadata") else false
val metadata = if (skipMetadata) null else exif.buildMetadataMap()
map.putMap("metadata", metadata)
return@coroutineScope map
} finally {
if (enableFlash) {
// reset to `torch` property
camera.cameraControl.enableTorch(this@takeSnapshot.torch == "on")
}
}
}