Android:如何处理 Runtime.getRuntime().exec() 在 root phone 上调用 dumpsys 的输出

Android: How to process output of Runtime.getRuntime().exec() calling dumpsys on rooted phone

我正在对有根 phone 进行小型概念验证,它依赖于能够读取 dumpsys 输出。

如果我像这样在我的(rooted)phone 运行 Android 11 上调用 dumpsys,使用 adb:

adb shell dumpsys telephony.registry | grep "mCi="

我得到了很长的打印输出。 grep 过滤包含手机信号塔 ID 的线路,但这在这里不重要(这只是一个例子)。现在我试图在一个非常简单的应用程序中执行相同的命令,并记录其输出,如下所示:

private  fun test() {
       
        try {
            val process = Runtime.getRuntime().exec("su dumpsys telephony.registry | grep \"mCi=\"")
            val bufferedReader = BufferedReader(InputStreamReader(process.inputStream))
            val string = bufferedReader.readText()
            Timber.d("output: $string")
            bufferedReader.close() // do I need this?
        } catch (e: IOException) {
            // handle Exception
        }
    }

我根本没有输出(string 长度为 0)。如果我用这样简单的东西替换我的进程命令:Runtime.getRuntime().exec("echo 'abcde'") 输出按预期记录 (output: 'abcde')。

我还尝试通过附加 --max-count=1 来缩短可能的输出,以防出现问题,让 grep 只输出第一个找到的行。同样,它使用 adb 工作,在代码中不起作用。

我做错了什么?

(我正在使用 Timber 来打印我的日志,如果有人不知道示例中的那一行是什么的话。)

您应该做的第一件事是记录也可用于您的进程的 stderr 流。这将为您提供有关命令错误的信息。

您的命令未被正确处理,因为它被视为一个命令。 .

中解释了原因

解决方案是使用 String[] 作为 exec 的参数,并使用 shell 显式执行命令。我写了一些代码来执行你的命令,但它在无根设备上的 Java 中。尽管如此,它仍会生成输出并且 grep 可以正常工作。

String[] arrayCommand = {"sh", "-c","dumpsys telephony.registry | grep \"permission\""};
            
Runtime r = Runtime.getRuntime();
Process process = r.exec(arrayCommand);

String stdoutString = convertInputStreamToString(process.getInputStream());
String stderrString = convertInputStreamToString(process.getErrorStream());