AeroToss: быстрый discovery + file picker + передача файлов

Discovery:
- Broadcast отправляется немедленно при старте (без задержки 3 сек)
- Интервал broadcast: 3 сек → 1 сек
- Timeout сокращён до 2 сек для быстрого отклика

File picker:
- Desktop: java.awt.FileDialog для выбора файла
- Android: ActivityResultContracts.OpenDocument → копирование в temp file
- SendScreen: реальный file picker вместо тестового файла
- Выбор файла: имя + размер
This commit is contained in:
2026-08-19 23:49:41 +03:00
parent fe880cbac1
commit a1b600a614
6 changed files with 155 additions and 171 deletions
@@ -3,11 +3,14 @@ package com.aerotoss
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.result.contract.ActivityResultContracts
import androidx.lifecycle.lifecycleScope
import com.aerotoss.core.AeroTossManager
import com.aerotoss.discovery.CompositeAndroidDiscovery
import com.aerotoss.transfer.AndroidFileTransferManager
import com.aerotoss.ui.App
import com.aerotoss.util.androidFilePickerLauncher
import com.aerotoss.util.handleAndroidPickResult
import com.aerotoss.wifi.WifiDirectManager
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@@ -16,10 +19,20 @@ import kotlinx.coroutines.withContext
class MainActivity : ComponentActivity() {
private var manager: AeroTossManager? = null
private val filePickerLauncher = registerForActivityResult(
ActivityResultContracts.OpenDocument()
) { uri ->
handleAndroidPickResult(uri, applicationContext)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (manager != null) return
androidFilePickerLauncher = { mimeTypes, _ ->
filePickerLauncher.launch(mimeTypes)
}
val transferManager = AndroidFileTransferManager(applicationContext)
val wifiDirectManager = WifiDirectManager(applicationContext)
val discoveryManager = CompositeAndroidDiscovery(wifiDirectManager)
@@ -0,0 +1,33 @@
package com.aerotoss.util
import android.net.Uri
import java.io.File
actual fun pickFile(onResult: (filePath: String?) -> Unit) {
androidPickFileCallback = onResult
androidFilePickerLauncher?.invoke(arrayOf("*/*"), 0) ?: run {
androidPickFileCallback = null
onResult(null)
}
}
var androidFilePickerLauncher: ((Array<String>, Int) -> Unit)? = null
var androidPickFileCallback: ((String?) -> Unit)? = null
fun handleAndroidPickResult(uri: Uri?, context: android.content.Context) {
if (uri == null) {
androidPickFileCallback?.invoke(null)
androidPickFileCallback = null
return
}
try {
val tempFile = File(context.cacheDir, "aerotoss_pick_${System.currentTimeMillis()}")
context.contentResolver.openInputStream(uri)?.use { input ->
tempFile.outputStream().use { output -> input.copyTo(output) }
}
androidPickFileCallback?.invoke(tempFile.absolutePath)
} catch (_: Exception) {
androidPickFileCallback?.invoke(null)
}
androidPickFileCallback = null
}