[英]Java ADB shell returns nothing
我想編寫一個Java程序來查找設備並列出其內容。 為此,我首先通過Java的Process類觸發“ adb設備”並解析輸出,該輸出只是finde。 然后我要觸發此命令:
adb shell -s DEVICE-SERIAL /sdcard/
當我將其放入終端時,會得到正確的輸出,即/ sdcard /根目錄中所有文件夾和文件的列表。
當我將其放入Java代碼時,不會返回任何內容。 但是,Stderr包含拼寫adb命令時獲得的標准幫助頁面。 這是有趣的事情:為了調試,我輸出了每個發送到ADB的命令。 如果我運行程序並復制完全相同的生成命令,然后在終端中運行它,則工作正常。
這是為什么? 供參考,這是我的代碼摘錄:
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:
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");
}
正如我之前所說,其他所有命令都可以正常運行(我測試了設備,get-state,get-serialno)。
輸出:
runtime.exec()
的參數錯誤。 當您應該使用{'adb', '-s', 'xxxx', 'shell', 'ls /sdcard/'}
時{'adb', '-s xxxx shell "ls /sdcard/"'}
您正在使用{'adb', '-s xxxx shell "ls /sdcard/"'}
{'adb', '-s', 'xxxx', 'shell', 'ls /sdcard/'}
對於OP來說可能為時已晚,但對以后的觀看者可能有用。
最近,我不得不集成一個系統以通過adb與實際設備緊密協作。 花了一些時間來弄清楚如何“適當地”做所有令人討厭的事情。 然后我想到了一個創建至少處理一些基本adb命令(adb設備,shell,pull,push,install)的庫的想法。 它可以使用相同的API在本地計算機上或通過ssh(具有密鑰交換設置)在遠程計算機上執行adb。 不要與adb shell轉發混淆;)。
它在Apache 2.0許可下: https : //github.com/lesavsoftware/rem-adb-exec
感謝AlexP。我找到了一個可行的解決方案(盡管需要解析輸出,但這是另一回事了):
我剛剛修改了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;
}
由於某些原因,如果我僅以編程方式手動輸入傳入的參數來運行runtime.exec,它將無法正常工作。
盡管該解決方案有點笨拙,但需要適當的實現。 此外,該解決方案還假定每個特定於設備的命令都是針對Shell的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.