2015-04-01 37 views
2

我有一個根應用程序應該在執行期間的某個點捕獲屏幕。爲了做到這一點,我與Android外殼交互使用下面的代碼:確保從InputStream讀取正確的數據

private static Process su = Runtime.getRuntime().exec("su"); 
private static DataOutputStream outputStream = new DataOutputStream(su.getOutputStream()); 
private static DataInputStream inputStream = new DataInputStream(su.getInputStream()); 

private void CaptureScreen() { 
    outputStream.writeBytes("/system/bin/screencap -p\n"); 
    outputStream.flush(); 
    Bitmap bitmap = BitmapFactory.decodeStream(inputStream); 
    //outputStream.writeBytes("echo test\n"); 
    //outputStream.flush(); 
} 

它正常工作,甚至當我把它稱爲多次,但此刻我發出產生之間的外殼輸出的虛擬指令CaptureScreen調用,BitmapFactory.decodeStream失敗。考慮到這一點,我有幾個問題:

  • 我想這是因爲InputStream中內的數據是沒有 不再是單純的與圖像數據有關。由於運行時間是單個 實例(如here),我再次假設其他 進程也可以在我的InputStream中的 實時系統中引入它們的輸出。我如何確保只從 InputStream獲取我需要的數據?
  • 爲什麼CaptureScreen在被多次調用時工作正常?如何 BitmapFactory.decodeStream管理從 InputStream獲取最後一張圖片?成功後是否「消耗」相關數據? 它是否從InputStream搜索最後的圖像數據?如果是這樣,爲什麼當 InputStream中的圖像數據之前存在不相關的數據時,它會失敗 ?

我知道我可以通過將圖像寫入文件然後從那裏讀取來解決此問題,但是我希望避免I/O操作而改用性能。

回答

1

這個玩弄了一段時間後,我找到了答案,以我自己的問題:

  • 雖然運行時是單實例,執行代碼,就可以開始在自己的一個新的進程。與此進程相關的輸入和輸出流只能由此進程寫入/讀取(除非另一進程專門將其流重定向到此進程,這在我的情況中極不可能)。
  • 輸入流的內容在讀取時確實「消耗殆盡」,因此多次調用此函數全部寫入/讀取圖像數據。使用與圖像無關的數據「污染」進程的輸入流會破壞decodeStream的功能。

另請注意,「su」不是結束的命令。直到被調用纔會終止。下面是修改後的類我在我的代碼中使用:

public class BitmapScreencap { 
    public final static BitmapScreencap Get = new BitmapScreencap(); 
    private BitmapScreencap() { } 
    public Bitmap Screen() { 
     try { 
      Process process = Runtime.getRuntime().exec("su"); 
      OutputStreamWriter outputStream = new OutputStreamWriter(process.getOutputStream()); 
      outputStream.write("/system/bin/screencap -p\n"); 
      outputStream.flush(); 
      Bitmap screen = BitmapFactory.decodeStream(process.getInputStream()); 
      outputStream.write("exit\n"); 
      outputStream.flush(); 
      outputStream.close(); 
      return screen; 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     return null; 
    } 
} 

而且它可以從任何地方你的項目中被稱爲:

BitmapScreencap.Get.Screen(); 
0

如何確保只從InputStream獲取所需的數據?

至少你可以檢查爲什麼CaptureScreen正常工作時,多次調用過程

的exitValue?

它只是讀取流,直到讀取結果爲-1。當您發送「/ system/bin/screencap -p \ n」進行處理時,InputStream會再次開始返回新數據。