diff --git a/app/build.gradle b/app/build.gradle index 244b59d..717a96e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -63,13 +63,13 @@ dependencies { implementation project(':utils') // Kotlin lang - implementation 'androidx.core:core-ktx:1.2.0' + implementation 'androidx.core:core-ktx:1.10.1' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.4' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3' // App compat and UI things implementation 'androidx.appcompat:appcompat:1.1.0' - implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.2.0' + implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.2' implementation "androidx.viewpager2:viewpager2:1.0.0" implementation 'androidx.constraintlayout:constraintlayout:1.1.3' @@ -87,4 +87,9 @@ dependencies { implementation "io.ktor:ktor-server-core:2.3.3" implementation "io.ktor:ktor-server-netty:2.3.3" + + testImplementation 'junit:junit:4.13.2' + testImplementation 'org.mockito:mockito-core:3.12.4' + testImplementation 'org.mockito:mockito-inline:3.12.4' + testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.4" } diff --git a/app/src/main/java/com/samsung/android/scan3d/serv/Cam.kt b/app/src/main/java/com/samsung/android/scan3d/serv/Cam.kt index d2357f0..5e7c75e 100644 --- a/app/src/main/java/com/samsung/android/scan3d/serv/Cam.kt +++ b/app/src/main/java/com/samsung/android/scan3d/serv/Cam.kt @@ -17,7 +17,14 @@ import com.samsung.android.scan3d.CameraActivity import com.samsung.android.scan3d.R import com.samsung.android.scan3d.fragments.CameraFragment import com.samsung.android.scan3d.http.HttpService -import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.cancel +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock class Cam : Service() { @@ -25,6 +32,9 @@ class Cam : Service() { var http: HttpService? = null val CHANNEL_ID = "REMOTE_CAM" + private val serviceScope = CoroutineScope(Dispatchers.Main + SupervisorJob()) + private val cameraMutex = Mutex() + override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { Log.i("CAM", "onStartCommand " + intent?.action) @@ -81,11 +91,14 @@ class Cam : Service() { } "onPause" -> { - engine?.insidePause = true - if (engine?.isShowingPreview == true) { - engine?.restart() + serviceScope.launch { + cameraMutex.withLock { + engine?.insidePause = true + if (engine?.isShowingPreview == true) { + engine?.restart() + } + } } - } "onResume" -> { @@ -93,30 +106,49 @@ class Cam : Service() { } "start_camera_engine" -> { - engine = CamEngine(this) - engine?.http = http - runBlocking { engine?.initializeCamera() } + serviceScope.launch { + cameraMutex.withLock { + val newEngine = withContext(Dispatchers.IO) { + CamEngine(this@Cam) + } + newEngine.http = http + engine = newEngine + newEngine.initializeCamera() + } + } } "new_view_state" -> { - - val old = engine?.viewState!! val new : CameraFragment.Companion.ViewState = intent.extras?.getParcelable("data")!! Log.i("CAM", "new_view_state: " + new) - Log.i("CAM", "from: " + old) - engine?.viewState = new - if (old != new) { - Log.i("CAM", "diff") - engine?.restart() + + serviceScope.launch { + cameraMutex.withLock { + val old = engine?.viewState + if (old == null) { + // Engine not ready or null + return@withLock + } + Log.i("CAM", "from: " + old) + engine?.viewState = new + if (old != new) { + Log.i("CAM", "diff") + engine?.restart() + } + } } } "new_preview_surface" -> { val surface: Surface? = intent.extras?.getParcelable("surface") - // Toast.makeText(this, "SURFACE", Toast.LENGTH_SHORT).show() - engine?.previewSurface = surface - if (engine?.viewState?.preview == true) { - runBlocking { engine?.initializeCamera() } + serviceScope.launch { + cameraMutex.withLock { + // Toast.makeText(this, "SURFACE", Toast.LENGTH_SHORT).show() + engine?.previewSurface = surface + if (engine?.viewState?.preview == true) { + engine?.initializeCamera() + } + } } } @@ -141,6 +173,7 @@ class Cam : Service() { override fun onDestroy() { super.onDestroy() Log.i("CAM", "OnDestroy") + serviceScope.cancel() kill() } diff --git a/app/src/main/java/com/samsung/android/scan3d/serv/CamEngine.kt b/app/src/main/java/com/samsung/android/scan3d/serv/CamEngine.kt index 3d1a51e..949f4cb 100644 --- a/app/src/main/java/com/samsung/android/scan3d/serv/CamEngine.kt +++ b/app/src/main/java/com/samsung/android/scan3d/serv/CamEngine.kt @@ -24,8 +24,9 @@ import android.view.Surface import com.samsung.android.scan3d.fragments.CameraFragment import com.samsung.android.scan3d.http.HttpService import com.samsung.android.scan3d.util.Selector -import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.suspendCancellableCoroutine +import kotlinx.coroutines.withContext import kotlinx.parcelize.Parcelize import kotlin.coroutines.resume import kotlin.coroutines.resumeWithException @@ -125,9 +126,9 @@ class CamEngine(val context: Context) { } } - fun restart() { + suspend fun restart() { stopRunning() - runBlocking { initializeCamera() } + initializeCamera() } @@ -185,7 +186,7 @@ class CamEngine(val context: Context) { }, handler) } - suspend fun initializeCamera() { + suspend fun initializeCamera() = withContext(Dispatchers.IO) { Log.i("CAMERA", "initializeCamera") Log.i("CAMERA", "RTSP: ${viewState.rtsp}, Encoding: ${viewState.encoding}") diff --git a/build.gradle b/build.gradle index 4c878eb..f9a29cf 100644 --- a/build.gradle +++ b/build.gradle @@ -18,15 +18,15 @@ buildscript { // Top-level variables used for versioning - ext.kotlin_version = '1.6.21' - ext.java_version = JavaVersion.VERSION_1_8 + ext.kotlin_version = '1.9.22' + ext.java_version = JavaVersion.VERSION_17 repositories { google() mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.1.0' + classpath 'com.android.tools.build:gradle:8.3.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath 'androidx.navigation:navigation-safe-args-gradle-plugin:2.7.0' diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index da1db5f..a595206 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists