2015-04-01 2 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 возникают нерелевантные данные?

Я знаю, что могу обойти эту проблему, записав изображение в файл, а затем прочитал его оттуда, но я хотел бы избежать операций ввода-вывода в пользу производительности.

ответ

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?

По крайней мере, вы можете проверить exitValue Процесса

Почему CaptureScreen работать корректно при вызове несколько раз?

Он просто считывает поток до получения -1 в результате чтения. Когда вы отправляете «/ system/bin/screencap -p \ n» для обработки, InputStream начинает возвращать новые данные снова.

Смежные вопросы