I'm trying to send a TCP message to a netcat server running on the machine where an Android device is connected.
In order to do so, I'm executing the following steps on the host:
adb reverse tcp:3000 tcp:3000
nc -l -p 3000
By running the device shell and performing the following command:
adb shell
> nc localhost 3000
I can receive arbitrary bytes from the device successfully.
Now, I'm trying to do the same with the following simple Android activity:
@file:OptIn(kotlin.ExperimentalStdlibApi::class)
package tcp.connection
import android.os.Bundle
import android.util.Log
import kotlinx.coroutines.runBlocking
import androidx.appcompat.app.AppCompatActivity
import java.io.PrintWriter
import java.lang.Exception
import java.net.InetAddress
import java.net.InetSocketAddress
import java.net.Socket
class MainActivity : AppCompatActivity() {
private val TAG = "[Main]"
private val WS_DEFAULT_PORT = 3000
private val WS_DEFAULT_HOST = "localhost"
private val WS_DEFAULT_TIMEOUT = 10_000L
private val INTENT_KEY_WS_HOST = "wsHost"
private val INTENT_KEY_WS_PORT = "wsPort"
private val INTENT_KEY_WS_TIMEOUT = "wsTimeout"
private var wsHost = WS_DEFAULT_HOST
private var wsPort = WS_DEFAULT_PORT
private var wsTimeout = WS_DEFAULT_TIMEOUT
fun tcpPing() {
Log.d(TAG, "PROBLEM - 1")
try {
// Create a socket to connect to the server
Log.d(TAG, "PROBLEM - 2")
val socket = Socket()
Log.d(TAG, "PROBLEM - 3 socket created")
socket.connect(InetSocketAddress(wsHost, wsPort), wsTimeout.toInt())
Log.d(TAG, "PROBLEM - 4 socket connection estabilished")
// Send the message
val autoflush = true
val msg = "PING\n"
PrintWriter(socket.getOutputStream(), autoflush).write(msg)
// Close the socket
Log.d(TAG, "PROBLEM - 5 before closing")
socket.close()
Log.d(TAG, "PROBLEM - 6 after closing")
} catch (e: Exception) {
e.printStackTrace()
Log.d(TAG, "PROBLEM - 7 failed")
}
}
@OptIn(ExperimentalUnsignedTypes::class)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Send intent extra by adding --es <param> to the launch.sh
// script
if (intent.extras != null) {
wsHost = intent.extras!!.getString(INTENT_KEY_WS_HOST, WS_DEFAULT_HOST)
wsPort =
intent.extras!!.getString(INTENT_KEY_WS_PORT, WS_DEFAULT_PORT.toString()).toInt()
wsTimeout =
intent.extras!!.getString(INTENT_KEY_WS_TIMEOUT, WS_DEFAULT_TIMEOUT.toString())
.toLong()
}
Log.d(TAG, "Host: $wsHost")
Log.d(TAG, "Port: $wsPort")
Log.d(TAG, "Timeout: $wsTimeout")
val t = object : Thread() {
override fun run() {
super.run()
tcpPing()
}
}
runBlocking { t.start() }
}
override fun onStop() {
super.onStop()
}
}
And with these entries in the AndroidManifest.xml
:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
This is the relevant log shown on logcat:
08-08 11:46:42.817 13722 13722 D [Main] : Host: localhost
08-08 11:46:42.817 13722 13722 D [Main] : Port: 3000
08-08 11:46:42.817 13722 13722 D [Main] : Timeout: 10000
08-08 11:46:42.910 13722 13748 D [Main] : PROBLEM - 1
08-08 11:46:42.910 13722 13748 D [Main] : PROBLEM - 2
08-08 11:46:42.911 13722 13748 D [Main] : PROBLEM - 3 socket created
08-08 11:46:52.936 13722 13748 W System.err: java.net.SocketTimeoutException: failed to connect to localhost/127.0.0.1 (port 3000) from /127.0.0.1 (port 42064) after 10000ms
08-08 11:46:52.938 13722 13748 W System.err: at libcore.io.IoBridge.connectErrno(IoBridge.java:191)
08-08 11:46:52.939 13722 13748 W System.err: at libcore.io.IoBridge.connect(IoBridge.java:135)
08-08 11:46:52.939 13722 13748 W System.err: at java.net.PlainSocketImpl.socketConnect(PlainSocketImpl.java:142)
08-08 11:46:52.940 13722 13748 W System.err: at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:390)
08-08 11:46:52.940 13722 13748 W System.err: at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:230)
08-08 11:46:52.941 13722 13748 W System.err: at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:212)
08-08 11:46:52.941 13722 13748 W System.err: at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:436)
08-08 11:46:52.942 13722 13748 W System.err: at java.net.Socket.connect(Socket.java:621)
08-08 11:46:52.943 13722 13748 W System.err: at tcp.connection.MainActivity.tcpPing(MainActivity.kt:126)
08-08 11:46:52.945 13722 13748 W System.err: at tcp.connection.MainActivity$onCreate$t$1.run(MainActivity.kt:200)
08-08 11:46:52.945 13722 13748 D [Main] : PROBLEM - 7 failed
What am I doing wrong?
Thank you in advance.
This was due to the device's display being locked when launching the app: disabling the Power Saving configuration and disabling the lock of the device solved the issue.