AeroToss: полный рефакторинг discovery

- TcpDiscovery принимает DeviceType в конструкторе (PHONE/DESKTOP)
- Desktop: type=DESKTOP, Phone: type=PHONE (больше не захардкожено)
- Удалён NSD discovery из Android (только TCP + Wi-Fi Direct)
- CompositeAndroidDiscovery больше не использует AndroidNsdDiscovery
- Удалён UdpBroadcastDiscovery (дублировал TcpDiscovery)
- deviceType теперь корректно передаётся в DiscoveryResponse
- hostAddress теперь всегда содержит реальный IP
This commit is contained in:
2026-08-19 23:24:01 +03:00
parent 2800f862b7
commit 827d431311
4 changed files with 85 additions and 171 deletions
@@ -1,16 +1,10 @@
package com.aerotoss
import android.Manifest
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.content.ContextCompat
import androidx.lifecycle.lifecycleScope
import com.aerotoss.core.AeroTossManager
import com.aerotoss.discovery.AndroidNsdDiscovery
import com.aerotoss.discovery.CompositeAndroidDiscovery
import com.aerotoss.transfer.AndroidFileTransferManager
import com.aerotoss.ui.App
@@ -20,73 +14,24 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class MainActivity : ComponentActivity() {
private var manager: AeroTossManager? = null
private val requiredPermissions: Array<String>
get() {
val perms = mutableListOf(
Manifest.permission.INTERNET,
Manifest.permission.ACCESS_WIFI_STATE,
Manifest.permission.CHANGE_WIFI_STATE,
Manifest.permission.ACCESS_NETWORK_STATE,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.CHANGE_WIFI_MULTICAST_STATE,
)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
perms.add(Manifest.permission.NEARBY_WIFI_DEVICES)
}
return perms.toTypedArray()
}
private val permissionLauncher = registerForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
) { permissions ->
val allGranted = permissions.values.all { it }
if (allGranted && manager == null) {
initializeApp()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (manager != null) return
if (hasAllPermissions()) {
initializeApp()
} else {
permissionLauncher.launch(requiredPermissions)
}
}
private fun hasAllPermissions(): Boolean {
return requiredPermissions.all {
ContextCompat.checkSelfPermission(this, it) == PackageManager.PERMISSION_GRANTED
}
}
private fun initializeApp() {
if (manager != null) return
val transferManager = AndroidFileTransferManager(applicationContext)
val nsdDiscovery = AndroidNsdDiscovery(applicationContext)
val wifiDirectManager = WifiDirectManager(applicationContext)
val discoveryManager = CompositeAndroidDiscovery(nsdDiscovery, wifiDirectManager)
val discoveryManager = CompositeAndroidDiscovery(wifiDirectManager)
val mgr = AeroTossManager(discoveryManager, transferManager)
manager = mgr
lifecycleScope.launch {
val port = withContext(Dispatchers.IO) {
transferManager.startServer(0)
}
val port = withContext(Dispatchers.IO) { transferManager.startServer(0) }
mgr.start(port)
}
setContent {
App(mgr)
}
setContent { App(mgr) }
}
override fun onDestroy() {
@@ -1,6 +1,5 @@
package com.aerotoss.discovery
import android.content.Context
import com.aerotoss.model.Device
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -8,17 +7,17 @@ import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import com.aerotoss.model.DeviceType
import com.aerotoss.wifi.WifiDirectManager
class CompositeAndroidDiscovery(
private val nsdDiscovery: AndroidNsdDiscovery,
private val wifiDirectManager: WifiDirectManager
) : DiscoveryManager {
private val _devices = MutableStateFlow<List<Device>>(emptyList())
override val devices: Flow<List<Device>> = _devices.asStateFlow()
private val tcpDiscovery = TcpDiscovery()
private val tcpDiscovery = TcpDiscovery(DeviceType.PHONE)
@Volatile private var scope: CoroutineScope? = null
@Volatile private var discoveryJob: kotlinx.coroutines.Job? = null
@@ -36,19 +35,16 @@ class CompositeAndroidDiscovery(
tcpDiscovery.devices,
wifiDirectManager.devices
) { tcpDevices, wifiDirectDevices ->
val allDevices = mutableMapOf<String, Device>()
tcpDevices.forEach { allDevices["tcp:${it.id}"] = it }
wifiDirectDevices.forEach { allDevices["wifi:${it.id}"] = it }
allDevices.values.toList()
}.collect { devices ->
_devices.value = devices
}
val all = mutableMapOf<String, Device>()
tcpDevices.forEach { all["tcp:${it.id}"] = it }
wifiDirectDevices.forEach { all["wifi:${it.id}"] = it }
all.values.toList()
}.collect { _devices.value = it }
}
}
override fun stopDiscovery() {
discoveryJob?.cancel()
discoveryJob = null
discoveryJob?.cancel(); discoveryJob = null
tcpDiscovery.stopDiscovery()
wifiDirectManager.stopDiscovery()
_devices.value = emptyList()
@@ -56,8 +52,7 @@ class CompositeAndroidDiscovery(
override fun dispose() {
stopDiscovery()
scope?.cancel()
scope = null
scope?.cancel(); scope = null
tcpDiscovery.dispose()
wifiDirectManager.cleanup()
}