3

Is there any way to programmatically obtain a list of android devices connected to adb ?

I want to do it in Java on a desktop application. I have the path of adb.exe but a parsing on the "adb devices" response doesn't seems to be the best idea.

Is there a more reliable method ?

Buda Florin
  • 624
  • 2
  • 12
  • 30
  • 4
    Why is parsing on the "adb devices" response not the best idea? What can be more reliable to obtain ADB devices than asking ADB itself? – m0skit0 Feb 14 '13 at 17:06
  • 1
    [pyadb is a python library](https://github.com/sch3m4/pyadb) that allows you to interact with adb programmatically. This API defines a get_devices() method which returns a list of device objects. From their code it seems like they are calling `adb devices` and parsing the resulting output into the list of objects. I would guess this is the easiest route to take with java too. – FoamyGuy Feb 14 '13 at 17:10

3 Answers3

6

this is the how I done it

try {
        Process process = Runtime.getRuntime().exec("adb devices");
        BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));  
        String line = null;  

        Pattern pattern = Pattern.compile("^([a-zA-Z0-9\\-]+)(\\s+)(device)");
        Matcher matcher;

        while ((line = in.readLine()) != null) {  
            if (line.matches(pattern.pattern())) {
                matcher = pattern.matcher(line);
                if (matcher.find())
                    System.out.println(matcher.group(1));
            }
        }  
    } catch (IOException e) {
        e.printStackTrace();
    }
Buda Florin
  • 624
  • 2
  • 12
  • 30
  • I get error when I execute the above code - java.io.IOException: Cannot run program "adb": CreateProcess error=2, The system cannot find the file specified; Though I am running it from adb directory. – vv88 Jan 20 '17 at 11:48
  • 1
    instead of .exec("adb devices"); try to add the path of your adb executable .exec("C:/androidSDK//....adb.exe devices"); – Buda Florin Jan 23 '17 at 06:47
4

The optimal solution depends on what you are going to do with the list. If you are going to run some adb commands on the devices you find - parsing adb devices output is the obvious choice. Another option would be going through the USB stack and collecting serial numbers of devices with ADB interface enumerated. Or my favorite one - under Linux I just create a custom udev rule which keeps track of all connected ADB devices. Mine is using a database, but it could be as simple as creating a symlink for every ADB device and then checking the file list.

Alex P.
  • 30,437
  • 17
  • 118
  • 169
0

For those looking for a Kotlin solution, I've adapted Buda Florin's answer:

class Cli {
    fun runCommand(cmd: String, workingDir: File = File("."), timeout: Duration = 3.minutes): String? {
        // this is modified from https://stackoverflow.com/a/52441962/940217
        return try {
            val parts = "\\s".toRegex().split(cmd)
            val proc = ProcessBuilder(*parts.toTypedArray())
                .directory(workingDir)
                .redirectOutput(ProcessBuilder.Redirect.PIPE)
                .redirectError(ProcessBuilder.Redirect.PIPE)
                .start()

            proc.waitFor(timeout.inWholeSeconds, TimeUnit.SECONDS)
            proc.inputStream.bufferedReader().readText()
        } catch (e: IOException) {
            e.printStackTrace()
            null
        }
    }
}

class AdbUtils(){
    fun listDevices(): List<String>? {
        val c = Cli()
        val adbDevicesResponse :String? = c.runCommand("adb devices")
        var deviceIds = adbDevicesResponse?.lines()?.mapNotNull {
            val matches = """^([a-zA-Z0-9\-]+)(\s+)(device)""".toRegex().find(it)
            matches?.groupValues?.get(1)
        }
        return deviceIds
    }
}
Kyle Falconer
  • 8,302
  • 6
  • 48
  • 68