问题场景:
最近开发中遇到一个bug,在设置日期和时间时,手动设置时间,开关机时间正常.使用自动获取网络时间,连接可上网的网络,获取时间也是正常.
但在使用静态IP时或者网络不可上网时,获取的时间就是异常的.
问题分析:
代码如下:
private void setAutoTime() {
if (isNetworkAvalible(getActivity())) {
Log.d("setRTCTime", "===setAutoTime===isNetworkAvalible====");
final Calendar calendar = Calendar.getInstance();
new Thread(new Runnable() {
@Override
public void run() {
URL urlTime = null;//取得资源对象
try {
urlTime = new URL("https://www.baidu.com");
URLConnection uc = urlTime.openConnection();//生成连接对象
uc.setConnectTimeout(3000);
uc.connect(); //发出连接
long autoTime = uc.getDate(); //取得网站日期时间
Date date = new Date(autoTime); //转换为标准时间对象
date.getDate();
Log.d("setRTCTime", "===setAutoTime===autoTime====" + autoTime);
if (autoTime == 0) {
return;
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
}
public boolean isNetworkAvalible(Context context) {
// 获得网络状态管理器
ConnectivityManager connectivityManager = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivityManager == null) {
return false;
} else {
// 建立网络数组
NetworkInfo[] net_info = connectivityManager.getAllNetworkInfo();
if (net_info != null) {
for (int i = 0; i < net_info.length; i++) {
// 判断获得的网络状态是否是处于连接状态
if (net_info[i].getState() == NetworkInfo.State.CONNECTED) {
return true;
}
}
}
}
return false;
}以上代码初看并未发现问题,然而仔细分析发现isNetworkAvalible()方法只能判断当前网线是否接入,假如使用的是静态IP,即使网线不接,返回的也是true.问题的根本原因就是这个接口不能判断出静态IP或者网络不能上网的情况.
既然问题原因找到了,那解决办法就是:通过ping网关的方式去检测网络是否能够正常上网.
解决方法:
具体代码如下:
private void setAutoTime() {
if (isNetworkAvalible(getActivity())) {
Log.d("setRTCTime", "===setAutoTime===isNetworkAvalible====");
final Calendar calendar = Calendar.getInstance();
new Thread(new Runnable() {
@Override
public void run() {
URL urlTime = null;//取得资源对象
try {
boolean isNetAval = pingNetWork(getGateway());//ping网关
Log.d("setRTCTime", "===setAutoTime===isNetAval====" + isNetAval);
if(!isNetAval){
syncRTCTime();//网络无效使用RTC时间
return;
}
urlTime = new URL("https://www.baidu.com");
URLConnection uc = urlTime.openConnection();//生成连接对象
uc.setConnectTimeout(3000);
uc.connect(); //发出连接
long autoTime = uc.getDate(); //取得网站日期时间
Date date = new Date(autoTime); //转换为标准时间对象
date.getDate();
Log.d("setRTCTime", "===setAutoTime===autoTime====" + autoTime);
if (autoTime == 0) {
syncRTCTime();//网络获取不到时间使用RTC时间
return;
}
syncNetTime(autoTime); //获取到网络时间同步系统时间
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}else{
syncRTCTime();//网络未连接使用RTC时间
}
}
public boolean isNetworkAvalible(Context context) {
// 获得网络状态管理器
ConnectivityManager connectivityManager = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivityManager == null) {
return false;
} else {
// 建立网络数组
NetworkInfo[] net_info = connectivityManager.getAllNetworkInfo();
if (net_info != null) {
for (int i = 0; i < net_info.length; i++) {
// 判断获得的网络状态是否是处于连接状态
if (net_info[i].getState() == NetworkInfo.State.CONNECTED) {
return true;
}
}
}
}
return false;
}
/**
* 获取网关
* @return
*/
private String getGateway() {
ConnectivityManager connectivity = (ConnectivityManager)
getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
LinkProperties properties = connectivity.getLinkProperties(connectivity.getActiveNetwork());
String ip = "0.0.0.0";
LinkAddress linkAddress = properties.getLinkAddresses().get(1);
for (int i = 0; i < properties.getLinkAddresses().size(); i++) {
LinkAddress linkAddressTmp = properties.getLinkAddresses().get(i);
String tmp = linkAddressTmp.getAddress().getHostAddress();
if (!tmp.contains(":") && !tmp.equals("0.0.0.0")) {
ip = tmp;
linkAddress = linkAddressTmp;
break;
}
}
String mask = dealWithMask(linkAddress.getPrefixLength());
String gateway = "0.0.0.0";
for (RouteInfo info : properties.getRoutes()) {
String tmp = info.getGateway().getHostAddress();
//Log.d(TAG, "initDate: gateway = " + tmp);
if (!tmp.equals("0.0.0.0") && !tmp.contains("::") && !tmp.contains(":")) {
gateway = tmp;
break;
}
}
return gateway;
}
private String dealWithMask(int prefixLength) {
int mask = 0xffffff << (32 - prefixLength);
return ((mask>>24)&0xff) + "." + ((mask>>16)&0xff) + "."
+ ((mask>>8)&0xff) + "." + (mask&0xff);
}
/**
* 判断是否是 静态IP 模式
* @return
*/
private static boolean isStaticIp() {
boolean state = false;
if (mEthernetManager == null) {
return false;
}
IpConfiguration.IpAssignment ipAssignment = mEthernetManager.getConfiguration("eth0").ipAssignment;
if (ipAssignment == IpConfiguration.IpAssignment.STATIC) {
state = true;
} else if (ipAssignment == IpConfiguration.IpAssignment.DHCP) {
state = false;
}
return state;
}
/**
* ping 网关
* @param cIP
* @return
*/
private static final boolean pingNetWork(final String cIP) {
String result = null;
try {
Process p = Runtime.getRuntime().exec("ping -c 1 "+cIP);
int status = p.waitFor();
if (status == 0) {
result = "success";
return true;
} else {
// 场景:当静态IP时,不能上网时,p.waitFor() 返回都是false,无法判断。
// 通过 p.getInputStream() 获取的信息进行判断
// a、不插网线会返还字符串 ping info:From 196.168.1.128: icmp_seq=1 Destination Host Unreachable
// b、插网线 为null ping info:
// 缺陷:检测时间较长
if(isStaticIp()) {
InputStream input = p.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(input));
StringBuffer buffer = new StringBuffer();
String line = "";
while ((line = in.readLine()) != null) {
buffer.append(line);
if (line.contains("Destination Host Unreachable")) {
result = "failed";
break;
}else{
result = "success";
}
//Log.i(TAG, "ping info:" + line);
}
if(result.equals("success")) {
return true;
}
}else{
result = "failed";
}
}
} catch (IOException e) {
result = "IOException";
} catch (InterruptedException e) {
result = "InterruptedException";
} finally {
//Log.d(TAG, "ping result = " + result);
}
return false;
}
private void syncNetTime(long time){
final Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(time);
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DAY_OF_MONTH);
int hour = calendar.get(Calendar.HOUR_OF_DAY);
int minute = calendar.get(Calendar.MINUTE);
int sec = calendar.get(Calendar.SECOND);
if (time / 1000 < Integer.MAX_VALUE) {
((AlarmManager) getActivity().getSystemService(Context.ALARM_SERVICE)).setTime(time);
yearAuto = year;
monthAuto = month;
dayAuto = day;
}
setRTCTime();
}
private void syncRTCTime(){
final Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DAY_OF_MONTH);
int hour = calendar.get(Calendar.HOUR_OF_DAY);
int minute = calendar.get(Calendar.MINUTE);
int sec = calendar.get(Calendar.SECOND);
long when = calendar.getTimeInMillis();
if (when / 1000 < Integer.MAX_VALUE) {
((AlarmManager) getActivity().getSystemService(Context.ALARM_SERVICE)).setTime(when);
yearAuto = year;
monthAuto = month;
dayAuto = day;
}
setRTCTime();
}目前网络上很多方法都是获取到的网络连接状态,并不能判断网络是否可以正常上网,以上方法可以解决这个问题,不过有时候ping的时候会比较慢一些.
| 留言与评论(共有 0 条评论) “” |