2012-04-09 39 views
6

Đối với cuộc sống của tôi, tôi không thể tải ứng dụng của mình để nhận phản hồi từ quá trình gọi busybox từ bên trong su shell.Lấy đầu ra từ lệnh busybox trong ứng dụng Android

Tôi đã thử ba phương pháp khác nhau, cũng như thử kết hợp cả ba để làm việc, nhưng tôi không bao giờ có được kết quả từ bất kỳ thứ gì bằng cách sử dụng busybox, chỉ còn lại các lệnh.

Để cụ thể hơn, tôi có thể làm cho nó trả về các lệnh như "ls/data" và "cat suchandsuch.file", nhưng bất kỳ thứ gì bắt đầu bằng "busybox" (nghĩa là busybox mount, busybox free) sẽ không hiển thị bất cứ thứ gì .

Đây là phương pháp mà có sự gần gũi nhất đối với tôi, mã này làm việc với "ls/dữ liệu", nhưng không phải là "busybox miễn phí"

này người ta sẽ chạy lệnh (đối với hầu hết các phần), và trở lại một chuỗi rỗng thay vì lặp vô tận từ đầu vào.

 Process p; 
     try { 
      p = Runtime.getRuntime().exec(new String[]{"su", "-c", "/system/bin/sh"}); 
     DataOutputStream stdin = new DataOutputStream(p.getOutputStream()); 
     stdin.writeBytes("ls /data\n"); 
     DataInputStream stdout = new DataInputStream(p.getInputStream()); 
     byte[] buffer = new byte[4096]; 
     int read = 0; 
     String out = new String(); 
     while(true){ 
      read = stdout.read(buffer); 
      out += new String(buffer, 0, read); 
      if(read<4096){ 
       break; 
      } 
     } 
     Toast.makeText(getApplicationContext(), out, Toast.LENGTH_SHORT).show(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

Bánh mì nướng gần phía dưới hiển thị mọi thứ từ "ls/data", nhưng khi được đổi thành bất kỳ thứ gì cho busybox, trống hoặc không.

Tôi cũng đã thử cả hai tính năng này, nhưng chưa bao giờ chúng hoạt động. (Tôi đã chuyển quá trình cho họ sau khi lệnh được chạy.)

Cả hai điều này sẽ luôn dẫn đến ứng dụng bị đóng băng ngay khi bạn nhấn nút cho phương pháp.

String termReader(Process process){ 
    BufferedReader reader = new BufferedReader(
     new InputStreamReader(process.getInputStream())); 
    try { 

    int i; 
    char[] buffer = new char[4096]; 
    StringBuffer output = new StringBuffer(); 
    while ((i = reader.read(buffer)) > 0) output.append(buffer, 0, i); 
    reader.close(); 
    return output.toString(); 
    } catch (IOException e) { 
    e.printStackTrace(); 
    return e.getMessage(); 
    } 
} 



String processReader(Process process){ 
    InputStream stdout = process.getInputStream(); 
    byte[] buffer = new byte[1024]; 
    int read; 
    String out = new String(); 
    while(true){ 
     try { 
      read = stdout.read(buffer); 
     out += new String(buffer, 0, read); 
     if(read<1024){ 
      break; 
     } 
     } catch (IOException e) { 
      e.printStackTrace(); 

     } 
    } 
    return out; 
} 

Theres không có đống dấu vết để làm việc với, do đó im bắt đầu để có được một chút bối rối.

Chỉnh sửa với mã được đề xuất bên dưới, uhm, bên dưới: D Tôi đã thay đổi nó một chút để làm cho nó trở thành một thao tác chạy trên giấy phép để xử lý sự cố và thử nghiệm dễ dàng hơn.

Điều này cũng đóng băng khi nó cố gắng đọc luồng đầu vào, và nếu tôi gọi stdin.writeBytes ("exit \ n") trước khi cố gắng đọc luồng nó cho tôi câu trả lời trống từ đóng terminal, nếu tôi gọi nó sau đó, nó lặp đi lặp lại vô tận.

 void Run() { 
       String command = "busybox traceroute\n"; 



     StringBuffer theRun = null; 
     try { 
      Process process = Runtime.getRuntime().exec("su"); 
      DataOutputStream stdin = new DataOutputStream(process.getOutputStream()); 
      stdin.writeBytes(command); 
      BufferedReader reader = new BufferedReader(
        new InputStreamReader(process.getInputStream())); 
      int read; 
      char[] buffer = new char[4096]; 
      StringBuffer output = new StringBuffer(); 
      while ((read = reader.read(buffer)) > 0) { 
       theRun = output.append(buffer, 0, read); 
      } 
      reader.close(); 
      process.waitFor(); 

     } catch (IOException e) { 
      throw new RuntimeException(e); 
     } catch (InterruptedException e) { 
      throw new RuntimeException(e); 
     } 
     Toast.makeText(getApplicationContext(), theRun, Toast.LENGTH_SHORT).show(); 
    } 

Dường như nó bỏ qua dòng đầu tiên (dòng thông tin busybox bạn nhận được mỗi khi bạn gọi lệnh) và không bắt phần còn lại của dữ liệu. Ive đã cố gắng tất cả các biến thể tôi có thể nghĩ ra để có được điều này làm việc ngay:/

Nếu ai ấy có một số cái nhìn sâu sắc về vấn đề này, tôi muốn được rất apreciative :)

Trả lời

1

Tôi đã tìm thấy một loại một workaround cho điều này .

Trước hết, các lệnh chạy được liên kết đến busybox trong trường hợp của tôi sẽ không bao giờ trả về kết quả đầu ra thông qua InputStream của họ, cho dù tôi đã thử phương thức nào (Và tôi đã thử ALOT lol).

Đây là những gì tôi phát hiện ra tôi có thể làm. Đó là một chút tẻ nhạt, và không cung cấp cho bạn sản lượng đầy đủ, nhưng nếu bạn muốn một cái gì đó để dựa vào việc một lệnh bắn ra đúng cách (trong trường hợp của tôi, ứng dụng của tôi sẽ không hoạt động đúng nếu tôi không thể so sánh tất cả mọi thứ chạy như thế nào.)

Bạn không thể lấy đầu vào từ quá trình này, nhưng bạn CÓ THỂ nhận giá trị thoát nếu bạn làm việc đúng :) hoạt động cho bất kỳ thứ gì không cung cấp cho bạn phản hồi phức tạp (như sử dụng mèo trên một tệp lớn)

