2

I'm trying to run a shell command in my Android app in order to check if a give tcp port is opened or not:

Runtime.getRuntime().exec(arrayOf("/system/bin/sh", "-c", "netstat -tulpn | grep :8080"))

Running this command in Android version < 10, works fine. It will do a full scan and return the entry if there is the given port used.

But in Android 10, it is not working anymore. The process exec will return:

Process[pid=9534 ,hasExited=true, exitcode=1]

When reading the inputStream of the process it is always null, while executing netstat -tulpn | grep :8080 from terminal will return an entry, as expected.

Running

Runtime.getRuntime().exec(arrayOf("/system/bin/sh", "-c", "netstat -tulpn"))

alone, and parsing the output, will only show:

Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program Name

and no other data at all.

I only have this problem in Android 10, because for older versions it is working.

Has anything changed in Android 10 regarding to shell commands? It is necessary for me to run this command. Any help would be appreciated...

Cezary Butler
  • 807
  • 7
  • 21
user677767
  • 203
  • 3
  • 10

2 Answers2

2

This is most likely because of privacy protection improved in Android 10.

Look here: https://developer.android.com/about/versions/10/privacy/changes#proc-net-filesystem

Cezary Butler
  • 807
  • 7
  • 21
  • It is suggesting to use `NetworkStatsManager` or `ConnectivityManager` but I'm not sure it I can scan the used tcp ports in the device using those. – user677767 Jul 27 '20 at 19:43
  • @user677767 I suspect you can't use those APIs to do port scan. If nothing will come up I'll verify that tomorrow. How much control you have over the devices the app is running on? Can you install app as system application? – Cezary Butler Jul 27 '20 at 20:08
  • No. The app is installed via Play Store as a normal third party app. I'm interested to do a scan over tcp ports that are in usage. – user677767 Jul 27 '20 at 20:18
0

My goal was to check if a given tcp port was in use or not. I made this method that did the job that I was looking for:

private fun isPortUsed(port: Int): Boolean {
    return try {
      // Try to open socket at the given port
      val socket = ServerSocket(port)
      // Release port
      socket.close()
      false
    } catch (ex: BindException) {
        // Port is already in use
        true
    } catch (ex: Exception) {
        // Other reason for failing
        false
    }
}
user677767
  • 203
  • 3
  • 10
  • The general idea of how you check if the port is in use is correct. However, this will be unreliable for a few reasons. There is also a third option, an opening of a socket might fail for a different reason which, in your code will falsely return the port is taken. Try finding more specific exception which is thrown when a port is in use. – Cezary Butler Jul 28 '20 at 07:27
  • You are right. I edited my question. If the reason of failure is because the port is already in use, it will through a `BindException`. Thank you – user677767 Jul 28 '20 at 08:20
  • 2
    I'm Glad I could help. Remember, that you can upvote my comment if you find it helpful. – Cezary Butler Jul 31 '20 at 19:30