确保从InputStream读取正确的数据

时间:2015-04-01 15:49:36

标签: java android

我有一个根应用程序,它应该在执行期间的某个时刻捕获屏幕。为了实现这一点,我使用以下代码与Android shell进行交互:

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调用之间产生shell输出的伪命令时,BitmapFactory.decodeStream失败。考虑到这一点,我有几个问题:

  • 我认为这是因为InputStream中的数据为no 更长时间与图像数据完全相关。由于运行时是单一的 实例(提到here),我再次假设其他 进程也可以在我的InputStream中引入它们的输出 现场系统。我怎样才能确保只从中获取所需的数据 的InputStream?
  • 为什么CaptureScreen多次调用时可以正常工作?怎么样 BitmapFactory.decodeStream设法从中获取最后一个图像 的InputStream?是否"消费"成功时的相关数据?是否 它从InputStream中搜索最后的图像数据?如果是这样,为什么呢 在图像数据之前存在无关数据时失败 的InputStream?

我知道我可以通过将图像写入文件然后从那里读取来解决这个问题,但我希望避免I / O操作以支持性能。

2 个答案:

答案 0 :(得分:2)

在玩了一段时间之后,我找到了自己问题的答案:

  • 虽然运行时是单个实例,但在其上执行代码会自行启动一个新进程。与此过程相关的输入和输出流只能由此过程写入/读取(除非另一个过程专门将其流重定向到此过程,这在我的情况下极不可能)。
  • 输入流的内容在读取时确实被“消耗”,因此多次调用该函数完全写入/读取图像数据。使用与图像无关的数据“污染”流程的输入流会破坏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();

答案 1 :(得分:0)

  

如何确保只从InputStream中获取所需的数据?

至少你可以检查进程的exitValue

  

为什么CaptureScreen多次调用时才能正常工作?

它只是读取流,直到读取结果为-1。当您发送“/ system / bin / screencap -p \ n”进行处理时,InputStream会再次开始返回新数据。