Android - 检查数据连接是否正常工作
Android - checking if data connection is actually working
我目前有一个特殊的用例,我很困惑如何解决。
我们一直在检查与 ConnectivityService 的互联网连接,其中包含 ConnectivityType.Wifi / ConnectivityType.Mobile 如果 已连接/正在连接 ,则带有 属性。这一切都很好,直到你 运行 进入以下情况:
- 您已在 phone 上启用数据。
- 数据连接已连接。
- 但是您不支付数据费用,因此无法进行任何数据传输。
- (尝试此操作时请确保您的 wifi 已关闭)
我以为我会简单地检查如下:
private static bool CanReachServer()
{
var uri = new Uri(Platform.ApiServerUrl); // replace with https://www.google.com if you like
try
{
using (HttpClient httpClient = new HttpClient())
{
httpClient.Timeout = TimeSpan.FromMilliseconds(5000);
HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, uri);
var task = httpClient.SendAsync(httpRequestMessage);
task.Wait();
if (task.Result.IsSuccessStatusCode)
return true;
else
return false;
}
}
catch (Exception ex)
{
Util.Log(string.Format("{0} - {1}", ex.Message, ex.StackTrace));
return false;
}
}
但这伴随着成功状态 200 的结果 - 这让我很困惑,因为我显然无法访问任何面向我 phone 的数据。
我建议您通过尝试打开到已知主机的套接字来检查连接 - 如果连接成功 - 您可以确定您有网络访问权限,否则您可以检查异常并处理它以显示错误连接。
public bool ActiveInternetConnectivity() {
try {
// connect to google on port 80, the HTTP port
var socket = new Java.Net.Socket("www.google.com", 80);
// the above would have thrown exception if failed, so we are good
socket.Close();
return true;
} catch (Exception ex) {
// check logcat to see why it failed, you could then catch and handle each exception independently ( time out, host unknown, end of stream, etc.. )
System.Diagnostics.Debug.WriteLine(ex);
// the connection has failed, return false
return false;
}
这只是一个想法,代码没有经过全面测试。
最终实施了以下似乎工作相当可靠的解决方案。您还可以对该方法强制可达性。
public static NetworkState GetNetworkState(this Context context, bool testReachability = false)
{
var result = NetworkState.NoNetwork;
var connMgr = (ConnectivityManager)context.GetSystemService(Context.ConnectivityService);
var activeNetwork = connMgr.ActiveNetworkInfo;
if (activeNetwork == null || !activeNetwork.IsConnectedOrConnecting)
{
connMgr.Dispose();
return NetworkState.NoNetwork;
}
if (activeNetwork.Type == ConnectivityType.Wifi && activeNetwork.IsConnected)
{
if (testReachability)
{
if (CanReachServer())
result = NetworkState.WiFi;
}
else
{
result = NetworkState.WiFi;
}
}
else if (activeNetwork.Type == ConnectivityType.Mobile && activeNetwork.IsConnected)
{
if (testReachability)
{
if (CanReachServer())
result = NetworkState.Mobile;
}
else
{
result = NetworkState.Mobile;
}
}
activeNetwork.Dispose();
connMgr.Dispose();
return result;
}
private static bool CanReachServer()
{
var uri = new Uri(Platform.ApiServerUrl).GetLeftPart(UriPartial.Authority);
var task = Task.Factory.StartNew(() =>
{
try
{
using (URL url = new URL(uri))
{
using (HttpURLConnection urlc = (HttpURLConnection)url.OpenConnection())
{
urlc.SetRequestProperty("User-Agent", "Android Application");
urlc.SetRequestProperty("Connection", "close");
urlc.ConnectTimeout = 6000;
urlc.ReadTimeout = 10000;
urlc.Connect();
bool result = urlc.ResponseCode == HttpStatus.Ok;
urlc.Disconnect();
return result;
}
}
}
catch (Exception ex)
{
Util.Log(string.Format("{0} - {1}", ex.Message, ex.StackTrace));
return false;
}
});
task.Wait();
return task.Result;
}
}
我目前有一个特殊的用例,我很困惑如何解决。
我们一直在检查与 ConnectivityService 的互联网连接,其中包含 ConnectivityType.Wifi / ConnectivityType.Mobile 如果 已连接/正在连接 ,则带有 属性。这一切都很好,直到你 运行 进入以下情况:
- 您已在 phone 上启用数据。
- 数据连接已连接。
- 但是您不支付数据费用,因此无法进行任何数据传输。
- (尝试此操作时请确保您的 wifi 已关闭)
我以为我会简单地检查如下:
private static bool CanReachServer()
{
var uri = new Uri(Platform.ApiServerUrl); // replace with https://www.google.com if you like
try
{
using (HttpClient httpClient = new HttpClient())
{
httpClient.Timeout = TimeSpan.FromMilliseconds(5000);
HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, uri);
var task = httpClient.SendAsync(httpRequestMessage);
task.Wait();
if (task.Result.IsSuccessStatusCode)
return true;
else
return false;
}
}
catch (Exception ex)
{
Util.Log(string.Format("{0} - {1}", ex.Message, ex.StackTrace));
return false;
}
}
但这伴随着成功状态 200 的结果 - 这让我很困惑,因为我显然无法访问任何面向我 phone 的数据。
我建议您通过尝试打开到已知主机的套接字来检查连接 - 如果连接成功 - 您可以确定您有网络访问权限,否则您可以检查异常并处理它以显示错误连接。
public bool ActiveInternetConnectivity() {
try {
// connect to google on port 80, the HTTP port
var socket = new Java.Net.Socket("www.google.com", 80);
// the above would have thrown exception if failed, so we are good
socket.Close();
return true;
} catch (Exception ex) {
// check logcat to see why it failed, you could then catch and handle each exception independently ( time out, host unknown, end of stream, etc.. )
System.Diagnostics.Debug.WriteLine(ex);
// the connection has failed, return false
return false;
}
这只是一个想法,代码没有经过全面测试。
最终实施了以下似乎工作相当可靠的解决方案。您还可以对该方法强制可达性。
public static NetworkState GetNetworkState(this Context context, bool testReachability = false)
{
var result = NetworkState.NoNetwork;
var connMgr = (ConnectivityManager)context.GetSystemService(Context.ConnectivityService);
var activeNetwork = connMgr.ActiveNetworkInfo;
if (activeNetwork == null || !activeNetwork.IsConnectedOrConnecting)
{
connMgr.Dispose();
return NetworkState.NoNetwork;
}
if (activeNetwork.Type == ConnectivityType.Wifi && activeNetwork.IsConnected)
{
if (testReachability)
{
if (CanReachServer())
result = NetworkState.WiFi;
}
else
{
result = NetworkState.WiFi;
}
}
else if (activeNetwork.Type == ConnectivityType.Mobile && activeNetwork.IsConnected)
{
if (testReachability)
{
if (CanReachServer())
result = NetworkState.Mobile;
}
else
{
result = NetworkState.Mobile;
}
}
activeNetwork.Dispose();
connMgr.Dispose();
return result;
}
private static bool CanReachServer()
{
var uri = new Uri(Platform.ApiServerUrl).GetLeftPart(UriPartial.Authority);
var task = Task.Factory.StartNew(() =>
{
try
{
using (URL url = new URL(uri))
{
using (HttpURLConnection urlc = (HttpURLConnection)url.OpenConnection())
{
urlc.SetRequestProperty("User-Agent", "Android Application");
urlc.SetRequestProperty("Connection", "close");
urlc.ConnectTimeout = 6000;
urlc.ReadTimeout = 10000;
urlc.Connect();
bool result = urlc.ResponseCode == HttpStatus.Ok;
urlc.Disconnect();
return result;
}
}
}
catch (Exception ex)
{
Util.Log(string.Format("{0} - {1}", ex.Message, ex.StackTrace));
return false;
}
});
task.Wait();
return task.Result;
}
}