diff --git a/app/src/main/java/com/example/hueharvester/MainActivity.kt b/app/src/main/java/com/example/hueharvester/MainActivity.kt index 454f73a..4e8510e 100644 --- a/app/src/main/java/com/example/hueharvester/MainActivity.kt +++ b/app/src/main/java/com/example/hueharvester/MainActivity.kt @@ -38,6 +38,8 @@ class MainActivity : AppCompatActivity() { private lateinit var cameraPreview: SurfaceView private var camera: Camera? = null + private var isCameraReleased = true + private var isSurfaceCreated = false private var savedPreviewSize: IntArray? = null private var savedPreviewFpsRange: IntArray? = null @@ -52,7 +54,7 @@ class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - //Log.d(MAIN, "onCreate") + Log.d(MAIN, "onCreate") setContentView(R.layout.activity_main) @@ -110,22 +112,22 @@ class MainActivity : AppCompatActivity() { if (!isIdSaved) { // Set the data collection starting point savedInstanceState?.let { - //Log.d(DBR, "Creation data ID from BUNDLE: ${it.getInt("creationDataID")}") - //Log.d(DBR, "Last data ID from BUNDLE: ${it.getInt("lastDataID")}") + Log.d(DBR, "Creation data ID from BUNDLE: ${it.getInt("creationDataID")}") + Log.d(DBR, "Last data ID from BUNDLE: ${it.getInt("lastDataID")}") } ?: try { run { dataList.last().let { creationDataID = it.id lastDataID = it.id - //Log.d(DBR, "Creation data ID from ROOM: $creationDataID") - //Log.d(DBR, "Last data ID from ROOM: $lastDataID") + Log.d(DBR, "Creation data ID from ROOM: $creationDataID") + Log.d(DBR, "Last data ID from ROOM: $lastDataID") } } } catch (e: NoSuchElementException) { - Log.e(DBR, "No data in the database", e) - //Log.i(DBR, "No data in the database") - //Log.d(DBR, "Creation data ID: $creationDataID") - //Log.d(DBR, "Last data ID: $lastDataID") + //Log.e(DBR, "No data in the database", e) + Log.i(DBR, "No data in the database") + Log.d(DBR, "Creation data ID: $creationDataID") + Log.d(DBR, "Last data ID: $lastDataID") } isIdSaved = true } @@ -147,7 +149,7 @@ class MainActivity : AppCompatActivity() { if (this.id - dataList.first().id > MAX_TIME ) { // doesn't clean up if there are less than MAX_TIME data // Clean up old data viewModel.deleteOldData(this.id - MAX_TIME) - //Log.d(DBR, "Last ID = ${lastColor.id} : deleted too old data => id < ${lastColor.id - MAX_TIME}") + Log.d(DBR, "Last ID = ${this.id} : deleted too old data => id < ${this.id - MAX_TIME}") } } } @@ -160,42 +162,42 @@ class MainActivity : AppCompatActivity() { * @see Camera */ private fun setupCameraPreview() { - //Log.v(MAIN, "Setting up camera preview") + Log.v(MAIN, "Setting up camera preview") val holder: SurfaceHolder = cameraPreview.holder holder.addCallback(object : SurfaceHolder.Callback { override fun surfaceCreated(holder: SurfaceHolder) { - //Log.i(MAIN, "Surface created") + Log.i(MAIN, "Surface created") if (!checkCameraPermission()) { requestCameraPermission() } else { - //Log.v(MAIN, "surfaceCreated calls initializeCameraAsync") - initializeCameraAsync(holder) + Log.v(MAIN, "surfaceCreated calls initializeCameraAsync") + initializeCamera(holder) isSurfaceCreated = true } } override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) { if (isSurfaceCreated) { // possible calling of surfaceChanged before surfaceCreated - //Log.i(MAIN, "Surface changed from [${savedPreviewSize?.get(0)} x ${savedPreviewSize?.get(1)}] to [$width x $height]") + Log.i(MAIN, "Surface changed from [${savedPreviewSize?.get(0)} x ${savedPreviewSize?.get(1)}] to [$width x $height]") if (camera != null && (width != savedPreviewSize?.get(0) || height != savedPreviewSize?.get( 1 )) ) { - //Log.v(MAIN, "surfaceChanged calls initializeCameraAsync") + Log.v(MAIN, "surfaceChanged calls initializeCameraAsync") camera?.stopPreview() - initializeCameraAsync(holder) + initializeCamera(holder) } } } override fun surfaceDestroyed(holder: SurfaceHolder) { - //Log.d(MAIN, "Surface destroyed") + Log.d(MAIN, "Surface destroyed") releaseCamera() isSurfaceCreated = false } }) } - /** Initialize the camera asynchronously + /** Initialize the camera * It sets the camera preview size and the preview frame rate * @param holder the [SurfaceHolder] to set the camera preview * @@ -203,69 +205,73 @@ class MainActivity : AppCompatActivity() { * @see Camera.Parameters * @see SurfaceHolder */ - private fun initializeCameraAsync(holder: SurfaceHolder) { - Thread { - try { - if (camera == null) { - camera = Camera.open() - //Log.i(MAIN, "Camera opened") - } + private fun initializeCamera(holder: SurfaceHolder) { + try { + if (isCameraReleased) { + camera = Camera.open() + isCameraReleased = false + Log.i(MAIN, "Camera opened") + } - adjustCameraOrientation() + adjustCameraOrientation() - val params = camera?.parameters + val params = camera?.parameters - savedPreviewSize?.let { - //Log.v(MAIN, "Restoring preview size: ${it[0]} x ${it[1]}") - params?.setPreviewSize(it[0], it[1]) - } ?: run { - val supportedPreviewSizes = params?.supportedPreviewSizes - val minPreviewSize = supportedPreviewSizes?.minByOrNull { it.width * it.height } - minPreviewSize?.let { - savedPreviewSize = intArrayOf(it.width, it.height) - params.setPreviewSize(it.width, it.height) - } - //Log.i(MAIN, "Preview size set to: ${savedPreviewSize?.get(0)} x ${savedPreviewSize?.get(1)}") + savedPreviewSize?.let { + Log.v(MAIN, "Restoring preview size: ${it[0]} x ${it[1]}") + params?.setPreviewSize(it[0], it[1]) + } ?: run { + val supportedPreviewSizes = params?.supportedPreviewSizes + val minPreviewSize = supportedPreviewSizes?.minByOrNull { it.width * it.height } + minPreviewSize?.let { + savedPreviewSize = intArrayOf(it.width, it.height) + params.setPreviewSize(it.width, it.height) } - savedPreviewFpsRange?.let { - params?.setPreviewFpsRange(it[0], it[1]) - } ?: run { - val supportedPreviewFpsRanges = params?.supportedPreviewFpsRange - val minPreviewFpsRange = - supportedPreviewFpsRanges?.minByOrNull { it[Camera.Parameters.PREVIEW_FPS_MIN_INDEX] } - minPreviewFpsRange?.let { - params.setPreviewFpsRange( - it[Camera.Parameters.PREVIEW_FPS_MIN_INDEX], - it[Camera.Parameters.PREVIEW_FPS_MAX_INDEX] - ) - savedPreviewFpsRange = it - } + Log.i( + MAIN, + "Preview size set to: ${savedPreviewSize?.get(0)} x ${ + savedPreviewSize?.get(1) + }" + ) + } + savedPreviewFpsRange?.let { + params?.setPreviewFpsRange(it[0], it[1]) + } ?: run { + val supportedPreviewFpsRanges = params?.supportedPreviewFpsRange + val minPreviewFpsRange = + supportedPreviewFpsRanges?.minByOrNull { it[Camera.Parameters.PREVIEW_FPS_MIN_INDEX] } + minPreviewFpsRange?.let { + params.setPreviewFpsRange( + it[Camera.Parameters.PREVIEW_FPS_MIN_INDEX], + it[Camera.Parameters.PREVIEW_FPS_MAX_INDEX] + ) + savedPreviewFpsRange = it } + } - camera?.apply { - parameters = params - - setPreviewCallback { data, cam -> - val previewSize = cam.parameters.previewSize - val (avgRed, avgGreen, avgBlue) = calculateAverageColor( - data, - previewSize.width, - previewSize.height - ) + camera?.apply { + parameters = params - manageNewData(avgRed, avgGreen, avgBlue) - } + setPreviewCallback { data, cam -> + val previewSize = cam.parameters.previewSize + val (avgRed, avgGreen, avgBlue) = calculateAverageColor( + data, + previewSize.width, + previewSize.height + ) - setPreviewDisplay(holder) - startPreview() - //Log.v(MAIN, "Camera preview started") + manageNewData(avgRed, avgGreen, avgBlue) } - Log.d(MAIN, "Camera setup successful") - } catch (e: Exception) { - releaseCamera() - Log.e(MAIN, "Camera setup failed", e) + + setPreviewDisplay(holder) + startPreview() + Log.v(MAIN, "Camera preview started") } - }.start() + Log.d(MAIN, "Camera setup successful") + } catch (e: Exception) { + releaseCamera() + Log.e(MAIN, "Camera setup failed", e) + } } /** Manage the new data collected from the camera @@ -315,13 +321,16 @@ class MainActivity : AppCompatActivity() { * @see Camera */ private fun releaseCamera() { - //Log.v(MAIN, "Releasing camera") - camera?.apply { - setPreviewCallback(null) - stopPreview() - release() - camera = null - Log.d(MAIN, "Camera released") + if (!isCameraReleased) { + Log.v(MAIN, "Releasing camera") + camera?.apply { + stopPreview() + setPreviewCallback(null) + release() + camera = null + isCameraReleased = true + Log.d(MAIN, "Camera released") + } } } @@ -350,9 +359,9 @@ class MainActivity : AppCompatActivity() { if (requestCode == CAMERA_REQUEST_CODE) { if (grantResults.isNotEmpty() && (grantResults[0] == PackageManager.PERMISSION_GRANTED)) { Toast.makeText(this, getString(R.string.camera_permission_granted), Toast.LENGTH_SHORT).show() - //Log.i(MAIN, "Camera permission granted") - //Log.v(MAIN, "requestCameraPermission calls initializeCameraAsync") - initializeCameraAsync(cameraPreview.holder) + Log.i(MAIN, "Camera permission granted") + Log.v(MAIN, "requestCameraPermission calls initializeCameraAsync") + initializeCamera(cameraPreview.holder) } else { Toast.makeText(this, getString(R.string.camera_permission_required), Toast.LENGTH_SHORT).show() } @@ -413,20 +422,20 @@ class MainActivity : AppCompatActivity() { return Triple(avgRed, avgGreen, avgBlue) } catch (e: NullPointerException) { Log.e(MAIN, "Error calculating average color") - //Log.i(MAIN, "Returning default values due to Error") + Log.i(MAIN, "Returning default values due to Error") return Triple(0, 0, 0) } } override fun onPause() { - //Log.d(MAIN, "onPause") + Log.d(MAIN, "onPause") super.onPause() releaseCamera() } override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) - //Log.d(MAIN, "onSaveInstanceState") + Log.d(MAIN, "onSaveInstanceState") outState.putInt("creationDataID", creationDataID) outState.putInt("lastDataID", lastDataID) @@ -449,7 +458,7 @@ class MainActivity : AppCompatActivity() { override fun onRestoreInstanceState(savedInstanceState: Bundle) { super.onRestoreInstanceState(savedInstanceState) - //Log.d(MAIN, "onRestoreInstanceState") + Log.d(MAIN, "onRestoreInstanceState") creationDataID = savedInstanceState.getInt("creationDataID") lastDataID = savedInstanceState.getInt("lastDataID")