从Java代码运行Android Shell命令返回空输出

问题描述

我正在尝试从Java代码运行shell命令(netstat -an -ptcat /proc/net/tcp),以便检查Android设备上是否打开了TCP端口。该设备是非root用户的(在root用户的设备上,这没有问题)。

我发现有两种类型可以从Java代码调用Shell命令。

获取我尝试使用的过程对象:

  1. Runtime.getRuntime().exec(command);

  2. new ProcessBuilder().command("sh","-c",command).start();

稍后,我正在处理InputStream对象并输出结果。

问题是cat /proc/net/tcp命令的结果为空字符串,而netstat -an -pt的结果为:

Active Internet connections (w/o servers) Proto Recv-Q Send-Q Local Address           Foreign Address         State       Active UNIX domain sockets (w/o servers) Proto RefCnt Flags    Type       State       I-Node Path

...这是netstat命令的标题

直接在Android Shell中运行上述命令时(通过在无根设备中打开adb shell),一切正常,并且命令的输出显示在控制台中。

我怀疑权限存在一些问题,因为这在有根设备上有效。

运行以下命令之一时的Logcat输出

 W cat     : type=1400 audit(0.0:3***4): avc: denied { read } for name="tcp" dev="proc" ino=4*2653***6 scontext=u:r:untrusted_app:s*:c**9,c**7,c5**,c*6* tcontext=u:object_r:proc_net_tcp_udp:s0 tclass=file permissive=0

如果这是权限问题,是否还有另一种方法可以通过我的应用程序读取非root用户的Android设备上当前打开的TCP端口?

解决方法

我部分找到了足够的答案。基本上,问题首先在于权限。

in documentation所述:从Android版本10 /proc/net开始,文件系统受到限制,无法访问。不幸的是(我应该说幸运的)我的无根测试设备是Android 10,因此进程对象将返回状态1,因为它没有读取/proc/net文件系统的权限。

我在Android 8上测试了相同的代码,并且一切正常。

我仍然没有弄清楚如何访问使用的端口,但是我将研究先前链接的文档中提到的NetworkStatsManagerConnectivityManager类。