简体   繁体   English

Java ADB Shell不返回任何内容

[英]Java ADB shell returns nothing

I want to write a java program to find a device and list its contents. 我想编写一个Java程序来查找设备并列出其内容。 For that I first fire "adb devices" via Java's Process class and parse the output, which works just finde. 为此,我首先通过Java的Process类触发“ adb设备”并解析输出,该输出只是finde。 Then I want to fire this command: 然后我要触发此命令:

adb shell -s DEVICE-SERIAL /sdcard/

When I put that into my terminal I get the right output, a list of all folders and files in at the root of /sdcard/. 当我将其放入终端时,会得到正确的输出,即/ sdcard /根目录中所有文件夹和文件的列表。

When I put that into Java code nothing is returned. 当我将其放入Java代码时,不会返回任何内容。 Stderr however contains the standard help page you get when you misspell an adb command. 但是,Stderr包含拼写adb命令时获得的标准帮助页面。 Here's the funny thing: For debugging I output every command sent to ADB. 这是有趣的事情:为了调试,我输出了每个发送到ADB的命令。 If I run my programm and copy the exact same generated command and run it in my terminal it works just fine. 如果我运行程序并复制完全相同的生成命令,然后在终端中运行它,则工作正常。

Why is that? 这是为什么? For reference, here are my code excerpts for that: 供参考,这是我的代码摘录:

ADB.java: ADB.java:

public static String runShellCommand(Device d, String command) {
    return runCommand(d, "shell " + command);
}

public static String runCommand(Device d, String command) {
    Runtime runtime = Runtime.getRuntime();
    String full = "";
    String error = "";

    try {
        if (d != null) {
            command = "-s " + d.getSerial() + " " + command;
        }

        System.out.println("Running command: adb " + command);
        Process process = runtime.exec(new String[] {ADB_LOCATION, command});

            process.waitFor();

        BufferedReader stdin = new BufferedReader(new InputStreamReader(process.getInputStream()));
        BufferedReader errin = new BufferedReader(new InputStreamReader(process.getErrorStream()));

        String line;

        while ((line = stdin.readLine()) != null) {
            full += line;
        }

        while ((line = errin.readLine()) != null) {
            error += line;
        }

        if (!error.isEmpty()) {
            System.err.println("\n=== ADB reports: ===");
            System.err.println(error);
        }
    } catch (IOException e) {
        e.printStackTrace();
    } catch (InterruptedException e) {
        System.out.println("App was overenthuasiastic. Couldn't wait for thread to finish.");
    }

    return full;
}

Device.java: Device.java:

public ArrayList<Folder> getFoldersInDirectory(String dir) {
    String[] list = ls(dir);

    for (String s: list) {
        System.out.println(s);
        System.out.println(isFolderOrFile(dir + s));
    }

    // Just for debugging, gets completed once this runs.
    return null;
}

protected String[] ls(String dir) {
    String result = ADB.runShellCommand(this, "ls " + dir);
    System.out.println(result);

    return result.split("\n");
}

As I said before, every other command runs just fine (I tested devices, get-state, get-serialno). 正如我之前所说,其他所有命令都可以正常运行(我测试了设备,get-state,get-serialno)。

Outputs: 输出: 输出

The parameters for runtime.exec() are wrong. runtime.exec()的参数错误。 You are using {'adb', '-s xxxx shell "ls /sdcard/"'} when you should be using {'adb', '-s', 'xxxx', 'shell', 'ls /sdcard/'} 当您应该使用{'adb', '-s', 'xxxx', 'shell', 'ls /sdcard/'}{'adb', '-s xxxx shell "ls /sdcard/"'}您正在使用{'adb', '-s xxxx shell "ls /sdcard/"'} {'adb', '-s', 'xxxx', 'shell', 'ls /sdcard/'}

Perhaps a bit too late for the OP, but could be useful for later viewers. 对于OP来说可能为时已晚,但对以后的观看者可能有用。

Recently I had to integrate one system to work closely with real devices via adb. 最近,我不得不集成一个系统以通过adb与实际设备紧密协作。 Took a bit of time to figure out all the nasty bits of how to do it "properly". 花了一些时间来弄清楚如何“适当地”做所有令人讨厌的事情。 Then I had an idea to create a library that handles at least some basic adb commands (adb devices, shell, pull, push, install). 然后我想到了一个创建至少处理一些基本adb命令(adb设备,shell,pull,push,install)的库的想法。 It can do adb on local machine, or on remote machine over ssh (with key exchange setup) with the same API. 它可以使用相同的API在本地计算机上或通过ssh(具有密钥交换设置)在远程计算机上执行adb。 Do not confuse with adb shell forwarding ;). 不要与adb shell转发混淆;)。

Its under apache 2.0 license: https://github.com/lesavsoftware/rem-adb-exec 它在Apache 2.0许可下: https : //github.com/lesavsoftware/rem-adb-exec

Thanks to Alex P. I found a solution that's working (need to parse the output, though, but that's a different story): 感谢AlexP。我找到了一个可行的解决方案(尽管需要解析输出,但这是另一回事了):

I just modified runCommand() to put the arguments in an String-array and give it to exec: 我刚刚修改了runCommand(),将参数放入字符串数组中,然后将其提供给exec:

public static String runCommand(Device d, String command) {
        Runtime runtime = Runtime.getRuntime();
        String full = "";
        String error = "";

        try {
            String[] cmdWithDevice = new String[5];
            String[] cmdWithoutDevice = new String[2];

            if (d != null) {
                cmdWithDevice[0] = ADB_LOCATION;
                cmdWithDevice[1] = "-s";
                cmdWithDevice[2] = d.getSerial();
                cmdWithDevice[3] = "shell";
                cmdWithDevice[4] = command;

                command = "-s " + d.getSerial() + " " + command;
            } else {
                cmdWithoutDevice[0] = ADB_LOCATION;
                cmdWithoutDevice[1] = command;
            }

            System.out.println("Running command: adb " + command);
            // Process process = runtime.exec(new String[] {ADB_LOCATION, command});
            Process process = runtime.exec(cmdWithDevice[0] == null ? cmdWithoutDevice : cmdWithDevice);

            BufferedReader stdin = new BufferedReader(new InputStreamReader(process.getInputStream()));
            BufferedReader errin = new BufferedReader(new InputStreamReader(process.getErrorStream()));

            process.waitFor();

            String line;

            while ((line = stdin.readLine()) != null) {
                full += line;
            }

            while ((line = errin.readLine()) != null) {
                error += line;
            }

            if (!error.isEmpty()) {
                System.err.println("\n=== ADB reports: ===");
                System.err.println(error);
            }

            stdin.close();
            errin.close();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            System.out.println("App was overenthuasiastic. Couldn't wait for thread to finish.");
        }

        return full;
    }

For some reason it does not work if I run runtime.exec manually with the arguments passed in, only programmatically. 由于某些原因,如果我仅以编程方式手动输入传入的参数来运行runtime.exec,它将无法正常工作。

This solution is a bit hacky, though and needs proper implementation. 尽管该解决方案有点笨拙,但需要适当的实现。 Also this solution assumes that every device-specific command is for shell. 此外,该解决方案还假定每个特定于设备的命令都是针对Shell的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM