新项目的app,可通过内网和外网的服务器ip进行请求访问,但是客户提供了专业终端,终端在wifi情况下走外网内网都可以,但关闭wifi则只能走4G专网,也就是只能走内网。

可前往我的小站查看:Android根据内网外网连接情况配置服务器访问IP

方案

Android中可以直接调用底层的shell,执行相应的命令,因此只需要执行ping命令即可。Android可以通过 Process p = Runtime.getRuntime().exec(/system/bin/ping -c 1 -w 1 " + ip)执行。

然后通过if (p.waitFor() == 0)判断是否ping通,这里的两个1表示参数,第一个表示ping 1次,第二个表示操作1s即为失败。

完整实现

  1. 首先声明权限,这一步非常重要,在AndroidManifes文件中
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET" />
  1. 维持几个全局变量
	String outer_ip = "183.230.XXX.XXX"; // 服务器外网IP
String inner_ip = "192.168.XXX.XXX"; // 服务器内网IP boolean outerIpAvilable = false; // 外网可用
boolean innerIpAvialable = false; // 内网可用
  1. 开启两个线程去ping两个ip,并通过CountDownLatch控制同步。因为要在两个ping结束之后,配置了ip之后才能做接下来的操作
private void initNetworkConfig() {
try {
final int totalThread = 2;
CountDownLatch countDownLatch = new CountDownLatch(totalThread);
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(new PingNetwork(outer_ip, countDownLatch, false));
executorService.execute(new PingNetwork(inner_ip, countDownLatch, true));
countDownLatch.await(); // 等待二者执行完毕
Log.d(TAG, "end");
if (innerIpAvialable && outerIpAvilable)
Toast.makeText(this, "内外都可使用", Toast.LENGTH_SHORT).show();
else if (outerIpAvilable)
Toast.makeText(this, "外网可使用", Toast.LENGTH_SHORT).show();
else
Toast.makeText(this, "内网可使用", Toast.LENGTH_SHORT).show();
executorService.shutdown();
}catch (Exception e) {
e.printStackTrace();
}
}
  1. 实现ping的异步线程,
class PingNetwork implements Runnable {

        String ip; // 需要ping的ip
CountDownLatch countDownLatch;
boolean isCheckInner;
public PingNetwork(String ip, CountDownLatch countDownLatch, boolean isCheckInner) {
this.ip = ip;
this.countDownLatch = countDownLatch;
this.isCheckInner = isCheckInner;
} @Override
public void run() {
try {
Process p = Runtime.getRuntime().exec("/system/bin/ping -c 1 -w 1 " + ip);// ping网址3次
// ping的状态
final int status = p.waitFor();
if (status == 0) {
Log.d(TAG, "ping onSuccess");
if (isCheckInner){
innerIpAvialable = true;
outerIpAvilable = false;
}
else{
outerIpAvilable = true;
innerIpAvialable = false;
}
} else {
// 读取ping的error内容,查看无法ping通的原因
InputStream errorStream = p.getErrorStream();
BufferedReader errIn = new BufferedReader(new InputStreamReader(errorStream));
StringBuilder sb = new StringBuilder();
String err = "";
while ((err = errIn.readLine()) != null) {
sb.append(err);
}
Log.d(TAG, "result err : " + sb.toString());
Log.d(TAG, "ping onFailure");
}
} catch (Exception e) {
Log.d(TAG, "ping onFailure");
} finally {
countDownLatch.countDown();
}
}
}

这里在ping失败时候可以打印错误信息查看,还记得第一步是声明权限,本人没有声明第二个权限,在这里得到了一个错误信息Pemission denied,网上说什么root的都有,其实不然。

完善

通过以上的实现,可以实现通过内网外网连接情况配置访问服务器的ip,但是设想一下,如果在app启动时,手机可以访问外网,所以程序配置了外网的ip(因为外网速度快),但是在使用的过程中,关闭了外网访问,比如说wifi,此时走了专网,即内网,则无法再访问服务器了。所以在切换网络时,需要从新配置访问ip。

因此,需要再app里面通过广播的方式,在android N(android 7)之前,可以通过android.net.conn.CONNECTIVITY_CHANGE广播,可以静态注册和动态注册,然而在7之后,改广播无效了,可以使用以下方案替换。

ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
connectivityManager.requestNetwork(new NetworkRequest.Builder().build(),
new ConnectivityManager.NetworkCallback() {
@Override public void onAvailable(Network network) {
super.onAvailable(network);
LogUtil.d("网络发生改变,更改配置");
NetworkUtils.initNetworkConfig();
}
});

NetworkUtils.initNetworkConfig();是我对上面通过ping配置ip的封装。

Android根据内网外网连接情况配置服务器访问IP的更多相关文章

  1. [转] 如何设置双网卡同时连接内网外网_bpao_新浪博客

    已剪辑自: http://blog.sina.com.cn/s/blog_5d3e229c0100skwe.html 如何设置双网卡同时连接内网外网 . 通过无线网络连接外网,确保连接成功后开始第二步 ...

  2. win10内网外网智能访问

    当电脑同时连接有线和WiFi时(有线连接为内网,WiFi为外网),会出现内网和外网内容无法同时访问的情况. 本方法实现内网和外网的同时访问. 第一步: 输入指令 “route print ” 查看路由 ...

  3. Ubuntu16.04双网卡配置,内网外网同时访问

    Ubuntu16.04双网卡配置,内网外网同时访问 配置:vim/etc/network/interface auto lo iface lo inet loopback auto eno1 ifac ...

  4. C#获取本机内网外网IP

    using System.Net; # region 获取内.外网Ip /// <summary> /// 获取本地ip地址,优先取内网ip /// </summary> pu ...

  5. 配置windows路由表,使电脑同时连接内网外网方法

    1.环境一(系统:windows xp,内网.外网不是同一类地址,内网地址固定): 外网:通过笔记本的无线网卡连接: 内网:通过笔记本的本地连接: 第一步,连接网线,配置本地连接地址,注意IP地址不要 ...

  6. kali linux android木马(内网+外网)

    1,内网木马 先生成一个小马 msfpayload -p android/meterpreter/reverse_tcp LHOST=192.168.8.104 LPORT=5555 R > a ...

  7. 【转】配置windows路由表,使电脑同时连接内网外网方法

    1. 公司内部,内网和外网的网关不一样,怎么样让电脑可以同时上内网和外网呢? 来一张不相关的磁盘结构图: ----------------------------------------------- ...

  8. FTP搭建 共享上网 穿透内网外网

    1.ftp原理介绍 FTP只通过TCP连接,没有用于FTP的UDP组件.FTP不同于其他服务的是它使用了两个端口, 一个数据端口和一个命令端口(或称为控制端口).通常21端口是命令端口,20端口是数据 ...

  9. ubuntu双网卡配置,实现内网外网同时访问!

    我们假定内网IP为:10.35.0.58,内网网关为:10.35.0.254:外网IP为222.76.250.4,外网网关为:222.76.250.1.其中局域名网需要连接:10.35.0.X,10. ...

随机推荐

  1. 智慧图携手DataPipeline,让实体商业更智慧!

    近日,国内领先的实体商业数字化运营服务商智慧图携手DataPipeline,基于专业的数据集成与应用基础展开了合作. 未来DataPipeline将通过不断提升自身产品和服务实力,与智慧图一道致力于帮 ...

  2. gin 页面重定向

    两种gin页面重定向方式 redirect: package main import ( "github.com/gin-gonic/gin" "net/http&quo ...

  3. Python——2x和3x的区别汇总

    1. 初始解释器编码: 2x:ascii 编码(不自持中文) 3x:unicode编码 推荐全部更换为utf-8 2. 输出方式不同 2x:print ‘你好’2.7版本的两种都支持 3x:print ...

  4. Needham-Schroeder Scyther工具形式化过程

    1.Needham-Schroeder Public key Protocol 协议的通信认证的过程 顺序图的 1.  A-> S :   A,  B 2. S->A:     {Ks, ...

  5. pod-test

    apiVersion: v1 kind: Pod metadata:   name: init-demo   # 命名空间   namespace: default   labels:     app ...

  6. java容器三:HashMap源码解析

    前言:Map接口 map是一个存储键值对的集合,实现了Map接口的主要类有以下几种 TreeMap:用红黑树实现 HashMap:数组和链表实现 HashTable:与HashMap类似,但是线程安全 ...

  7. AI demo framework

    import pickle import matplotlib.pyplot as plt from sklearn import datasets from sklearn.model_select ...

  8. php最快测试环境建立

    win下待验证,但linux下真快. 不要nginx,不要php-fpm,就一个字,快! 1, 安装php yum install php 输出如下: Dependencies Resolved == ...

  9. SpringBoot RabbitMQ 延迟队列代码实现

    场景 用户下单后,如果30min未支付,则删除该订单,这时候就要可以用延迟队列 准备 利用rabbitmq_delayed_message_exchange插件: 首先下载该插件:https://ww ...

  10. C# 如何取消BackgroundWorker异步操作

    BackgroundWorker 在执行DoWork事件时该如何取消呢? 方法1 DoWork 执行一个(耗时)循环 方法2 DoWork执行一个(耗时)方法[注:方法没有循环] 见代码: 方法1中D ...