2014-01-07 4 views
0

Java 프로그램을 작성하여 장치를 찾고 해당 내용을 나열하려고합니다. 이를 위해 먼저 Java의 Process 클래스를 통해 "adb 장치"를 실행하고 출력을 구문 분석하여 finde 만 작동합니다. 그런 다음이 명령을 발사 할 : 내 터미널에 난 오른쪽 출력,/sdcard에 /의 루트에있는 모든 폴더와 파일의 목록을 얻을 넣어Java ADB 셸이 아무 것도 반환하지 않습니다.

adb shell -s DEVICE-SERIAL /sdcard/ 

.

Java 코드에 넣으면 아무것도 반환되지 않습니다. 그러나 Stderr에는 adb 명령의 철자를 잘못 입력했을 때 나타나는 표준 도움말 페이지가 있습니다. 다음은 재미있는 일입니다. 디버깅을 위해 ADB로 보낸 모든 명령을 출력합니다. 내 programm을 실행하고 정확히 동일한 생성 된 명령을 복사하여 터미널에서 실행하면 정상적으로 작동합니다.

왜 그럴까요? 참고로, 여기 내 코드 발췌은위한 것입니다 :

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()에 대한 Outputs

+0

없는 –

+0

runShellCommand 기본적으로 그냥 runCommand가 호출하고 전에 "쉘"을두고하지만 난 게시합니다 니펫 그것. –

답변

1

매개 변수가 잘못되었습니다. 당신이 알렉스 P.에 {'adb', '-s', 'xxxx', 'shell', 'ls /sdcard/'}

+0

디버깅 목적으로 필자는 수동으로 작성했지만 작동하지 않았습니다. 아직 출력이 없습니다. 이번에는 stderr도 비어 있습니다. –

+0

빈'/ sdcard' 폴더가 있습니까? –

+0

아니요, 채워짐. 나는 사고로 해결책을 찾았습니다. 나는 그것을 게시 할 것입니다. –

1

감사를 사용해야 할 때 당신은 내가 일하고있어 해결책을 발견 {'adb', '-s xxxx shell "ls /sdcard/"'}를 사용하고 (하지만, 출력을 구문 분석 할 필요가 있지만, 다른 이야기) :

나는 방금 수정 runCommand ()는 문자열 배열에 인수를 넣어 그것을 간부을 제공합니다 :

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의 수동으로 실행하는 경우가 작동하지 않는 몇 가지 이유.

이 솔루션은 약간 해킹이지만 적절한 구현이 필요합니다. 또한이 솔루션은 모든 장치 별 명령이 셸용이라고 가정합니다.

2

OP에 비해 약간 늦었지만 나중에 시청하는 데 유용 할 수 있습니다.

최근 adb를 통해 실제 장치와 긴밀하게 작업하기 위해 하나의 시스템을 통합해야했습니다. "제대로"하는 방법의 모든 불쾌한 비트를 알아낼 시간이 조금 걸렸습니다. 그런 다음 필자는 최소한 기본 adb 명령 (adb 장치, 쉘, 풀, 푸시, 설치)을 처리하는 라이브러리를 만드는 아이디어를 가지고있었습니다. 로컬 컴퓨터에서 adb를 수행하거나 동일한 API를 사용하여 ssh (키 교환 설정 사용)를 통해 원격 컴퓨터에서 수행 할 수 있습니다. adb 쉘 포워딩과 혼동하지 마십시오;).

그것의 아파치에서 2.0 라이센스 :`ADB.runShellCommand()는`당신`ADB.java`에서 https://github.com/lesavsoftware/rem-adb-exec

관련 문제