sự khác biệt giữa hai là dễ tìm, ví dụ:

command = "cat /sys" // works, exits with 1 

command = "cat /init.rc" doesnt work, exits with 0 

đây là làm thế nào tôi thiết lập nó để làm việc một cách dễ dàng. Chạy các lệnh như bình thường bằng cách sử dụng phương pháp được cung cấp bởi MasterJB:.

  Process p; 
     try { 
      p = Runtime.getRuntime().exec(new String[]{"su", "-c", "/system/bin/sh"}); 
     DataOutputStream stdin = new DataOutputStream(p.getOutputStream()); 
     stdin.writeBytes(command); 
     stdin.writeBytes("echo $?\n"); 

     DataInputStream stdout = new DataInputStream(p.getInputStream()); 
     byte[] buffer = new byte[4096]; 
     int read = 0; 
     String out = new String(); 
     while(true){ 
      read = stdout.read(buffer); 
      out += new String(buffer, 0, read); 
      if(read<4096){ 
       break; 
      } 

        // here is where you catch the error value 

           int len = out.length(); 
     char suExitValue = out.charAt(len-2); 
     Toast.makeText(getApplicationContext(), String.valueOf(suExitValue), Toast.LENGTH_SHORT).show(); 


        return0or1(Integer.valueOf(suExitValue), command); // 0 or 1 Method 

        // end catching exit value        

     } 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

Tôi cũng tìm thấy nó dễ dàng hơn để thực hiện một "0 hoặc 1" phương pháp để trả lại những gì đã xảy ra, trong ví dụ này nó bắn như một bánh mì nướng. bạn cũng có thể muốn kiểm tra nếu char là accualy một số nguyên, như một số lệnh cho không có giá trị xuất cảnh những gì bao giờ hết (wierd, tôi biết.Một ví dụ là ls/sys, điều này trả về một giá trị xuất cảnh trống khi chạy qua một thiết bị đầu cuối su.)

String return0or1 (int returnValue, String command){ 
    String message = command + " - Cannot get return value."; 

    if (returnValue == 0){ 
     message = command + " - successful."; 
     return message; 
    } 
    if (returnValue == 1){ 
     message = command + " - failed."; 
     return message; 
    } 
    return message; 
} 

với một chút nghiên cứu bạn có thể phù hợp với chỉ là về bất kỳ giá trị xuất cảnh với câu trả lời thích hợp, chỉ cần gotta chụp chúng ngay :)

những phương pháp trở chỉ dù lệnh chạy (0), nhưng nếu nó nhận được mã thoát kép hoặc gấp ba, chữ số cuối có thể bằng 0 khi nó không thành công (ví dụ khi giá trị thoát là 10), vì vậy điều này sẽ hoạt động trong hầu hết các trường hợp, nhưng cần được mở rộng để nhận giá trị gấp đôi và gấp ba lần.

3

Đây là giải pháp nhanh chóng ... Đây là lớp tiện ích mà tôi đã tạo chỉ dành cho việc này. Bạn có thể sử dụng shell gốc, một shell gốc nếu thiết bị được root, hoặc thiết lập một shell tùy chỉnh. Đây rồi.

https://github.com/jjNford/android-shell

+0

Đây là vàng! Cảm ơn bạn! –

Các vấn đề liên quan