Thank you to both @CommonsWare and @Taranmeet Singh for helping to find my solution.
I build a small http server on my phone that can be reach through http call from my laptop.
Two points were not so obvious for me :
- the tecno
- the host ip
For the first point, you can use :
I choose the last option because :
- It used natively kotlin
- It is build and maintained by JetBrains, the other library were less maintained
- It is really light (10 lines to make it works)
To use Ktor you need to add this in your app gradle :
defaultConfig {
...
multiDexEnabled true
}
For the second point : by default you are bind and localhost, but you can change that :
embeddedServer(Netty, host = "192.168.43.1", port = 8080)
This ip is the default one for Android (it seems), you can also Utils method to get it :
How to get IP address of the device from code?
fun getIPAddress(useIPv4: Boolean): String {
try {
val interfaces: List<NetworkInterface> =
Collections.list(NetworkInterface.getNetworkInterfaces())
for (intf in interfaces) {
val addrs: List<InetAddress> = Collections.list(intf.inetAddresses)
for (addr in addrs) {
if (!addr.isLoopbackAddress) {
val sAddr = addr.hostAddress
//boolean isIPv4 = InetAddressUtils.isIPv4Address(sAddr);
val isIPv4 = sAddr.indexOf(':') < 0
if (useIPv4) {
if (isIPv4) return sAddr
} else {
if (!isIPv4) {
val delim = sAddr.indexOf('%') // drop ip6 zone suffix
return if (delim < 0) sAddr.toUpperCase(Locale.ROOT) else sAddr.substring(
0,
delim
).toUpperCase(Locale.ROOT)
}
}
}
}
}
} catch (ignored: Exception) {
} // for now eat exceptions
return ""
}
This work for me, hope it will help others.
Final code look like this:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
embeddedServer(Netty, host = getIPAddress(true), port = 8080) {
install(ContentNegotiation) {
gson {}
}
routing {
get("/") {
call.respond(mapOf("message" to "Hello , this ktor server"))
}
}
}.start(wait = false)
}
/**
* Get IP address from first non-localhost interface
*
* @param useIPv4 true=return ipv4, false=return ipv6
* @return address or empty string
*/
private fun getIPAddress(useIPv4: Boolean): String {
try {
val interfaces: List<NetworkInterface> =
Collections.list(NetworkInterface.getNetworkInterfaces())
for (intf in interfaces) {
val addrs: List<InetAddress> = Collections.list(intf.inetAddresses)
for (addr in addrs) {
if (!addr.isLoopbackAddress) {
val sAddr = addr.hostAddress
//boolean isIPv4 = InetAddressUtils.isIPv4Address(sAddr);
val isIPv4 = sAddr.indexOf(':') < 0
if (useIPv4) {
if (isIPv4) return sAddr
} else {
if (!isIPv4) {
val delim = sAddr.indexOf('%') // drop ip6 zone suffix
return if (delim < 0) sAddr.toUpperCase(Locale.ROOT) else sAddr.substring(
0,
delim
).toUpperCase(Locale.ROOT)
}
}
}
}
}
} catch (ignored: Exception) {
} // for now eat exceptions
return ""
}}