diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 5651002..aee9c35 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -50,6 +50,8 @@ dependencies {
implementation(libs.androidx.ui.tooling.preview)
implementation(libs.androidx.material3)
implementation(libs.androidx.navigation.compose)
+ implementation(libs.ktor.client.core)
+ implementation(libs.ktor.client.cio)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 38b7a03..5f93a75 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -4,6 +4,7 @@
+
()
Column(
modifier = Modifier
@@ -54,23 +43,23 @@ fun SettingsScreen(appViewModel: AppViewModel = viewModel()) {
)
OutlinedTextField(
modifier = Modifier.fillMaxWidth(),
- value = serverUrl,
- onValueChange = { serverUrl = it },
- label = { Text(stringResource(id = R.string.server_url_label)) }
+ value = viewModel.serverAddress,
+ onValueChange = viewModel::onServerAddressChanged,
+ label = { Text(stringResource(id = R.string.server_address_label)) }
)
OutlinedTextField(
modifier = Modifier.fillMaxWidth(),
- value = deviceName,
- onValueChange = { deviceName = it },
+ value = viewModel.deviceName,
+ onValueChange = viewModel::onDeviceNameChanged,
label = { Text(stringResource(id = R.string.device_name_label)) }
)
OutlinedTextField(
modifier = Modifier.fillMaxWidth(),
- value = registrationCode,
- onValueChange = { registrationCode = it },
+ value = viewModel.registrationCode,
+ onValueChange = viewModel::onRegistrationCodeChanged,
label = { Text(stringResource(id = R.string.registration_code_label)) }
)
- OutlinedButton(onClick = { connect() }, modifier = Modifier.fillMaxWidth()) {
+ OutlinedButton(onClick = { viewModel.connect() }, modifier = Modifier.fillMaxWidth()) {
Text(
stringResource(id = R.string.connect_button_label)
)
@@ -81,9 +70,15 @@ fun SettingsScreen(appViewModel: AppViewModel = viewModel()) {
style = MaterialTheme.typography.headlineSmall
)
if (appViewModel.isBluetoothEnabled()) {
- Text(text = "Controller settings: Bluetooth is enabled.", style = MaterialTheme.typography.bodyMedium)
+ Text(
+ text = "Controller settings: Bluetooth is enabled.",
+ style = MaterialTheme.typography.bodyMedium
+ )
} else {
- Text(text = "Bluetooth is disabled. Please enable it in settings.", style = MaterialTheme.typography.bodyMedium)
+ Text(
+ text = "Bluetooth is disabled. Please enable it in settings.",
+ style = MaterialTheme.typography.bodyMedium
+ )
}
}
}
diff --git a/app/src/main/java/com/example/tvcontroller/SettingsViewModel.kt b/app/src/main/java/com/example/tvcontroller/SettingsViewModel.kt
new file mode 100644
index 0000000..ff29e14
--- /dev/null
+++ b/app/src/main/java/com/example/tvcontroller/SettingsViewModel.kt
@@ -0,0 +1,38 @@
+package com.example.tvcontroller
+
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import com.example.tvcontroller.services.DeviceService
+import kotlinx.coroutines.launch
+
+class SettingsViewModel : ViewModel() {
+ var serverAddress by mutableStateOf(DeviceService.getServerAddress())
+ private set
+ var deviceName by mutableStateOf(android.os.Build.MANUFACTURER + " " + android.os.Build.MODEL)
+ private set
+ var registrationCode by mutableStateOf("")
+ private set
+
+ fun connect() {
+ //Log.i("SettingsScreen", "Save settings: $serverUrl, $deviceName, $registrationCode")
+ viewModelScope.launch {
+ DeviceService.setServerAddress(serverAddress)
+ DeviceService.createIntegration(deviceName, registrationCode)
+ }
+ }
+
+ fun onServerAddressChanged(url: String) {
+ serverAddress = url
+ }
+
+ fun onDeviceNameChanged(name: String) {
+ deviceName = name
+ }
+
+ fun onRegistrationCodeChanged(code: String) {
+ registrationCode = code
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/tvcontroller/BluetoothService.kt b/app/src/main/java/com/example/tvcontroller/services/BluetoothService.kt
similarity index 94%
rename from app/src/main/java/com/example/tvcontroller/BluetoothService.kt
rename to app/src/main/java/com/example/tvcontroller/services/BluetoothService.kt
index 12de817..6fe8601 100644
--- a/app/src/main/java/com/example/tvcontroller/BluetoothService.kt
+++ b/app/src/main/java/com/example/tvcontroller/services/BluetoothService.kt
@@ -1,14 +1,11 @@
-package com.example.tvcontroller
+package com.example.tvcontroller.services
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothManager
import android.content.Context
import android.content.Intent
-import android.app.Activity
import android.content.BroadcastReceiver
import android.content.IntentFilter
-import androidx.activity.result.ActivityResultLauncher
-import androidx.core.app.ComponentActivity
import androidx.core.content.ContextCompat.getSystemService
class BluetoothService(private val context: Context) {
diff --git a/app/src/main/java/com/example/tvcontroller/services/DeviceService.kt b/app/src/main/java/com/example/tvcontroller/services/DeviceService.kt
new file mode 100644
index 0000000..5ad2bb7
--- /dev/null
+++ b/app/src/main/java/com/example/tvcontroller/services/DeviceService.kt
@@ -0,0 +1,46 @@
+package com.example.tvcontroller.services
+
+import android.util.Log
+import io.ktor.client.engine.cio.*
+import io.ktor.client.*
+import io.ktor.client.call.body
+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.HttpMethod
+import org.json.JSONObject
+
+object DeviceService {
+ private var client = HttpClient(CIO)
+ private var serverAddress: String = ""
+
+ suspend fun createIntegration(name: String, code: String) {
+ Log.i("DeviceService", "Creating integration for $name with code $code at $serverAddress")
+ val json = JSONObject()
+ json.put("name", name)
+ json.put("code", code)
+ try {
+ val response: HttpResponse = client.request("http://$serverAddress/api/integrations") {
+ method = HttpMethod.Post
+ setBody(json.toString())
+ headers {
+ append("Content-Type", "application/json")
+ }
+ }
+
+ val body: String = response.body()
+ Log.i("DeviceService", "Response: ${response.status.value} $body")
+ } catch (e: Exception) {
+ Log.e("DeviceService", "Error creating integration", e)
+ }
+ }
+
+ fun setServerAddress(url: String) {
+ serverAddress = url
+ }
+
+ fun getServerAddress(): String {
+ return serverAddress
+ }
+}
diff --git a/app/src/main/java/com/example/tvcontroller/ui/AppUiState.kt b/app/src/main/java/com/example/tvcontroller/ui/AppUiState.kt
index 722d8f5..449ae6d 100644
--- a/app/src/main/java/com/example/tvcontroller/ui/AppUiState.kt
+++ b/app/src/main/java/com/example/tvcontroller/ui/AppUiState.kt
@@ -3,5 +3,5 @@ package com.example.tvcontroller.ui
import com.example.tvcontroller.Screen
data class AppUiState(
- val currentScreen: Screen = Screen.Camera,
+ val currentScreen: Screen = Screen.Settings,
)
\ No newline at end of file
diff --git a/app/src/main/java/com/example/tvcontroller/ui/AppViewModel.kt b/app/src/main/java/com/example/tvcontroller/ui/AppViewModel.kt
index 03551ba..35d0abd 100644
--- a/app/src/main/java/com/example/tvcontroller/ui/AppViewModel.kt
+++ b/app/src/main/java/com/example/tvcontroller/ui/AppViewModel.kt
@@ -1,16 +1,7 @@
package com.example.tvcontroller.ui
-import android.content.Context
-import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
-import com.example.tvcontroller.BluetoothService
-import com.example.tvcontroller.Screen
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.asStateFlow
-import kotlinx.coroutines.flow.update
class AppViewModel() : ViewModel() {
private var isBluetoothEnabled = mutableStateOf(false)
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 8b085a8..942f1aa 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -10,4 +10,5 @@
disconnected
Save
Connect
+ Server address
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
index 20e2a01..132244e 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -20,4 +20,4 @@ kotlin.code.style=official
# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
-android.nonTransitiveRClass=true
\ No newline at end of file
+android.nonTransitiveRClass=true
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 3fe6ea9..c7146a4 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -5,6 +5,7 @@ coreKtx = "1.10.1"
junit = "4.13.2"
junitVersion = "1.1.5"
espressoCore = "3.5.1"
+ktor = "3.1.0"
lifecycleRuntimeKtx = "2.6.1"
activityCompose = "1.8.0"
composeBom = "2024.04.01"
@@ -26,6 +27,8 @@ 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" }
+ktor-client-cio = { module = "io.ktor:ktor-client-cio", version.ref = "ktor" }
+ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }