Android 10三星S10执行/system/bin/ip neigh遇IOException及NPE问题求助
首先,你的问题包含两个核心层面:执行/system/bin/ip neigh时抛出的IOException,以及后续因reader未初始化导致的NullPointerException。我们先解决NPE的即时问题,再深挖根本原因。
一、先修复NullPointerException(即时止损)
你的finally块直接调用reader.close(),但如果runtime.exec()抛出异常,reader根本没被初始化,就会触发NPE。最简单的修复是增加空判断,或者更推荐使用Java 7+的try-with-resources语法——它会自动关闭资源,无需手动处理finally,代码更简洁安全:
Runtime runtime = Runtime.getRuntime(); // 使用try-with-resources自动管理BufferedReader try (BufferedReader reader = new BufferedReader( new InputStreamReader( runtime.exec("/system/bin/ip neigh").getInputStream() ) )) { String line; while ((line = reader.readLine()) != null) { doMyStuff(); } } catch (Exception e) { e.printStackTrace(); }
如果你坚持保留原有代码结构,也可以在finally里加空判断:
finally { if (reader != null) { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } }
二、解决/system/bin/ip执行失败的根本原因
针对Android 10的Galaxy S10出现的IOException: error=375259648, Exec failed,我们可以从以下几个方向排查和解决:
1. 确认ip工具的实际路径
三星One UI这类定制ROM可能调整了系统工具的位置,ip可能不在/system/bin/,而是在/system/xbin/或其他路径。你可以先在该设备上通过ADB shell执行which ip确认实际路径,再替换代码中的路径。
更稳妥的方式是不写绝对路径,直接执行ip neigh,让系统通过PATH环境变量自动查找,同时使用字符串数组的重载方法避免命令解析问题:
Process mIpAddrProcess = runtime.exec(new String[]{"ip", "neigh"});
2. 排查SELinux权限限制
Android 10对普通应用执行系统shell命令有更严格的SELinux限制,三星的定制固件可能进一步收紧了权限。你可以做以下验证:
- 在ADB shell中临时关闭SELinux(执行
setenforce 0),如果此时命令能正常执行,说明是SELinux权限问题。这种情况下,普通应用很难绕过限制,建议换用系统API实现需求。 - 检查应用的
targetSdkVersion:如果版本≥29,Android 10的隔离机制会阻止部分系统命令执行,临时降低到28测试可以验证是否是版本限制导致的(不推荐作为长期方案)。
3. 替换为Android原生API获取邻居信息
调用shell命令的兼容性极差,更推荐使用Android官方API获取邻居(ARP)信息,完全避免依赖系统工具:
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); Network activeNetwork = cm.getActiveNetwork(); LinkProperties linkProperties = cm.getLinkProperties(activeNetwork); if (linkProperties != null) { List<NeighborInfo> neighborInfos = linkProperties.getAllNeighborInfo(); for (NeighborInfo info : neighborInfos) { // 处理邻居信息,比如获取IP地址、硬件地址 doMyStuffWithNeighbor(info); } }
注意:LinkProperties.getAllNeighborInfo()在Android 8.0+可用,需要申请ACCESS_NETWORK_STATE权限。这个方法的兼容性远优于shell命令,也不会触发SELinux限制。
4. 其他可能的限制
Android 10中普通应用无法访问/dev下部分设备节点,而ip neigh需要读取ARP缓存,可能依赖这些节点。如果上述方法都无效,仅在root设备上可以尝试用su包装命令,但这显然不适合面向普通用户的应用。
内容的提问来源于stack exchange,提问作者abhilash anand

