fixing conneciton state after a wifi disconnect

This commit is contained in:
2025-07-04 07:59:11 -04:00
parent 613686989e
commit c6e43a9f96
2 changed files with 66 additions and 35 deletions

View File

@@ -38,6 +38,8 @@ class WifiAwareManager(private val context: Context) {
private var subscribeDiscoverySession: SubscribeDiscoverySession? = null
private val peerHandles = ConcurrentHashMap<String, PeerHandle>()
private val peerRoomMapping = ConcurrentHashMap<String, String>() // PeerHandle.toString() -> roomName
private var currentRoom: String? = null
// Replace callbacks with Flows
private val _messageFlow = MutableSharedFlow<Triple<String, String, String>>()
@@ -111,6 +113,7 @@ class WifiAwareManager(private val context: Context) {
}
fun startHostMode(roomName: String) {
currentRoom = roomName
val config = PublishConfig.Builder()
.setServiceName(SERVICE_NAME)
.setServiceSpecificInfo(roomName.toByteArray())
@@ -196,6 +199,7 @@ class WifiAwareManager(private val context: Context) {
// Store peer handle for this room
peerHandles[roomName] = peerHandle
currentRoom = roomName
// Send connection request to host
Log.d(TAG, "Sending connection request to room: $roomName")
@@ -203,7 +207,8 @@ class WifiAwareManager(private val context: Context) {
// Update peer activity when discovered
val peerId = peerHandle.toString()
lastPeerActivity[peerId] = System.currentTimeMillis()
peerRoomMapping[peerId] = roomName
lastPeerActivity[roomName] = System.currentTimeMillis()
// Wait a bit for host to prepare, then connect
coroutineScope.launch {
@@ -288,8 +293,19 @@ class WifiAwareManager(private val context: Context) {
override fun onLost(network: android.net.Network) {
Log.d(TAG, "onLost: Network lost for room: $roomName")
// Clear peer handles when connection is lost
// Check if we still have active keep-alive for this room
val lastActivity = lastPeerActivity[roomName]
val currentTime = System.currentTimeMillis()
if (lastActivity != null && (currentTime - lastActivity) < KEEP_ALIVE_TIMEOUT_MS) {
Log.d(TAG, "Network lost but keep-alive still active for room: $roomName - ignoring disconnect")
// Don't disconnect if keep-alive is still active
return
}
// Clear peer handles when connection is truly lost
peerHandles.remove(roomName)
lastPeerActivity.remove(roomName)
coroutineScope.launch {
_connectionFlow.emit(Pair(roomName, false))
}
@@ -358,8 +374,10 @@ class WifiAwareManager(private val context: Context) {
override fun onAvailable(network: android.net.Network) {
Log.d(TAG, "Client connected")
val peerId = peerHandle.toString()
peerHandles[peerId] = peerHandle
lastPeerActivity[peerId] = System.currentTimeMillis()
val roomName = currentRoom ?: "host"
peerHandles[roomName] = peerHandle
peerRoomMapping[peerId] = roomName
lastPeerActivity[roomName] = System.currentTimeMillis()
if (!isResumed) {
isResumed = true
continuation.resume(Result.success(Unit))
@@ -391,7 +409,11 @@ class WifiAwareManager(private val context: Context) {
try {
// Update peer activity on any message
val peerId = peerHandle.toString()
lastPeerActivity[peerId] = System.currentTimeMillis()
val roomName = peerRoomMapping[peerId] ?: currentRoom
if (roomName != null) {
lastPeerActivity[roomName] = System.currentTimeMillis()
}
val messageStr = String(message)
val parts = messageStr.split("|", limit = 3)
@@ -468,23 +490,23 @@ class WifiAwareManager(private val context: Context) {
var messagesSent = 0
if (publishDiscoverySession != null && peerHandles.isNotEmpty()) {
peerHandles.forEach { (peerId, peerHandle) ->
peerHandles.forEach { (roomName, peerHandle) ->
try {
publishDiscoverySession?.sendMessage(peerHandle, messagesSent, message)
messagesSent++
Log.d(TAG, "Sent keep-alive to peer: $peerId")
Log.d(TAG, "Sent keep-alive to room: $roomName")
} catch (e: Exception) {
Log.e(TAG, "Failed to send keep-alive to peer: $peerId", e)
Log.e(TAG, "Failed to send keep-alive to room: $roomName", e)
}
}
} else if (subscribeDiscoverySession != null && peerHandles.isNotEmpty()) {
peerHandles.forEach { (peerId, peerHandle) ->
peerHandles.forEach { (roomName, peerHandle) ->
try {
subscribeDiscoverySession?.sendMessage(peerHandle, messagesSent, message)
messagesSent++
Log.d(TAG, "Sent keep-alive to peer: $peerId")
Log.d(TAG, "Sent keep-alive to room: $roomName")
} catch (e: Exception) {
Log.e(TAG, "Failed to send keep-alive to peer: $peerId", e)
Log.e(TAG, "Failed to send keep-alive to room: $roomName", e)
}
}
}
@@ -493,7 +515,12 @@ class WifiAwareManager(private val context: Context) {
private fun handleKeepAlive(peerHandle: PeerHandle, shouldReply: Boolean) {
// Update last activity for this peer
val peerId = peerHandle.toString()
lastPeerActivity[peerId] = System.currentTimeMillis()
val roomName = peerRoomMapping[peerId] ?: currentRoom
if (roomName != null) {
lastPeerActivity[roomName] = System.currentTimeMillis()
Log.d(TAG, "Updated keep-alive activity for room: $roomName")
}
// Send acknowledgment if requested
if (shouldReply) {
@@ -513,25 +540,26 @@ class WifiAwareManager(private val context: Context) {
private fun checkPeerActivity() {
val currentTime = System.currentTimeMillis()
val inactivePeers = mutableListOf<String>()
val inactiveRooms = mutableListOf<String>()
lastPeerActivity.forEach { (peerId, lastActivity) ->
lastPeerActivity.forEach { (roomName, lastActivity) ->
if (currentTime - lastActivity > KEEP_ALIVE_TIMEOUT_MS) {
Log.w(TAG, "Peer $peerId inactive for too long, considering disconnected")
inactivePeers.add(peerId)
Log.w(TAG, "Room $roomName inactive for too long, considering disconnected")
inactiveRooms.add(roomName)
}
}
// Remove inactive peers
inactivePeers.forEach { peerId ->
lastPeerActivity.remove(peerId)
peerHandles.remove(peerId)
}
// If all peers are disconnected, emit disconnection event
if (peerHandles.isEmpty() && lastPeerActivity.isNotEmpty()) {
// Remove inactive rooms
inactiveRooms.forEach { roomName ->
lastPeerActivity.remove(roomName)
peerHandles.remove(roomName)
// Clean up peer room mapping
peerRoomMapping.entries.removeIf { it.value == roomName }
// Emit disconnection event for this room
coroutineScope.launch {
_connectionFlow.emit(Pair("", false))
_connectionFlow.emit(Pair(roomName, false))
}
}
}
@@ -547,6 +575,8 @@ class WifiAwareManager(private val context: Context) {
wifiAwareSession?.close()
wifiAwareSession = null
peerHandles.clear()
peerRoomMapping.clear()
currentRoom = null
// Don't cancel the coroutine scope - we need it for future operations
Log.d(TAG, "WifiAwareManager stopped - session cleared for fresh start")
}

View File

@@ -72,14 +72,7 @@ class ChatRepository @Inject constructor(
)
addMessage(message)
// If we're receiving messages, we must be connected
if (_connectionState.value !is ConnectionState.Connected &&
_connectionState.value !is ConnectionState.Hosting) {
when (_connectionState.value) {
is ConnectionState.Hosting -> {} // Keep hosting state
else -> _connectionState.value = ConnectionState.Connected("Active")
}
}
// Don't change connection state based on messages - let WifiAwareManager handle it
}
} catch (e: Exception) {
android.util.Log.e("ChatRepository", "Error collecting message flow", e)
@@ -90,12 +83,20 @@ class ChatRepository @Inject constructor(
repositoryScope.launch {
try {
wifiAwareManager.connectionFlow.collect { (roomName, isConnected) ->
android.util.Log.d("ChatRepository", "Connection flow update - room: $roomName, connected: $isConnected, current state: ${_connectionState.value}")
if (isConnected) {
currentRoomName = roomName
_connectionState.value = ConnectionState.Connected(roomName)
// Only change to connected if we're not already hosting
if (_connectionState.value !is ConnectionState.Hosting) {
_connectionState.value = ConnectionState.Connected(roomName)
}
loadMessagesFromDatabase(roomName)
} else {
_connectionState.value = ConnectionState.Disconnected
// Only disconnect if the room matches our current room
if (roomName.isEmpty() || roomName == currentRoomName) {
_connectionState.value = ConnectionState.Disconnected
}
}
// Call the legacy callback if set
connectionCallback?.invoke(roomName, isConnected)