在Android开发中,检测设备和服务器之间的网络连通性是一项常见且重要的任务。利用Ping命令,可以快速诊断网络问题并确保应用的网络请求流畅。
简介
ping(Packet Internet Grouper)是一种因特网包探测器,用于测试网络连接量的程序,Ping是工作在TCP/IP网络体系结构中应用层的服务命令,主要是向特定的目的服务器发送ICMP(Internet Control Message Protocol 因特网报文控制协议)Echo 请求报文,测试目的站是否可达及了解其有关状态。
检测网络必要性
最常见的现象是,假如我们用手机连接一个路由器,路由器没有插网线,这时如果我们使用Android常用的api,检测网络是否连接,判断是否可用,毫无疑问,最后返回的都是true,当我们请求接口的时候可能就是无法访问。在日常工作中,这种问题也会经常碰到,当我们一切准备就绪,提交给测试,结果他说没法加载数据,其实就是网络不好,数据没请求成功而已,所以检测网络状态,ui层给出提示是很有必要的。
Android执行Ping命令
在Android常用的有两种方式执行ping命令使用Runtime.getRunTime().exec(),或者使用ProcessBuilder,这里以第一种方式为例:
假如我们现在ping谷歌服务器的连通性:
Runtime.getRuntime().exec("www.google.com")
我们也可以加入参数比如发送的数据,超时时间等
ping -c 3 -i 2 -s 100 -t 64 -w 10 -q www.google.com
上面这行命令的参数含义:
ping: 是一个常用的网络工具,它用来测试另一台计算机是否可通过IP网络到达。
-c 3: 指定发送的回显请求数量为3次。
-i 2: 设置每次ping请求之间的间隔时间为2秒。
-s 100: 设置每次ping发送的数据包大小为100字节。
-t 64: 设置Time-to-Live(TTL)为64。TTL是数据包在网络中可以经过的最大路由器数目;每当数据包经过一个路由器,其值就减1,当值降至0时,该数据包将被丢弃。
-w 10: 设置总的超时时间为10秒。这指的是ping命令执行的总时长,而不是单次ping请求的超时时间。
-q: 安静输出。不显示每次回显请求的详细信息,只在摘要中打印最小、最大以及 平均延迟。
www.google.com: 这是要测试连接的目标主机名称或IP地址。
将上述选项结合在一起,这条命令的意思是通过向www.google.com发送3个数据包,每个数据包的大小为100字节,那每隔2秒发送一个,TTL值设置为64,并且将整个命令的执行时间限制在10秒内,执行过程中不显示详细的ping请求回应的数据,只在最后提供汇总信息。
完整示例
public class NetWorkCheck implements Runnable {private static final String TAG = "NetWorkCheck";private final String mIpAddress;private final Consumer<NetworkSingle> mCallback;public NetWorkCheck(String ipAddress, Consumer<NetworkSingle> callback) {this.mIpAddress = ipAddress;this.mCallback = callback;}@Overridepublic void run() {try {ping();} catch (Exception e) {e.printStackTrace();}}private void ping() {String cmd = "";NetworkSingle single = NetworkSingle.NONE;BufferedReader in = null;//ping -c 3 -i 2 -s 100 -t 64 -w 10 -q www.google.comtry {cmd = "ping -c 3 -i 2 -s 100 -t 64 -w 10 -q " + mIpAddress;Log.d(TAG, cmd);Process myProcess = Runtime.getRuntime().exec(cmd);in = new BufferedReader(new InputStreamReader(myProcess.getInputStream()));String inputLine;while ((inputLine = in.readLine()) != null) {System.out.println("result= " + inputLine);// 3 packets transmitted, 3 received, 0% packet loss, time 4006ms// rtt min/avg/max/mdev = 51.957/62.180/74.437/9.289 msif (inputLine.contains("packet loss")) {int start = inputLine.indexOf("received,") + 10;int end = inputLine.indexOf("%");String packetLoss = inputLine.substring(start, end).trim();int packetLossValue = Integer.parseInt(packetLoss);if (packetLossValue == 0) {single = NetworkSingle.GREAT;} else if (packetLossValue < 30) {single = NetworkSingle.GOOD;} else if (packetLossValue < 50) {single = NetworkSingle.BAD;}}}System.out.println("Cannot reach " + mIpAddress);} catch (Exception e) {e.printStackTrace();} finally {if (in != null) {try {in.close();} catch (Exception e) {e.printStackTrace();}}}mCallback.accept(single);}}
定时检测
通过上面示例,知道了如何使用ping检测连通性,接下来就需要开启定时任务轮询检测,我通过android提供的ScheduledExecutorService,执行定时任务,示例如下:
public class GoogleNetTaskManager {private final ScheduledExecutorService executorService;public GoogleNetTaskManager(int numThreads) {executorService = Executors.newScheduledThreadPool(numThreads);}public void scheduleAtFixedRate(Runnable runnable, long initialDelay, long period,TimeUnit unit) {try {executorService.scheduleAtFixedRate(runnable, initialDelay, period, unit);}catch (Exception e){AtotoLogger.e("Ping server error = "+e.getMessage());}}public void shutdown() {executorService.shutdown();}
}
开启定时任务:
private final GoogleNetTaskManager mGoogleNetTaskManager;
mGoogleNetTaskManager = new GoogleNetTaskManager(5);mGoogleNetTaskManager = new GoogleNetTaskManager(5);
mGoogleNetTaskManager.scheduleAtFixedRate(new NetWorkCheck(ApiConfig.URL_PING_ADDRESS,StatusHolder.networkSingle::postValue), 0, 10,TimeUnit.SECONDS);
总结
以上就是在Android中检测网络连通性的主要流程,需要特别注意的就是需要加入网络权限,在不需要的时候记得关闭定时任务,如果您觉得对您有帮助,记得点赞加关注。