Compare commits

..

2 Commits

Author SHA1 Message Date
2f90fd7b09 feat: use camerax with webrtc lib 2025-04-01 19:15:03 +02:00
7471168a21 feat: connect to server on app launch 2025-04-01 19:11:03 +02:00
2 changed files with 38 additions and 24 deletions

View File

@ -5,7 +5,6 @@ import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.camera.core.ImageAnalysis
import androidx.camera.view.CameraController
import androidx.camera.view.LifecycleCameraController
import androidx.compose.foundation.layout.fillMaxSize
@ -16,29 +15,26 @@ import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import com.example.tvcontroller.ui.theme.TVControllerTheme
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import com.example.tvcontroller.services.BluetoothService
import com.example.tvcontroller.services.CameraService
import com.example.tvcontroller.services.ControllerService
import com.example.tvcontroller.services.DeviceService
import com.example.tvcontroller.ui.theme.TVControllerTheme
import com.example.tvcontroller.ui.views.CameraView
import com.example.tvcontroller.ui.views.RemoteView
import com.example.tvcontroller.ui.views.SettingsView
import com.example.tvcontroller.webrtc.CameraXCapturer
import com.example.tvcontroller.webrtc.RtcPeerConnection
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@ -71,6 +67,10 @@ class MainActivity : ComponentActivity() {
cameraService = CameraService(applicationContext)
controllerService = ControllerService(applicationContext, bluetoothService)
checkPermissions()
lifecycleScope.launch(Dispatchers.IO) {
deviceService.initialize()
}
enableEdgeToEdge()
setContent {
TVControllerTheme {
@ -164,8 +164,7 @@ fun TvControllerApp(
composable(route = Screen.Settings.name) {
SettingsView(
deviceService = deviceService,
bluetoothService = bluetoothService,
rtcPeerConnection = rtcPeerConnection
bluetoothService = bluetoothService
)
}
}

View File

@ -10,10 +10,13 @@ import io.ktor.client.call.body
import io.ktor.client.plugins.cookies.HttpCookies
import io.ktor.client.plugins.websocket.WebSockets
import io.ktor.client.plugins.websocket.webSocket
import io.ktor.client.request.HttpRequestBuilder
import io.ktor.client.request.cookie
import io.ktor.client.request.headers
import io.ktor.client.request.request
import io.ktor.client.request.setBody
import io.ktor.client.statement.HttpResponse
import io.ktor.http.Cookie
import io.ktor.http.HttpMethod
import io.ktor.websocket.Frame
import io.ktor.websocket.readText
@ -25,15 +28,18 @@ private const val TAG = "DeviceService"
class DeviceService(private val context: Context) {
private var client = HttpClient(CIO) {
install(HttpCookies)
install(WebSockets)
}
private var serverAddress: String = ""
private var token: String = ""
private var deviceId: String = ""
init {
suspend fun initialize() {
loadPreferences()
if (token.isEmpty()) return
getIntegration()?.let {
connect()
}
}
suspend fun registerIntegration(name: String, code: String) {
@ -44,13 +50,15 @@ class DeviceService(private val context: Context) {
token = ""
deviceId = ""
try {
val response: HttpResponse = client.request("http://$serverAddress/api/integrations/register") {
method = HttpMethod.Post
setBody(requestJson.toString())
headers {
append("Content-Type", "application/json")
val response: HttpResponse =
client.request("http://$serverAddress/api/integrations/register") {
method = HttpMethod.Post
setBody(requestJson.toString())
headers {
append("Content-Type", "application/json")
}
cookie(name = "token", value = token)
}
}
val body: String = response.body()
val responseJson = JSONObject(body)
@ -78,6 +86,7 @@ class DeviceService(private val context: Context) {
headers {
append("Authorization", "Bearer $token")
}
cookie(name = "token", value = token)
}
val body: String = response.body()
@ -120,11 +129,17 @@ class DeviceService(private val context: Context) {
fun connect() {
Log.i(TAG, "Connecting to websocket at $serverAddress")
runBlocking {
// split server address into host and port
val (host, port) = serverAddress.split(":")
// if no port is specified, assume 80
val portInt = if (port.isEmpty()) 80 else port.toInt()
client.webSocket(method = HttpMethod.Get, host = host, port = portInt, path = "/ws") {
client.webSocket(
method = HttpMethod.Get,
host = host,
port = portInt,
path = "/ws",
request = {
cookie(name = "token", value = token)
}
) {
Log.i(TAG, "Listening for incoming websocket messages")
while (true) {
val frame = incoming.receive()