WiFi direct can be used for Mesh networking because each node can act both as an WiFi access point for others and as a WiFi station (client) itself. The tricky part is that each device as a group owner will be assigned the IP 192.168.49.1, so you get an IP address conflict. The workaround is to use the IPv6 link local addresses to transfer data:
val ssid = group?.networkName
val passphrase = group?.passphrase
val interfaceName = group?.`interface`
val linkInterface = NetworkInterface.getNetworkInterfaces().toList()
.firstOrNull {
it.name == interfaceName
}
val linkLocalAddr = linkInterface?.inetAddresses?.toList()
?.firstOrNull { it.isLinkLocalAddress && it is Inet6Address } as? Inet6Address
Each node can then relay data to/from other nodes over multiple hops.
The device connecting would need to know the LinkLocal IP address of the other node before connecting to the access point; this can be done via QR code and/or Bluetooth Low Energy advertising.
Some Android 12+ devices support Access Point-Station Concurrency. On those devices it is possible to run a Local-only Hotspot and simultaneously connect to another access point as a station (client). The IP range of the Local-only Hotspot is randomized, so it is unlikely that two neighbor nodes will have an IP address conflict.
There is now an open-source library with an initial implementation of a Mesh Network over WiFi (disclaimer: I am the author of that library):
https://www.github.com/UstadMobile/Meshrabiya