Http Server / Client communication #7
22 changed files with 233 additions and 197 deletions
|
@ -4,34 +4,36 @@
|
|||
<value>
|
||||
<entry key="app">
|
||||
<State>
|
||||
<targetSelectedWithDropDown>
|
||||
<runningDeviceTargetSelectedWithDropDown>
|
||||
<Target>
|
||||
<type value="QUICK_BOOT_TARGET" />
|
||||
<type value="RUNNING_DEVICE_TARGET" />
|
||||
<deviceKey>
|
||||
<Key>
|
||||
<type value="VIRTUAL_DEVICE_PATH" />
|
||||
<value value="C:\Users\RC606\.android\avd\Small_Phone_API_26.avd" />
|
||||
<type value="SERIAL_NUMBER" />
|
||||
<value value="2XJDU17923000406" />
|
||||
</Key>
|
||||
</deviceKey>
|
||||
</Target>
|
||||
</targetSelectedWithDropDown>
|
||||
<timeTargetWasSelectedWithDropDown value="2024-05-04T10:43:32.941497Z" />
|
||||
</runningDeviceTargetSelectedWithDropDown>
|
||||
<timeTargetWasSelectedWithDropDown value="2024-05-05T12:21:32.176293Z" />
|
||||
<runningDeviceTargetsSelectedWithDialog>
|
||||
<Target>
|
||||
<type value="RUNNING_DEVICE_TARGET" />
|
||||
<deviceKey>
|
||||
<Key>
|
||||
<type value="VIRTUAL_DEVICE_PATH" />
|
||||
<value value="C:\Users\RC606\.android\avd\Small_Phone_API_34.avd" />
|
||||
</Key>
|
||||
</deviceKey>
|
||||
</Target>
|
||||
</runningDeviceTargetsSelectedWithDialog>
|
||||
<targetsSelectedWithDialog>
|
||||
<Target>
|
||||
<type value="QUICK_BOOT_TARGET" />
|
||||
<deviceKey>
|
||||
<Key>
|
||||
<type value="VIRTUAL_DEVICE_PATH" />
|
||||
<value value="C:\Users\RC606\.android\avd\Small_Phone_API_26.avd" />
|
||||
</Key>
|
||||
</deviceKey>
|
||||
</Target>
|
||||
<Target>
|
||||
<type value="QUICK_BOOT_TARGET" />
|
||||
<deviceKey>
|
||||
<Key>
|
||||
<type value="VIRTUAL_DEVICE_PATH" />
|
||||
<value value="C:\Users\RC606\.android\avd\Small_Phone_API_26_-_2.avd" />
|
||||
<value value="C:\Users\RC606\.android\avd\Small_Phone_API_34_-_2.avd" />
|
||||
</Key>
|
||||
</deviceKey>
|
||||
</Target>
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="FrameworkDetectionExcludesConfiguration">
|
||||
|
|
|
@ -63,6 +63,9 @@ dependencies {
|
|||
implementation("androidx.room:room-ktx:2.6.1")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3")
|
||||
implementation("androidx.navigation:navigation-compose:2.7.7")
|
||||
implementation("org.nanohttpd:nanohttpd:2.3.1")
|
||||
implementation("com.google.code.gson:gson:2.10.1")
|
||||
implementation("com.squareup.okhttp3:okhttp-android:5.0.0-alpha.14")
|
||||
testImplementation("junit:junit:4.13.2")
|
||||
androidTestImplementation("androidx.test.ext:junit:1.1.5")
|
||||
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
|
||||
|
|
|
@ -7,7 +7,7 @@ import androidx.activity.ComponentActivity
|
|||
import androidx.activity.compose.setContent
|
||||
import androidx.annotation.RequiresApi
|
||||
import com.faraphel.tasks_valider.connectivity.bwf.BwfManager
|
||||
import com.faraphel.tasks_valider.database.Database
|
||||
import com.faraphel.tasks_valider.database.TaskDatabase
|
||||
import com.faraphel.tasks_valider.ui.screen.communication.CommunicationScreen
|
||||
|
||||
|
||||
|
@ -15,7 +15,7 @@ class MainActivity : ComponentActivity() {
|
|||
private var bwfManager: BwfManager? = null ///< the WiFi-Direct helper
|
||||
|
||||
companion object {
|
||||
private lateinit var database: Database ///< the database manager
|
||||
private lateinit var database: TaskDatabase ///< the database manager
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
package com.faraphel.tasks_valider.connectivity.packets
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
|
||||
|
||||
/**
|
||||
* Base for a packet that can be encoded and decoded for a Socket
|
||||
*/
|
||||
@Serializable
|
||||
sealed class BasePacket {
|
||||
companion object {
|
||||
/**
|
||||
* Create a new instance from an array of bytes.
|
||||
* @param data: data obtained from the toBytes function.
|
||||
*/
|
||||
inline fun <reified Packet: BasePacket> fromBytes(data: ByteArray): Packet {
|
||||
return Json.decodeFromString<Packet>(data.toString())
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode the content of the packet into an array of bytes
|
||||
*/
|
||||
fun toBytes(): ByteArray {
|
||||
return Json.encodeToString(this).encodeToByteArray()
|
||||
}
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
package com.faraphel.tasks_valider.connectivity.packets
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
|
||||
/**
|
||||
* This is a simple packet class to test a connection
|
||||
*/
|
||||
@Serializable
|
||||
data object PacketPing : BasePacket()
|
|
@ -1,43 +0,0 @@
|
|||
package com.faraphel.tasks_valider.connectivity.room
|
||||
|
||||
import android.util.Log
|
||||
import com.faraphel.tasks_valider.connectivity.packets.BasePacket
|
||||
import com.faraphel.tasks_valider.connectivity.packets.PacketPing
|
||||
import java.net.InetAddress
|
||||
import java.net.InetSocketAddress
|
||||
import java.net.Socket
|
||||
|
||||
|
||||
/**
|
||||
* A client to handle the room connection.
|
||||
* @param address the address of the server
|
||||
* @param port the port of the server
|
||||
*/
|
||||
class RoomClient(
|
||||
private val address: InetAddress,
|
||||
private val port: Int
|
||||
) : Thread() {
|
||||
private val server = Socket()
|
||||
|
||||
constructor(address: String, port: Int) : this(InetAddress.getByName(address), port)
|
||||
|
||||
override fun run() {
|
||||
Log.d("room-client", "connecting to the server...")
|
||||
try {
|
||||
server.connect(InetSocketAddress(address, port), 10_000)
|
||||
} catch (exception: Exception) {
|
||||
Log.e("room-client", "could not connect to the server", exception)
|
||||
return
|
||||
}
|
||||
Log.d("room-client", "connection successful !")
|
||||
|
||||
val serverIn = server.getInputStream()
|
||||
val serverOut = server.getOutputStream()
|
||||
|
||||
serverOut.write(PacketPing.toBytes())
|
||||
val data = serverIn.readBytes()
|
||||
val packet = BasePacket.fromBytes<PacketPing>(data)
|
||||
|
||||
Log.d("room-client", packet.toString())
|
||||
}
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
package com.faraphel.tasks_valider.connectivity.room
|
||||
|
||||
import android.util.Log
|
||||
import com.faraphel.tasks_valider.connectivity.packets.PacketPing
|
||||
import java.net.ServerSocket
|
||||
import java.net.Socket
|
||||
|
||||
|
||||
/**
|
||||
* A server to handle the room connection.
|
||||
* @param port the port of the server
|
||||
* @param timeout the timeout for a client (in milliseconds)
|
||||
*/
|
||||
class RoomServer(
|
||||
private val port: Int,
|
||||
private val timeout: Int = 10_000
|
||||
) : Thread() {
|
||||
private var server = ServerSocket(port)
|
||||
|
||||
init {
|
||||
server.soTimeout = 0 // accepting clients take an infinite timeout
|
||||
}
|
||||
|
||||
/**
|
||||
* Accept and treat a client
|
||||
*/
|
||||
private fun handleClient(client: Socket) {
|
||||
// TODO(Faraphel): should every client be handled in a new small thread ?
|
||||
// Create the thread here and handle it until the connection is broken
|
||||
|
||||
val clientIn = client.getInputStream()
|
||||
val clientOut = client.getOutputStream()
|
||||
|
||||
Log.i("room-server", "data: ${PacketPing.toBytes().toList()}")
|
||||
clientOut.write(PacketPing.toBytes())
|
||||
}
|
||||
|
||||
/**
|
||||
* Accept connections and treat them
|
||||
*/
|
||||
override fun run() {
|
||||
while (!server.isClosed) {
|
||||
val client = server.accept()
|
||||
client.soTimeout = timeout // set the timeout for the communication
|
||||
this.handleClient(client)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the server
|
||||
*/
|
||||
fun close() {
|
||||
server.close()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package com.faraphel.tasks_valider.connectivity.task
|
||||
|
||||
import android.util.Log
|
||||
import com.google.gson.Gson
|
||||
import okhttp3.OkHttpClient
|
||||
import java.net.InetAddress
|
||||
import java.net.URL
|
||||
|
||||
|
||||
/**
|
||||
* A client to handle the room connection.
|
||||
* @param address the address of the server
|
||||
* @param port the port of the server
|
||||
*/
|
||||
class TaskClient(
|
||||
private val address: InetAddress,
|
||||
private val port: Int
|
||||
) : Thread() {
|
||||
private val client = OkHttpClient()
|
||||
private val jsonParser = Gson()
|
||||
|
||||
constructor(address: String, port: Int) : this(InetAddress.getByName(address), port)
|
||||
|
||||
override fun run() {
|
||||
Log.i("room-client", "started !")
|
||||
|
||||
// send a request to the server
|
||||
val request = okhttp3.Request.Builder()
|
||||
.url(URL("http://${address.hostAddress}:$port"))
|
||||
.build()
|
||||
|
||||
// get the response
|
||||
val response = client.newCall(request).execute()
|
||||
|
||||
// check if the response is successful
|
||||
if (!response.isSuccessful) {
|
||||
Log.e("room-client", "could not connect to the server")
|
||||
return
|
||||
}
|
||||
Log.i("room-client", "connected to the server")
|
||||
|
||||
// parse the response
|
||||
val body = response.body.string()
|
||||
val data = jsonParser.fromJson(body, Map::class.java)
|
||||
|
||||
// print the data
|
||||
data.forEach { (key, value) -> Log.d("room-client", "$key: $value") }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
package com.faraphel.tasks_valider.connectivity.task
|
||||
|
||||
import android.util.Log
|
||||
import com.faraphel.tasks_valider.database.TaskDatabase
|
||||
import com.faraphel.tasks_valider.database.entities.Task
|
||||
import com.google.gson.Gson
|
||||
import fi.iki.elonen.NanoHTTPD
|
||||
|
||||
|
||||
/**
|
||||
* A server to handle the task API to allow clients to interact with the database.
|
||||
* @param port the port of the server
|
||||
* @param database the database to interact with
|
||||
*/
|
||||
class TaskServer(
|
||||
private val port: Int,
|
||||
private val database: TaskDatabase
|
||||
) : NanoHTTPD(port) {
|
||||
private val jsonParser = Gson()
|
||||
|
||||
override fun serve(session: IHTTPSession): Response {
|
||||
val method: Method = session.method
|
||||
val uri: String = session.uri
|
||||
|
||||
// remove the first slash
|
||||
val daoName: String = uri.substring(1)
|
||||
|
||||
// handle the request
|
||||
when (method) {
|
||||
// get the data from the database
|
||||
Method.GET -> {
|
||||
return newFixedLengthResponse(
|
||||
Response.Status.OK,
|
||||
"application/json",
|
||||
jsonParser.toJson( database.taskDao().getAll() )
|
||||
)
|
||||
}
|
||||
// insert the data into the database
|
||||
Method.POST -> {
|
||||
val task = jsonParser.fromJson(
|
||||
session.inputStream.bufferedReader(),
|
||||
Task::class.java
|
||||
)
|
||||
database.taskDao().insert(task)
|
||||
|
||||
return newFixedLengthResponse(
|
||||
Response.Status.CREATED,
|
||||
"application/json",
|
||||
jsonParser.toJson(task)
|
||||
)
|
||||
}
|
||||
// other methods are not allowed
|
||||
else -> {
|
||||
return newFixedLengthResponse(
|
||||
Response.Status.METHOD_NOT_ALLOWED,
|
||||
"text/plain",
|
||||
"Method not allowed"
|
||||
)
|
||||
}
|
||||
// TODO(Faraphel): implement a permission system
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the server with the default configuration
|
||||
*/
|
||||
override fun start() {
|
||||
super.start(SOCKET_READ_TIMEOUT, false)
|
||||
}
|
||||
}
|
|
@ -1,9 +1,6 @@
|
|||
package com.faraphel.tasks_valider.database
|
||||
|
||||
import android.os.Build
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.room.Database
|
||||
import androidx.room.DatabaseConfiguration
|
||||
import androidx.room.RoomDatabase
|
||||
import androidx.room.TypeConverters
|
||||
import com.faraphel.tasks_valider.database.converters.InstantConverter
|
||||
|
@ -13,15 +10,19 @@ import com.faraphel.tasks_valider.database.dao.StudentDao
|
|||
import com.faraphel.tasks_valider.database.dao.TaskDao
|
||||
import com.faraphel.tasks_valider.database.dao.TaskGroupDao
|
||||
import com.faraphel.tasks_valider.database.dao.TeacherDao
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseDao
|
||||
import com.faraphel.tasks_valider.database.entities.Group
|
||||
import com.faraphel.tasks_valider.database.entities.GroupStudent
|
||||
import com.faraphel.tasks_valider.database.entities.Student
|
||||
import com.faraphel.tasks_valider.database.entities.Task
|
||||
import com.faraphel.tasks_valider.database.entities.TaskGroup
|
||||
import com.faraphel.tasks_valider.database.entities.Teacher
|
||||
import java.time.Instant
|
||||
|
||||
|
||||
/**
|
||||
* The database for the tasks application.
|
||||
* Contains the entities and the relations between them.
|
||||
*/
|
||||
@Database(
|
||||
entities = [
|
||||
Group::class,
|
||||
|
@ -37,7 +38,7 @@ import java.time.Instant
|
|||
@TypeConverters(
|
||||
InstantConverter::class
|
||||
)
|
||||
abstract class Database : RoomDatabase() {
|
||||
abstract class TaskDatabase : RoomDatabase() {
|
||||
// entities
|
||||
abstract fun groupDao(): GroupDao
|
||||
abstract fun studentDao(): StudentDao
|
||||
|
@ -47,4 +48,20 @@ abstract class Database : RoomDatabase() {
|
|||
// relations
|
||||
abstract fun groupStudentDao(): GroupStudentDao
|
||||
abstract fun taskGroupDao(): TaskGroupDao
|
||||
|
||||
/**
|
||||
* Get the DAO from the name of the dao.
|
||||
*/
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun <Entity> daoFromName(name: String): BaseDao<Entity>? {
|
||||
return when (name) {
|
||||
"group" -> groupDao()
|
||||
"student" -> studentDao()
|
||||
"teacher" -> teacherDao()
|
||||
"task" -> taskDao()
|
||||
"group_student" -> groupStudentDao()
|
||||
"task_group" -> taskGroupDao()
|
||||
else -> null
|
||||
} as BaseDao<Entity>?
|
||||
}
|
||||
}
|
|
@ -11,16 +11,16 @@ import androidx.compose.runtime.mutableIntStateOf
|
|||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import com.faraphel.tasks_valider.connectivity.room.RoomClient
|
||||
import com.faraphel.tasks_valider.connectivity.task.TaskClient
|
||||
import com.faraphel.tasks_valider.ui.screen.communication.DEFAULT_SERVER_ADDRESS
|
||||
import com.faraphel.tasks_valider.ui.screen.communication.DEFAULT_SERVER_PORT
|
||||
import com.faraphel.tasks_valider.ui.screen.communication.RANGE_SERVER_PORT
|
||||
import com.faraphel.tasks_valider.ui.screen.tasks.TaskGroupScreen
|
||||
import com.faraphel.tasks_valider.ui.screen.task.TaskGroupScreen
|
||||
|
||||
|
||||
@Composable
|
||||
fun CommunicationInternetClientScreen() {
|
||||
val client = remember { mutableStateOf<RoomClient?>(null) }
|
||||
val client = remember { mutableStateOf<TaskClient?>(null) }
|
||||
|
||||
if (client.value == null) CommunicationInternetClientContent(client)
|
||||
else TaskGroupScreen()
|
||||
|
@ -28,7 +28,7 @@ fun CommunicationInternetClientScreen() {
|
|||
|
||||
|
||||
@Composable
|
||||
fun CommunicationInternetClientContent(client: MutableState<RoomClient?>) {
|
||||
fun CommunicationInternetClientContent(client: MutableState<TaskClient?>) {
|
||||
val serverAddress = remember { mutableStateOf(DEFAULT_SERVER_ADDRESS) }
|
||||
val serverPort = remember { mutableIntStateOf(DEFAULT_SERVER_PORT) }
|
||||
|
||||
|
@ -55,7 +55,7 @@ fun CommunicationInternetClientContent(client: MutableState<RoomClient?>) {
|
|||
|
||||
Button(onClick = {
|
||||
// TODO(Faraphel): check if the server is reachable
|
||||
client.value = RoomClient(serverAddress.value, serverPort.intValue)
|
||||
client.value = TaskClient(serverAddress.value, serverPort.intValue)
|
||||
client.value!!.start()
|
||||
}) {
|
||||
Text("Connect")
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
package com.faraphel.tasks_valider.ui.screen.communication.internet
|
||||
|
||||
import android.app.Activity
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.activity
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
|
@ -13,7 +15,7 @@ import com.faraphel.tasks_valider.ui.screen.communication.internet.server.Commun
|
|||
|
||||
|
||||
@Composable
|
||||
fun CommunicationInternetScreen() {
|
||||
fun CommunicationInternetScreen(activity: Activity) {
|
||||
val controller = rememberNavController()
|
||||
|
||||
NavHost(navController = controller, startDestination = "mode") {
|
||||
|
@ -24,7 +26,7 @@ fun CommunicationInternetScreen() {
|
|||
CommunicationInternetClientScreen()
|
||||
}
|
||||
composable("server") {
|
||||
CommunicationInternetServerScreen()
|
||||
CommunicationInternetServerScreen(activity)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.faraphel.tasks_valider.ui.screen.communication.internet.server
|
||||
|
||||
import android.app.Activity
|
||||
import android.util.Log
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material3.Button
|
||||
|
@ -13,26 +15,27 @@ import androidx.compose.runtime.mutableIntStateOf
|
|||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import com.faraphel.tasks_valider.connectivity.bwf.BwfManager
|
||||
import com.faraphel.tasks_valider.connectivity.room.RoomServer
|
||||
import androidx.room.Room
|
||||
import com.faraphel.tasks_valider.connectivity.task.TaskServer
|
||||
import com.faraphel.tasks_valider.database.TaskDatabase
|
||||
import com.faraphel.tasks_valider.ui.screen.communication.DEFAULT_SERVER_PORT
|
||||
import com.faraphel.tasks_valider.ui.screen.communication.RANGE_SERVER_PORT
|
||||
import com.faraphel.tasks_valider.ui.screen.tasks.TaskGroupScreen
|
||||
import com.faraphel.tasks_valider.ui.screen.task.TaskGroupScreen
|
||||
|
||||
|
||||
@Composable
|
||||
fun CommunicationInternetServerScreen() {
|
||||
val server = remember { mutableStateOf<RoomServer?>(null)}
|
||||
fun CommunicationInternetServerScreen(activity: Activity) {
|
||||
val server = remember { mutableStateOf<TaskServer?>(null)}
|
||||
|
||||
// if the server is not created, prompt the user for the server configuration
|
||||
if (server.value == null) CommunicationInternetServerContent(server)
|
||||
if (server.value == null) CommunicationInternetServerContent(activity, server)
|
||||
// else, go to the base tasks screen
|
||||
else TaskGroupScreen()
|
||||
}
|
||||
|
||||
|
||||
@Composable
|
||||
fun CommunicationInternetServerContent(server: MutableState<RoomServer?>) {
|
||||
fun CommunicationInternetServerContent(activity: Activity, server: MutableState<TaskServer?>) {
|
||||
val expandedStudentList = remember { mutableStateOf(false) }
|
||||
val serverPort = remember { mutableIntStateOf(DEFAULT_SERVER_PORT) }
|
||||
|
||||
|
@ -69,9 +72,20 @@ fun CommunicationInternetServerContent(server: MutableState<RoomServer?>) {
|
|||
)
|
||||
|
||||
Button(onClick = {
|
||||
server.value = RoomServer(serverPort.intValue)
|
||||
// Reset the database | TODO(Faraphel): only for testing purpose
|
||||
activity.deleteDatabase("local")
|
||||
|
||||
// Create the database
|
||||
val database = Room.databaseBuilder(
|
||||
activity,
|
||||
TaskDatabase::class.java,
|
||||
"local"
|
||||
).build()
|
||||
|
||||
// Create the server
|
||||
Log.i("room-server", "creating the server")
|
||||
server.value = TaskServer(serverPort.intValue, database)
|
||||
server.value!!.start()
|
||||
// TODO(Faraphel): go to the base tasks screen
|
||||
}) {
|
||||
Text("Create")
|
||||
}
|
||||
|
|
|
@ -35,11 +35,11 @@ fun CommunicationScreen(activity: Activity) {
|
|||
CommunicationSelectContent(controller, activity)
|
||||
}
|
||||
composable("internet") {
|
||||
CommunicationInternetScreen()
|
||||
CommunicationInternetScreen(activity)
|
||||
}
|
||||
composable("wifi-p2p") {
|
||||
val bwfManager = BwfManager.fromActivity(activity)
|
||||
CommunicationWifiP2pScreen(bwfManager)
|
||||
CommunicationWifiP2pScreen(activity, bwfManager)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import androidx.compose.runtime.MutableState
|
|||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import com.faraphel.tasks_valider.connectivity.bwf.BwfManager
|
||||
import com.faraphel.tasks_valider.ui.screen.tasks.TaskGroupScreen
|
||||
import com.faraphel.tasks_valider.ui.screen.task.TaskGroupScreen
|
||||
import com.faraphel.tasks_valider.ui.widgets.connectivity.WifiP2pDeviceListWidget
|
||||
|
||||
|
||||
|
@ -23,6 +23,7 @@ fun CommunicationWifiP2pClientScreen(bwfManager: BwfManager) {
|
|||
return
|
||||
}
|
||||
|
||||
|
||||
// if the device is selected but not connected, try to connect
|
||||
if (selectedDevice.value != null) {
|
||||
// TODO(Faraphel): error handling
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.faraphel.tasks_valider.ui.screen.communication.wifiP2p
|
||||
|
||||
import android.app.Activity
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.Text
|
||||
|
@ -9,14 +10,12 @@ import androidx.navigation.compose.NavHost
|
|||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import com.faraphel.tasks_valider.connectivity.bwf.BwfManager
|
||||
import com.faraphel.tasks_valider.ui.screen.communication.internet.CommunicationInternetScreen
|
||||
import com.faraphel.tasks_valider.ui.screen.communication.internet.server.CommunicationInternetServerScreen
|
||||
import com.faraphel.tasks_valider.ui.screen.communication.wifiP2p.client.CommunicationWifiP2pClientScreen
|
||||
import com.faraphel.tasks_valider.ui.screen.communication.wifiP2p.server.CommunicationWifiP2pServerScreen
|
||||
|
||||
|
||||
@Composable
|
||||
fun CommunicationWifiP2pScreen(bwfManager: BwfManager) {
|
||||
fun CommunicationWifiP2pScreen(activity: Activity, bwfManager: BwfManager) {
|
||||
val controller = rememberNavController()
|
||||
|
||||
NavHost(navController = controller, startDestination = "mode") {
|
||||
|
@ -27,7 +26,7 @@ fun CommunicationWifiP2pScreen(bwfManager: BwfManager) {
|
|||
CommunicationWifiP2pClientScreen(bwfManager)
|
||||
}
|
||||
composable("server") {
|
||||
CommunicationWifiP2pServerScreen(bwfManager)
|
||||
CommunicationWifiP2pServerScreen(activity, bwfManager)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.faraphel.tasks_valider.ui.screen.communication.wifiP2p.server
|
||||
|
||||
import android.app.Activity
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material3.Button
|
||||
|
@ -13,19 +14,21 @@ import androidx.compose.runtime.mutableIntStateOf
|
|||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.room.Room
|
||||
import com.faraphel.tasks_valider.connectivity.bwf.BwfManager
|
||||
import com.faraphel.tasks_valider.connectivity.room.RoomServer
|
||||
import com.faraphel.tasks_valider.connectivity.task.TaskServer
|
||||
import com.faraphel.tasks_valider.database.TaskDatabase
|
||||
import com.faraphel.tasks_valider.ui.screen.communication.DEFAULT_SERVER_PORT
|
||||
import com.faraphel.tasks_valider.ui.screen.communication.RANGE_SERVER_PORT
|
||||
import com.faraphel.tasks_valider.ui.screen.tasks.TaskGroupScreen
|
||||
import com.faraphel.tasks_valider.ui.screen.task.TaskGroupScreen
|
||||
|
||||
|
||||
@Composable
|
||||
fun CommunicationWifiP2pServerScreen(bwfManager: BwfManager) {
|
||||
val server = remember { mutableStateOf<RoomServer?>(null)}
|
||||
fun CommunicationWifiP2pServerScreen(activity: Activity, bwfManager: BwfManager) {
|
||||
val server = remember { mutableStateOf<TaskServer?>(null)}
|
||||
|
||||
// if the server is not created, prompt the user for the server configuration
|
||||
if (server.value == null) CommunicationWifiP2pServerContent(bwfManager, server)
|
||||
if (server.value == null) CommunicationWifiP2pServerContent(activity, bwfManager, server)
|
||||
// else, go to the base tasks screen
|
||||
else TaskGroupScreen()
|
||||
}
|
||||
|
@ -33,8 +36,9 @@ fun CommunicationWifiP2pServerScreen(bwfManager: BwfManager) {
|
|||
|
||||
@Composable
|
||||
fun CommunicationWifiP2pServerContent(
|
||||
activity: Activity,
|
||||
bwfManager: BwfManager,
|
||||
server: MutableState<RoomServer?>
|
||||
server: MutableState<TaskServer?>
|
||||
) {
|
||||
val expandedStudentList = remember { mutableStateOf(false) }
|
||||
val serverPort = remember { mutableIntStateOf(DEFAULT_SERVER_PORT) }
|
||||
|
@ -72,8 +76,21 @@ fun CommunicationWifiP2pServerContent(
|
|||
)
|
||||
|
||||
Button(onClick = {
|
||||
// TODO(Faraphel): should be merged with the internet server
|
||||
|
||||
// Reset the database | TODO(Faraphel): only for testing purpose
|
||||
activity.deleteDatabase("local")
|
||||
|
||||
// Create the database
|
||||
val database = Room.databaseBuilder(
|
||||
activity,
|
||||
TaskDatabase::class.java,
|
||||
"local"
|
||||
).build()
|
||||
|
||||
bwfManager.recreateGroup {
|
||||
server.value = RoomServer(serverPort.intValue)
|
||||
// Create the server
|
||||
server.value = TaskServer(serverPort.intValue, database)
|
||||
server.value!!.start()
|
||||
}
|
||||
}) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package com.faraphel.tasks_valider.ui.screen.tasks
|
||||
package com.faraphel.tasks_valider.ui.screen.task
|
||||
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
|
@ -1,4 +1,4 @@
|
|||
package com.faraphel.tasks_valider.ui.widgets.tasks
|
||||
package com.faraphel.tasks_valider.ui.widgets.task
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.material3.Text
|
|
@ -1,4 +1,4 @@
|
|||
package com.faraphel.tasks_valider.ui.widgets.tasks
|
||||
package com.faraphel.tasks_valider.ui.widgets.task
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.material3.Text
|
|
@ -1,4 +1,4 @@
|
|||
package com.faraphel.tasks_valider.ui.widgets.tasks
|
||||
package com.faraphel.tasks_valider.ui.widgets.task
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
|
@ -11,12 +11,12 @@ import androidx.compose.material3.Text
|
|||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.faraphel.tasks_valider.database.Database
|
||||
import com.faraphel.tasks_valider.database.TaskDatabase
|
||||
import com.faraphel.tasks_valider.database.entities.TaskGroup
|
||||
|
||||
|
||||
@Composable
|
||||
fun WidgetTaskStudent(database: Database, taskStudent: TaskGroup) {
|
||||
fun WidgetTaskStudent(database: TaskDatabase, taskStudent: TaskGroup) {
|
||||
val teacherDao = database.teacherDao()
|
||||
|
||||
Column {
|
Loading…
Reference in a new issue