Android root设备调用Runtime.exec执行dumpsys命令无输出如何解决
问题根因
Runtime.getRuntime().exec()本身不支持解析shell语法,包括管道符|、引号转义、重定向等逻辑,你传入的带管道的完整命令会被当成su的单一参数执行,系统无法识别该指令,自然没有输出。你之前执行echo能成功是因为这是无特殊语法的单一命令,不需要shell参与解析。- 你没有等待进程执行完成就直接读取输入流,可能进程还未完成输出就读取结束,导致拿到空字符串。同时你没有读取进程的错误流,无法捕获执行过程中的报错信息,很难排查问题。
- 部分root环境下直接把完整命令拼在
su后的调用方式本身不兼容,需要显式启动root shell再执行命令。
正确实现方案
先启动root权限的shell进程,再把需要执行的命令写入shell的输入流执行,示例代码如下:
private fun test() { try { // 启动root权限的shell val process = Runtime.getRuntime().exec("su") val outputStream = DataOutputStream(process.outputStream) // 写入要执行的命令,加\n表示触发执行,最后加exit表示执行完退出shell outputStream.writeBytes("dumpsys telephony.registry | grep \"mCi=\"\n") outputStream.writeBytes("exit\n") outputStream.flush() // 等待进程执行完成,确认执行结果 val exitCode = process.waitFor() if (exitCode == 0) { // 读取正常输出 BufferedReader(InputStreamReader(process.inputStream)).use { reader -> val result = reader.readText() Timber.d("output: $result") } } else { // 读取错误信息排查问题 BufferedReader(InputStreamReader(process.errorStream)).use { reader -> val errorMsg = reader.readText() Timber.d("执行错误: $errorMsg") } } outputStream.close() process.destroy() } catch (e: Exception) { e.printStackTrace() } }
补充说明
- 关于你问的流关闭问题:所有IO流使用完必须主动关闭避免资源泄漏,上面代码里用了Kotlin的
use扩展方法,会在执行结束后自动关闭流,不需要手动写close逻辑。 - 如果想要简化写法,也可以尝试使用
su -c参数:Runtime.getRuntime().exec("su -c \"dumpsys telephony.registry | grep 'mCi='\""),但这种写法在不同的su实现(Magisk、SuperSU等)上兼容性不一致,更推荐上面显式写入命令的方案。 - 要提前确认你已经给当前应用授予了root权限,部分root管理工具默认会拦截应用的root申请。
内容的提问来源于stack exchange,提问作者michpohl
相关产品推荐
相关产品推荐

