diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 6d7aba8..184028e 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -90,6 +90,9 @@
+
diff --git a/app/src/main/java/com/nova/brain/glass/helper/OfflineCmdServiceHelper.kt b/app/src/main/java/com/nova/brain/glass/helper/OfflineCmdServiceHelper.kt
index f34a6fb..9c43023 100644
--- a/app/src/main/java/com/nova/brain/glass/helper/OfflineCmdServiceHelper.kt
+++ b/app/src/main/java/com/nova/brain/glass/helper/OfflineCmdServiceHelper.kt
@@ -45,7 +45,14 @@ object OfflineCmdServiceHelper {
)
private val CMDS_SPRAYING = listOf(
OfflineCmdBean("开始", "kai shi"),
- OfflineCmdBean("开始任务", "kai shi ren wu")
+ OfflineCmdBean("开始任务", "kai shi ren wu"),
+ OfflineCmdBean("拍照", "pai zhao"),
+ OfflineCmdBean("拍摄", "pai she"),
+ OfflineCmdBean("放大", "fang da"),
+ OfflineCmdBean("拉近", "la jin"),
+ OfflineCmdBean("缩小", "suo xiao"),
+ OfflineCmdBean("拉远", "la yuan"),
+ OfflineCmdBean("取消", "qu xiao")
)
private val CMDS_SPRAYING_FINISH = listOf(
OfflineCmdBean("补充照片", "bu chong zhao pian"),
diff --git a/app/src/main/java/com/nova/brain/glass/ui/CameraPreviewPocActivity.kt b/app/src/main/java/com/nova/brain/glass/ui/CameraPreviewPocActivity.kt
new file mode 100644
index 0000000..c5a3ff6
--- /dev/null
+++ b/app/src/main/java/com/nova/brain/glass/ui/CameraPreviewPocActivity.kt
@@ -0,0 +1,407 @@
+package com.nova.brain.glass.ui
+
+import android.Manifest
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.graphics.ImageFormat
+import android.graphics.Rect
+import android.graphics.SurfaceTexture
+import android.hardware.camera2.CameraCaptureSession
+import android.hardware.camera2.CameraCharacteristics
+import android.hardware.camera2.CameraAccessException
+import android.hardware.camera2.CameraDevice
+import android.hardware.camera2.CameraManager
+import android.hardware.camera2.CaptureRequest
+import android.hardware.camera2.TotalCaptureResult
+import android.hardware.camera2.params.StreamConfigurationMap
+import android.media.ImageReader
+import android.os.Bundle
+import android.os.Environment
+import android.os.Handler
+import android.os.HandlerThread
+import android.view.KeyEvent
+import android.view.Surface
+import android.view.TextureView
+import androidx.core.app.ActivityCompat
+import com.nova.brain.glass.R
+import com.nova.brain.glass.databinding.ActivityCameraPreviewPocBinding
+import com.nova.brain.glass.helper.OfflineCmdListener
+import com.nova.brain.glass.helper.OfflineCmdServiceHelper
+import com.xuqm.base.extensions.showMessage
+import com.xuqm.base.ui.BaseActivity
+import java.io.File
+import java.io.FileOutputStream
+import java.util.UUID
+import kotlin.math.roundToInt
+
+class CameraPreviewPocActivity : BaseActivity() {
+
+ companion object {
+ const val EXTRA_PHOTO_PATH = "extra_photo_path"
+ private const val REQUEST_CAMERA_PERMISSION = 1001
+ }
+
+ override fun getLayoutId(): Int = R.layout.activity_camera_preview_poc
+ override fun fullscreen(): Boolean = true
+
+ private val cameraManager by lazy { getSystemService(CameraManager::class.java) }
+ private var cameraDevice: CameraDevice? = null
+ private var captureSession: CameraCaptureSession? = null
+ private var previewRequestBuilder: CaptureRequest.Builder? = null
+ private var imageReader: ImageReader? = null
+ private var backgroundThread: HandlerThread? = null
+ private var backgroundHandler: Handler? = null
+ private var activeArraySize: Rect? = null
+ private var maxZoom = 1f
+ private var zoomLevel = 1f
+ private var currentOutputPath: String? = null
+ private var isCapturing = false
+
+ private val offlineCmdListener = object : OfflineCmdListener {
+ override fun onOfflineCmd(cmd: String) {
+ runOnUiThread {
+ when (cmd) {
+ "退出", "返回", "退回", "取消" -> finish()
+ "拍照", "拍摄", "开始", "开始任务" -> captureStillImage()
+ "放大", "拉近" -> adjustZoom(0.2f)
+ "缩小", "拉远" -> adjustZoom(-0.2f)
+ }
+ }
+ }
+ }
+
+ private val textureListener = object : TextureView.SurfaceTextureListener {
+ override fun onSurfaceTextureAvailable(surface: SurfaceTexture, width: Int, height: Int) {
+ openCamera()
+ }
+
+ override fun onSurfaceTextureSizeChanged(surface: SurfaceTexture, width: Int, height: Int) = Unit
+ override fun onSurfaceTextureDestroyed(surface: SurfaceTexture): Boolean = true
+ override fun onSurfaceTextureUpdated(surface: SurfaceTexture) = Unit
+ }
+
+ override fun initView(savedInstanceState: Bundle?) {
+ super.initView(savedInstanceState)
+ binding.previewView.surfaceTextureListener = textureListener
+ binding.captureButton.setOnClickListener { captureStillImage() }
+ binding.zoomInButton.setOnClickListener { adjustZoom(0.2f) }
+ binding.zoomOutButton.setOnClickListener { adjustZoom(-0.2f) }
+ updateZoomText()
+ }
+
+ override fun onResume() {
+ super.onResume()
+ startBackgroundThread()
+ OfflineCmdServiceHelper.addOnLineListener(offlineCmdListener)
+ OfflineCmdServiceHelper.addListenerSpraying()
+ if (binding.previewView.isAvailable) {
+ openCamera()
+ } else {
+ binding.previewView.surfaceTextureListener = textureListener
+ }
+ }
+
+ override fun onPause() {
+ closeCamera()
+ OfflineCmdServiceHelper.removeListenerSpraying()
+ OfflineCmdServiceHelper.removeOnLineListener(offlineCmdListener)
+ stopBackgroundThread()
+ super.onPause()
+ }
+
+ override fun dispatchKeyEvent(event: KeyEvent): Boolean {
+ if (event.action != KeyEvent.ACTION_DOWN) return super.dispatchKeyEvent(event)
+ return when (event.keyCode) {
+ KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_MINUS, KeyEvent.KEYCODE_VOLUME_DOWN -> {
+ adjustZoom(-0.2f)
+ true
+ }
+ KeyEvent.KEYCODE_DPAD_RIGHT, KeyEvent.KEYCODE_EQUALS, KeyEvent.KEYCODE_VOLUME_UP -> {
+ adjustZoom(0.2f)
+ true
+ }
+ KeyEvent.KEYCODE_DPAD_CENTER, KeyEvent.KEYCODE_ENTER, KeyEvent.KEYCODE_CAMERA -> {
+ captureStillImage()
+ true
+ }
+ else -> super.dispatchKeyEvent(event)
+ }
+ }
+
+ override fun onRequestPermissionsResult(
+ requestCode: Int,
+ permissions: Array,
+ grantResults: IntArray
+ ) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults)
+ if (requestCode != REQUEST_CAMERA_PERMISSION) return
+ if (grantResults.all { it == PackageManager.PERMISSION_GRANTED }) {
+ openCamera()
+ } else {
+ "缺少相机权限,无法验证预览".showMessage()
+ finish()
+ }
+ }
+
+ private fun openCamera() {
+ if (
+ ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED
+ ) {
+ ActivityCompat.requestPermissions(
+ this,
+ arrayOf(Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO),
+ REQUEST_CAMERA_PERMISSION
+ )
+ return
+ }
+ try {
+ val selectedCameraId = selectBackCameraId() ?: run {
+ "未找到可用相机".showMessage()
+ finish()
+ return
+ }
+ val characteristics = cameraManager.getCameraCharacteristics(selectedCameraId)
+ activeArraySize = characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE)
+ maxZoom = (characteristics.get(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM) ?: 1f)
+ .coerceAtLeast(1f)
+ zoomLevel = zoomLevel.coerceIn(1f, maxZoom)
+ val streamMap = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)
+ val previewSize = choosePreviewSize(streamMap)
+ val captureSize = chooseCaptureSize(streamMap)
+ val texture = binding.previewView.surfaceTexture ?: return
+ texture.setDefaultBufferSize(previewSize.width, previewSize.height)
+ imageReader?.close()
+ imageReader = ImageReader.newInstance(captureSize.width, captureSize.height, ImageFormat.JPEG, 2).apply {
+ setOnImageAvailableListener({ reader ->
+ val image = reader.acquireNextImage() ?: return@setOnImageAvailableListener
+ val outputPath = currentOutputPath
+ if (outputPath == null) {
+ image.close()
+ return@setOnImageAvailableListener
+ }
+ val buffer = image.planes.firstOrNull()?.buffer
+ val bytes = ByteArray(buffer?.remaining() ?: 0)
+ buffer?.get(bytes)
+ image.close()
+ runCatching {
+ FileOutputStream(outputPath).use { it.write(bytes) }
+ }.onSuccess {
+ runOnUiThread {
+ setResult(RESULT_OK, Intent().putExtra(EXTRA_PHOTO_PATH, outputPath))
+ finish()
+ }
+ }.onFailure {
+ isCapturing = false
+ runOnUiThread {
+ binding.statusText.text = "图片保存失败: ${it.message ?: "未知错误"}"
+ }
+ }
+ }, backgroundHandler)
+ }
+ binding.statusText.text = "相机预览验证中,可拉近拉远后拍照"
+ cameraManager.openCamera(selectedCameraId, object : CameraDevice.StateCallback() {
+ override fun onOpened(device: CameraDevice) {
+ cameraDevice = device
+ createPreviewSession(texture)
+ }
+
+ override fun onDisconnected(device: CameraDevice) {
+ device.close()
+ cameraDevice = null
+ runOnUiThread { binding.statusText.text = "相机已断开" }
+ }
+
+ override fun onError(device: CameraDevice, error: Int) {
+ device.close()
+ cameraDevice = null
+ runOnUiThread { binding.statusText.text = "相机打开失败: $error" }
+ }
+ }, backgroundHandler)
+ } catch (securityException: SecurityException) {
+ binding.statusText.text = "缺少相机权限"
+ "缺少相机权限,无法打开预览".showMessage()
+ }
+ }
+
+ private fun createPreviewSession(texture: SurfaceTexture) {
+ val device = cameraDevice ?: return
+ val previewSurface = Surface(texture)
+ previewRequestBuilder = try {
+ device.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW).apply {
+ addTarget(previewSurface)
+ set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO)
+ set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE)
+ applyZoom(this)
+ }
+ } catch (e: CameraAccessException) {
+ handleCameraFailure("相机预览初始化失败: ${e.message}")
+ return
+ } catch (e: IllegalStateException) {
+ handleCameraFailure("相机设备不可用: ${e.message}")
+ return
+ }
+ val readerSurface = imageReader?.surface ?: return
+ try {
+ device.createCaptureSession(
+ listOf(previewSurface, readerSurface),
+ object : CameraCaptureSession.StateCallback() {
+ override fun onConfigured(session: CameraCaptureSession) {
+ captureSession = session
+ val request = previewRequestBuilder?.build() ?: return
+ try {
+ session.setRepeatingRequest(request, null, backgroundHandler)
+ } catch (e: CameraAccessException) {
+ handleCameraFailure("相机预览启动失败: ${e.message}")
+ } catch (e: IllegalStateException) {
+ handleCameraFailure("相机会话不可用: ${e.message}")
+ }
+ }
+
+ override fun onConfigureFailed(session: CameraCaptureSession) {
+ handleCameraFailure("相机预览配置失败")
+ }
+ },
+ backgroundHandler
+ )
+ } catch (e: CameraAccessException) {
+ handleCameraFailure("相机会话创建失败: ${e.message}")
+ } catch (e: IllegalStateException) {
+ handleCameraFailure("相机会话不可用: ${e.message}")
+ }
+ }
+
+ private fun captureStillImage() {
+ if (isCapturing) return
+ val device = cameraDevice ?: return
+ val session = captureSession ?: return
+ val readerSurface = imageReader?.surface ?: return
+ val outputPath = createOutputFile().absolutePath
+ currentOutputPath = outputPath
+ isCapturing = true
+ binding.statusText.text = "拍照中,请保持稳定..."
+ try {
+ val captureBuilder = device.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE).apply {
+ addTarget(readerSurface)
+ set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO)
+ set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE)
+ applyZoom(this)
+ set(CaptureRequest.JPEG_ORIENTATION, 0)
+ }
+ session.stopRepeating()
+ session.capture(captureBuilder.build(), object : CameraCaptureSession.CaptureCallback() {
+ override fun onCaptureCompleted(
+ session: CameraCaptureSession,
+ request: CaptureRequest,
+ result: TotalCaptureResult
+ ) {
+ previewRequestBuilder?.build()?.let {
+ runCatching {
+ session.setRepeatingRequest(it, null, backgroundHandler)
+ }
+ }
+ }
+ }, backgroundHandler)
+ } catch (e: CameraAccessException) {
+ isCapturing = false
+ handleCameraFailure("拍照失败: ${e.message}")
+ } catch (e: IllegalStateException) {
+ isCapturing = false
+ handleCameraFailure("相机设备不可用: ${e.message}")
+ }
+ }
+
+ private fun adjustZoom(delta: Float) {
+ maxZoom = maxZoom.coerceAtLeast(1f)
+ zoomLevel = (zoomLevel + delta).coerceIn(1f, maxZoom)
+ updateZoomText()
+ val requestBuilder = previewRequestBuilder ?: return
+ val session = captureSession ?: return
+ applyZoom(requestBuilder)
+ try {
+ session.setRepeatingRequest(requestBuilder.build(), null, backgroundHandler)
+ } catch (e: CameraAccessException) {
+ handleCameraFailure("缩放失败: ${e.message}")
+ } catch (e: IllegalStateException) {
+ handleCameraFailure("相机会话不可用: ${e.message}")
+ }
+ }
+
+ private fun updateZoomText() {
+ binding.zoomText.text = "缩放 ${String.format("%.1f", zoomLevel)}x"
+ }
+
+ private fun applyZoom(builder: CaptureRequest.Builder) {
+ val sensorRect = activeArraySize ?: return
+ if (zoomLevel <= 1f) {
+ builder.set(CaptureRequest.SCALER_CROP_REGION, sensorRect)
+ return
+ }
+ val centerX = sensorRect.centerX()
+ val centerY = sensorRect.centerY()
+ val deltaX = (0.5f * sensorRect.width() / zoomLevel).roundToInt()
+ val deltaY = (0.5f * sensorRect.height() / zoomLevel).roundToInt()
+ val cropRect = Rect(centerX - deltaX, centerY - deltaY, centerX + deltaX, centerY + deltaY)
+ builder.set(CaptureRequest.SCALER_CROP_REGION, cropRect)
+ }
+
+ private fun selectBackCameraId(): String? {
+ val ids = cameraManager.cameraIdList ?: return null
+ return ids.firstOrNull { id ->
+ val facing = cameraManager.getCameraCharacteristics(id)
+ .get(CameraCharacteristics.LENS_FACING)
+ facing == CameraCharacteristics.LENS_FACING_BACK
+ } ?: ids.firstOrNull()
+ }
+
+ private fun choosePreviewSize(map: StreamConfigurationMap?): android.util.Size {
+ val sizes = map?.getOutputSizes(SurfaceTexture::class.java).orEmpty()
+ return sizes.maxByOrNull { it.width * it.height } ?: android.util.Size(1920, 1080)
+ }
+
+ private fun chooseCaptureSize(map: StreamConfigurationMap?): android.util.Size {
+ val sizes = map?.getOutputSizes(ImageFormat.JPEG).orEmpty()
+ return sizes.maxByOrNull { it.width * it.height } ?: android.util.Size(1920, 1080)
+ }
+
+ private fun createOutputFile(): File {
+ val publicPicturesDir =
+ Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
+ if (!publicPicturesDir.exists()) {
+ publicPicturesDir.mkdirs()
+ }
+ return File(publicPicturesDir, "camera_poc_${UUID.randomUUID()}.jpg")
+ }
+ private fun closeCamera() {
+ captureSession?.close()
+ captureSession = null
+ cameraDevice?.close()
+ cameraDevice = null
+ imageReader?.close()
+ imageReader = null
+ isCapturing = false
+ currentOutputPath = null
+ }
+
+ private fun handleCameraFailure(message: String) {
+ closeCamera()
+ runOnUiThread {
+ binding.statusText.text = message
+ message.showMessage()
+ setResult(RESULT_CANCELED)
+ finish()
+ }
+ }
+
+ private fun startBackgroundThread() {
+ if (backgroundThread != null) return
+ backgroundThread = HandlerThread("camera-preview-poc").also { it.start() }
+ backgroundHandler = Handler(backgroundThread!!.looper)
+ }
+
+ private fun stopBackgroundThread() {
+ backgroundThread?.quitSafely()
+ backgroundThread?.join()
+ backgroundThread = null
+ backgroundHandler = null
+ }
+}
diff --git a/app/src/main/java/com/nova/brain/glass/ui/SprayingActivity.kt b/app/src/main/java/com/nova/brain/glass/ui/SprayingActivity.kt
index 781b6c3..9d06660 100644
--- a/app/src/main/java/com/nova/brain/glass/ui/SprayingActivity.kt
+++ b/app/src/main/java/com/nova/brain/glass/ui/SprayingActivity.kt
@@ -1,26 +1,19 @@
package com.nova.brain.glass.ui
import android.content.Intent
-import android.os.Environment
import androidx.recyclerview.widget.RecyclerView
import com.nova.brain.glass.R
import com.nova.brain.glass.databinding.ActivitySprayingBinding
-import com.nova.brain.glass.helper.GlassMediaServiceHelper
import com.nova.brain.glass.helper.OfflineCmdListener
import com.nova.brain.glass.helper.OfflineCmdServiceHelper
import com.nova.brain.glass.helper.SprayingPhotoManager
import com.nova.brain.glass.model.ItemItem
import com.nova.brain.glass.viewmodel.SprayingVM
-import com.rokid.security.glass3.sdk.base.data.media.PhotoResolution
-import com.rokid.security.system.server.media.callback.PhotoFileCallback
import com.xuqm.base.adapter.BasePagedAdapter
import com.xuqm.base.adapter.CommonPagedAdapter
import com.xuqm.base.adapter.ViewHolder
-import com.xuqm.base.common.LogHelper
import com.xuqm.base.extensions.showMessage
import com.xuqm.base.ui.BaseListFormLayoutNormalActivity
-import java.io.File
-import java.util.UUID
class SprayingActivity :
BaseListFormLayoutNormalActivity() {
@@ -35,6 +28,10 @@ class SprayingActivity :
}
private var productionInfoId: String = ""
+ companion object {
+ private const val REQUEST_CAMERA_PREVIEW = 2001
+ }
+
private val listener = object : OfflineCmdListener {
override fun onOfflineCmd(cmd: String) {
runOnUiThread {
@@ -48,7 +45,6 @@ class SprayingActivity :
binding.hint.text = "拍照中,请稍后..."
}
SprayingPhotoManager.clear()
- isPhoto = true
takePhoto()
}
}
@@ -58,50 +54,10 @@ class SprayingActivity :
}
fun takePhoto() {
- val fileName = "test_${System.currentTimeMillis()}.png"
- val publicPicturesDir =
- Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
- val file = File(publicPicturesDir, fileName)
- GlassMediaServiceHelper.takePhoto(PhotoResolution.RESOLUTION_1080P, file.absolutePath)
- }
-
- private val photoCallbackId = UUID.randomUUID().toString()
-
- private val mPhotoFileCallback = object : PhotoFileCallback.Stub() {
- override fun onTakePhoto(path: String) {
- LogHelper.d("onTakePhoto-->path = $path")
- }
-
- override fun getCallbackId(): String {
- return photoCallbackId
- }
-
- override fun onTakePhotoV2(path: String?, width: Int, height: Int) {
- LogHelper.d("width:$width--height:$height")
- if (path == null) {
- if (isPhoto) {
- isPhoto = false
- takePhoto()
- } else {
- runOnUiThread {
- binding.hint.text = "单击或语音输入“开始”,进入下一步"
- }
- "相机异常".showMessage()
- }
- } else {
- SprayingPhotoManager.addPhoto(path)
- startActivity(Intent(this@SprayingActivity, SprayingOCRActivity::class.java).apply {
- putExtra("path", path)
- putExtra("taskId", taskId)
- putExtra("productionInfoId", productionInfoId)
- })
- finish()
-// runOnUiThread {
-// binding.hint.text = "单击或语音输入“开始”,进入下一步"
-// binding.iv.setImageBitmap(BitmapFactory.decodeFile(path))
-// }
- }
- }
+ startActivityForResult(
+ Intent(this, CameraPreviewPocActivity::class.java),
+ REQUEST_CAMERA_PREVIEW
+ )
}
@@ -127,7 +83,6 @@ class SprayingActivity :
override fun onResume() {
super.onResume()
- GlassMediaServiceHelper.addPhotoCallback(mPhotoFileCallback)
OfflineCmdServiceHelper.addOnLineListener(listener)
OfflineCmdServiceHelper.addListenerSpraying()
}
@@ -136,7 +91,28 @@ class SprayingActivity :
super.onPause()
OfflineCmdServiceHelper.removeListenerSpraying()
OfflineCmdServiceHelper.removeOnLineListener(listener)
- GlassMediaServiceHelper.removePhotoCallback(mPhotoFileCallback)
+ }
+
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ super.onActivityResult(requestCode, resultCode, data)
+ if (requestCode != REQUEST_CAMERA_PREVIEW) return
+ if (resultCode != RESULT_OK) {
+ binding.hint.text = "单击或语音输入“开始”,进入下一步"
+ return
+ }
+ val path = data?.getStringExtra(CameraPreviewPocActivity.EXTRA_PHOTO_PATH)
+ if (path.isNullOrBlank()) {
+ binding.hint.text = "单击或语音输入“开始”,进入下一步"
+ "未获取到照片".showMessage()
+ return
+ }
+ SprayingPhotoManager.addPhoto(path)
+ startActivity(Intent(this, SprayingOCRActivity::class.java).apply {
+ putExtra("path", path)
+ putExtra("taskId", taskId)
+ putExtra("productionInfoId", productionInfoId)
+ })
+ finish()
}
override fun onDestroy() {
@@ -144,7 +120,6 @@ class SprayingActivity :
window.clearFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
}
- private var isPhoto = false
private val adapter = object : CommonPagedAdapter(R.layout.item_photo) {
override fun convert(holder: ViewHolder, item: ItemItem, position: Int) {
holder
@@ -155,7 +130,6 @@ class SprayingActivity :
binding.hint.text = "拍照中,请稍后..."
}
SprayingPhotoManager.clear()
- isPhoto = true
takePhoto()
}
}
diff --git a/app/src/main/res/layout/activity_camera_preview_poc.xml b/app/src/main/res/layout/activity_camera_preview_poc.xml
new file mode 100644
index 0000000..108e875
--- /dev/null
+++ b/app/src/main/res/layout/activity_camera_preview_poc.xml
@@ -0,0 +1,104 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+