持续读取程序的输出并在别处显示该数据
Continuously reading output from program and displaying that data elsewhere
我正在尝试从输出数据的程序中读取数据,然后在我的 GUI 上连续显示该数据。具体来说,我已将旋转编码器作为输入设备连接到我的 Raspberry Pi 3,它在 Android OS (4.4 - KitKat) 上运行。当我与旋转编码器进行物理交互时,以及当我在终端的 /dev/input/eventX 中从工具 "getevent" 读取数据时,我看到数据随着旋转编码器的移动而弹出。
我正在尝试读取输出的数据,并且几乎立即读取该数据并将其实时显示在我的 GUI 上(或以非常小的延迟)。
所以我尝试做的如下:
1) 在我的 GetEventRecorder class 中,我写入以打开 getevent 工具,然后从中读取输出。我使用 scheduleAtFixedRate 重复此过程(延迟很小)。该工具在我关闭之前一直保持打开状态。我相信我需要关闭该工具才能从中读取输出。所以我关闭它,打算马上再打开它。我认为这可能会导致我在下面描述的部分问题。
2) 在我的 MainActivity() 中,我有一个定期更新(小延迟)的 textView,它从第 1 部分读取数据。我在 RunThread 中执行此操作。
问题:只有在工具关闭后,我才能看到屏幕上显示的数据。但是,我似乎在关闭之前看不到数据(我认为这是正常的)。但是,此后我似乎无法读取任何新输入,只能读取工具关闭前的输入。但我想继续不断地阅读数据,但似乎无法做到这一点。请在下面找到我的代码。由于这是我的第一个post,请提出任何问题,以便我进一步澄清我的情况等
主要活动:
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
TextView textElement;
private String myOutput;
private GetEventRecorder getEventRecorder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textElement = (TextView) findViewById(R.id.firstTextView);
getEventRecorder = new GetEventRecorder();
init_all();
runThread();
}
public void init_all() {
getEventRecorder.start();
}
private void runThread() {
new Thread() {
public void run() {
while (true) {
try {
runOnUiThread(new Runnable() {
@Override
public void run() {
myOutput= getEventRecorder.logGetEventData();
textElement.append(myOutput);
}
});
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
}
获取事件记录器:
import java.io.OutputStream;
import java.util.Timer;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.TimerTask;
public class GetEventRecorder {
private GetEventRecorder mRecorder = null;
Timer timer;
String err = "initial";
// active su session
private Process mProcess;
// Byte Writer
private DataOutputStream outputStream;
private BufferedReader br;
private StringBuilder text = new StringBuilder();
private int i = 0;
{
try {
mProcess = Runtime.getRuntime().exec("su");
outputStream = new DataOutputStream(mProcess.getOutputStream());
String comm1 = "getevent -c 2 /dev/input/event1";
String newLine = "\n";
outputStream.writeBytes(comm1);
outputStream.writeBytes(newLine);
} catch (IOException e) {
e.printStackTrace();
}
}
public void start() {
try {
timer = new Timer();
timer.scheduleAtFixedRate(new GetEventRecorder.RecorderTask(), 0,
1000);
} catch (Exception e) {
}
}
public void stop() {
if (mRecorder != null) {
mRecorder.stop();
mRecorder = null;
timer.cancel();
}
}
private class RecorderTask extends TimerTask {
@Override
public void run() {
try {
String close = "^C";
outputStream.writeBytes(close);
outputStream.flush();
br = new BufferedReader(new InputStreamReader(mProcess.getInputStream()));
String line;
if (br != null) {
if (br.ready()) {
while ((line = br.readLine()) != null) {
text.append(line);
text.append("\n");
}
}
}
} catch (Exception e) {
err = "error_1";
}
}
}
public String logGetEventData() {
if (text != null) {
String retour = text.toString();
return retour;
} else {
return "err_log";
}
}
}
我对你的术语感到困惑,因为你指的是 "opening the getevent file"。我相信 getevent 是 Android 上的一个工具(一个程序)。参见 https://android.googlesource.com/platform/system/core.git/+/android-4.2.2_r1/toolbox/getevent.c and https://source.android.com/devices/input/getevent
根据您的代码,您似乎正在创建一个超级用户 shell 作为子进程,运行 通过向子进程发送命令(它将继续创建 运行 getevent =42=]),然后循环发送^C给子进程。
你把-c 2
传给getevent,这意味着它会读取两个值然后退出。
^C
到 shell 进程终止进程。所以你并没有真正关闭文件。
您生成的 shell 不是交互式的,因此作业控制功能可能未启用。所以 ^C
可能无论如何都不起作用。 (不是 100% 确定这个。)
你不会在任何地方重新运行 getevent
,所以如果它因任何原因停止输出(例如前面的列表),你将不会看到更多。
因此,要按照您的方式实现您想要的效果,您需要重生 getevent。这就是您现在静态初始化块中的代码。
正如进一步的评论一样,这对于您正在做的事情来说似乎有些矫枉过正。你真的想直接从事件设备中读取。您似乎使用这种方法解决的唯一问题可能是设备文件的权限。
我正在尝试从输出数据的程序中读取数据,然后在我的 GUI 上连续显示该数据。具体来说,我已将旋转编码器作为输入设备连接到我的 Raspberry Pi 3,它在 Android OS (4.4 - KitKat) 上运行。当我与旋转编码器进行物理交互时,以及当我在终端的 /dev/input/eventX 中从工具 "getevent" 读取数据时,我看到数据随着旋转编码器的移动而弹出。
我正在尝试读取输出的数据,并且几乎立即读取该数据并将其实时显示在我的 GUI 上(或以非常小的延迟)。
所以我尝试做的如下:
1) 在我的 GetEventRecorder class 中,我写入以打开 getevent 工具,然后从中读取输出。我使用 scheduleAtFixedRate 重复此过程(延迟很小)。该工具在我关闭之前一直保持打开状态。我相信我需要关闭该工具才能从中读取输出。所以我关闭它,打算马上再打开它。我认为这可能会导致我在下面描述的部分问题。
2) 在我的 MainActivity() 中,我有一个定期更新(小延迟)的 textView,它从第 1 部分读取数据。我在 RunThread 中执行此操作。
问题:只有在工具关闭后,我才能看到屏幕上显示的数据。但是,我似乎在关闭之前看不到数据(我认为这是正常的)。但是,此后我似乎无法读取任何新输入,只能读取工具关闭前的输入。但我想继续不断地阅读数据,但似乎无法做到这一点。请在下面找到我的代码。由于这是我的第一个post,请提出任何问题,以便我进一步澄清我的情况等
主要活动:
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
TextView textElement;
private String myOutput;
private GetEventRecorder getEventRecorder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textElement = (TextView) findViewById(R.id.firstTextView);
getEventRecorder = new GetEventRecorder();
init_all();
runThread();
}
public void init_all() {
getEventRecorder.start();
}
private void runThread() {
new Thread() {
public void run() {
while (true) {
try {
runOnUiThread(new Runnable() {
@Override
public void run() {
myOutput= getEventRecorder.logGetEventData();
textElement.append(myOutput);
}
});
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
}
获取事件记录器:
import java.io.OutputStream;
import java.util.Timer;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.TimerTask;
public class GetEventRecorder {
private GetEventRecorder mRecorder = null;
Timer timer;
String err = "initial";
// active su session
private Process mProcess;
// Byte Writer
private DataOutputStream outputStream;
private BufferedReader br;
private StringBuilder text = new StringBuilder();
private int i = 0;
{
try {
mProcess = Runtime.getRuntime().exec("su");
outputStream = new DataOutputStream(mProcess.getOutputStream());
String comm1 = "getevent -c 2 /dev/input/event1";
String newLine = "\n";
outputStream.writeBytes(comm1);
outputStream.writeBytes(newLine);
} catch (IOException e) {
e.printStackTrace();
}
}
public void start() {
try {
timer = new Timer();
timer.scheduleAtFixedRate(new GetEventRecorder.RecorderTask(), 0,
1000);
} catch (Exception e) {
}
}
public void stop() {
if (mRecorder != null) {
mRecorder.stop();
mRecorder = null;
timer.cancel();
}
}
private class RecorderTask extends TimerTask {
@Override
public void run() {
try {
String close = "^C";
outputStream.writeBytes(close);
outputStream.flush();
br = new BufferedReader(new InputStreamReader(mProcess.getInputStream()));
String line;
if (br != null) {
if (br.ready()) {
while ((line = br.readLine()) != null) {
text.append(line);
text.append("\n");
}
}
}
} catch (Exception e) {
err = "error_1";
}
}
}
public String logGetEventData() {
if (text != null) {
String retour = text.toString();
return retour;
} else {
return "err_log";
}
}
}
我对你的术语感到困惑,因为你指的是 "opening the getevent file"。我相信 getevent 是 Android 上的一个工具(一个程序)。参见 https://android.googlesource.com/platform/system/core.git/+/android-4.2.2_r1/toolbox/getevent.c and https://source.android.com/devices/input/getevent
根据您的代码,您似乎正在创建一个超级用户 shell 作为子进程,运行 通过向子进程发送命令(它将继续创建 运行 getevent =42=]),然后循环发送^C给子进程。
你把
-c 2
传给getevent,这意味着它会读取两个值然后退出。^C
到 shell 进程终止进程。所以你并没有真正关闭文件。您生成的 shell 不是交互式的,因此作业控制功能可能未启用。所以
^C
可能无论如何都不起作用。 (不是 100% 确定这个。)你不会在任何地方重新运行
getevent
,所以如果它因任何原因停止输出(例如前面的列表),你将不会看到更多。
因此,要按照您的方式实现您想要的效果,您需要重生 getevent。这就是您现在静态初始化块中的代码。
正如进一步的评论一样,这对于您正在做的事情来说似乎有些矫枉过正。你真的想直接从事件设备中读取。您似乎使用这种方法解决的唯一问题可能是设备文件的权限。