Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/365.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/226.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Runtime.getRuntime exec_Java_Android - Fatal编程技术网

Java Runtime.getRuntime exec

Java Runtime.getRuntime exec,java,android,Java,Android,我已经创建了一个类来处理android应用程序中的root命令,这个类基本上工作正常。我使用Runtime.getRuntime().exec(“su”)创建进程,然后使用DataOutputStream输入命令,并使用DataInputStream和不推荐使用的readLine从命令中获取数据。(我尝试过使用BufferedReader,但与此问题没有区别) 我的问题是,如果命令产生错误,应用程序将挂起。F.eks。如果我执行命令“[-f/test]&&md5sum/test”| | echo

我已经创建了一个类来处理android应用程序中的root命令,这个类基本上工作正常。我使用Runtime.getRuntime().exec(“su”)创建进程,然后使用DataOutputStream输入命令,并使用DataInputStream和不推荐使用的readLine从命令中获取数据。(我尝试过使用BufferedReader,但与此问题没有区别)

我的问题是,如果命令产生错误,应用程序将挂起。F.eks。如果我执行命令“[-f/test]&&md5sum/test”| | echo 0”,我将不会有任何问题“而且该文件不存在,我将不得不强制关闭该应用程序,因为它将一无所获。在本例中,解决方案有理由像第一个示例中那样检查文件,但并非所有情况都如此简单。问题可能会发生,当问题发生时,人们不应该强制关闭应用程序


是否有办法解决此问题?

您的应用程序可能挂起,因为您可能没有处理生成的进程生成的stderr/stdout。这背后的原因是派生进程的输出缓冲区非常小(通常只有几千字节)。一旦这些缓冲区已满,该进程将挂起,直到其缓冲区释放出足够的空间以继续写入输出文本。我怀疑您在运行第二个命令时遇到问题,因为第二个命令失败并生成大量控制台输出。您的子进程耗尽了缓冲区空间,然后尝试阻塞,直到有更多的空间可用,这是永远不会发生的

Runtime.getRuntime().exec()
返回
进程的实例
Process
对象有一个访问器方法(我相信它是
getInputStream()
),允许您使用它的stdout。您还需要对
getErrorStream()
执行相同的操作。通常,我获取
InputStream
,然后让一个单独的线程持续使用该
InputStream
中的数据,直到它关闭。您不需要对数据本身做任何事情,只需读取它即可。这将告诉底层进程,它可以清除其输出缓冲区,希望在它们满之前清除(从而导致进程阻塞)


另外,我对Android不是100%熟悉,但在纯java中,最好使用
ProcessBuilder
生成子
Process
实例。这是因为
ProcessBuilder
允许您在同一个流中组合子线程的stderr和stdout,这样您就可以通过从
process.getInputStream()返回的流中读取数据来在一个线程中使用这两个函数。但我还是遇到了一些问题

while ((line = buffer.readLine()) != null) {
    data = line;
}

if (data != null && data.contains("uid=0")) {
    return true;
}
这将提供与以前相同的问题。什么地方都没有。但是,如果我将代码更改为

while ((line = buffer.readLine()) != null) {
    if (data != null && data.contains("uid=0")) {
        return true;
    }
}
这很好用。这一过程将结束,并将回归现实。问题是为了使用它,我必须确切地知道返回数据是什么(我在这个测试方法中就是这样做的)。所以这不是解决办法

以下是整个测试方法

try {
    ProcessBuilder builder = new ProcessBuilder("su");
    builder.redirectErrorStream(true);

    Process process = builder.start();
    DataOutputStream output = new DataOutputStream(process.getOutputStream());
    InputStreamReader reader = new InputStreamReader(process.getInputStream());
    BufferedReader buffer = new BufferedReader(reader);

    output.writeBytes("id\n");
    output.flush();

    String line = null;
    String data = null;
    while ((line = buffer.readLine()) != null) {
        data = line;
    }

    if (data != null && data.contains("uid=0")) {
        return true;
    }

} catch(Throwable e) {
    Log.d(TAG, "Root access rejected [" + e.getClass().getName() + "] : " + e.getMessage());
}

return false;

你可能没有完全正确地阅读它的stdout/stderr流,凯,你能提供一个如何正确阅读的例子吗?哇,谢谢。这很有道理。我将研究一下这个问题,并看看ProcessBuilder。再次感谢:)好的,我提出了一个解决方案,接缝工作良好。在output.writeBytes(cmd+“\n”)之后,在output.flush()之前添加output.writeBytes(“echo-EOL:a00c38d8:EOL\n”)。然后在循环中,您可以执行while((line=buffer.readLine())!=null&&!(EOL:a00c38d8:EOL).equals(line))并在readLine挂起之前绘制最后一行,等待下一行进入。