在Android中如何检测有限的网络连接?

6
有许多关于如何在Android中检测网络连接的问题。链接https://dev59.com/j2855IYBdhLWcg3woVw_#4239019提供了非常详细的答案,而链接https://dev59.com/r3E85IYBdhLWcg3wYicB#8548926则展示了识别所连接网络类型的方法。
我们使用类似那些答案的代码来检测网络连接,例如:
private boolean isNetworkAvailable() {
    ConnectivityManager connectivityManager 
          = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
    return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}

这让我们能够在用户离线时警告用户。然而,它并不能帮助我们确定用户是否有限制的连接。有些限制连接条件会导致用户抱怨,这些包括:
  1. 用户连接到家庭WiFi网络,但电缆调制解调器或互联网服务不可用。

  2. 用户在酒店或咖啡店,并成功连接到WiFi网络,但网络要求他们登录或同意服务条款才能获得完整的网络访问权限。

在这两种情况下,我们的 isNetworkAvailable() 测试返回 true。操作系统告诉我们我们已连接到网络。然而,用户没有可用的互联网连接。
有没有好的方法来确定用户是否有完全功能的网络连接?
我正在考虑调用一个轻量级的 Web 服务来验证他们的连接性,并在应用程序未从服务中获得有效返回时警告用户。这样做是否过度?还是其他人也不得不采取类似的技术手段?
2个回答

8

有什么好方法可以确定用户具有完全功能的网络连接吗?

尝试从某个地方下载文件。理想情况下,“某个地方”是您自己的服务器,以测试设备与服务器之间的连接。

可惜,在ConnectivityManager上没有doesTehConnexionSuck()iCanHazBandwidth()方法。:-)

这是否过度了?

以“金发姑娘和三只熊”的精神来描述,我会将其描述为刚刚好的杀伤力。

我们在Web应用程序中也必须进行同样的花招


1
我喜欢“justrightkill”的想法,但它没有同样的感觉 - http://www.youtube.com/watch?v=YjETcbEDmoQ - Michael Levy

3

为了完整起见,让我发布一些代码。 我认为这是相当通用的HttpClient代码,用于发出Http请求并在请求成功时返回true。 我使用了HttpHead,因为我不关心响应中的实体,这应该使它更快。 此方法位于名为ConnectivityHelper的类中,DefaultSettings是一个包含大量有用常量定义的类。

public static boolean isNetworkAvailable() {
    ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo netInfo;

    try {
        netInfo = manager.getActiveNetworkInfo();
    } catch (Exception e) {
        netInfo = null;
    }

    return netInfo != null && netInfo.isConnected() && testConnection(DefaultSettings.TEST_CONNECTION_URL);
}


private static boolean testConnection(String url) {
    HttpClient httpClient = null;
    HttpHead request = null;
    HttpResponse response = null;
    int statusCode = 0;

    try {
        HttpParams myParams = new BasicHttpParams();
        HttpConnectionParams.setConnectionTimeout(myParams, DefaultSettings.CONNECTION_TIMEOUT);
        HttpConnectionParams.setSoTimeout(myParams, DefaultSettings.SO_TIMEOUT);

        httpClient = new DefaultHttpClient(myParams);

        request = new HttpHead(url);
        response = httpClient.execute(request);
        statusCode = response.getStatusLine().getStatusCode();

        if (statusCode != 200)
        {
            Log.e(ConnectivityHelper.class.getName(), String.format("testConnection not successful. For %s - Status code = %d", url, statusCode));
            return false;
        }
        return true;

    } catch(ClientProtocolException e) {
        Log.e(ConnectivityHelper.class.getName(), String.format("testConnection failure. For %s - Exception: %s.", url, e.toString()));

        if (request != null && !request.isAborted()) {
            request.abort();
        }

        return false;
    } catch(IOException e) {
        if (statusCode == 401) {
            Log.e(ConnectivityHelper.class.getName(), String.format("testConnection access denied. For %s - Status code = %d", url, statusCode));               
        } else {
            Log.e(ConnectivityHelper.class.getName(), String.format("testConnection failure. For %s - Exception: %s.", url, e.toString()));
        }

        if (request != null && !request.isAborted()) {
            request.abort();
        }

        return false;
    } finally {
        if (httpClient != null) {
            httpClient.getConnectionManager().shutdown();
        }
    }           
}

好的,正是@CommonsWare发布的答案引导我编写了上面的代码,所以他的回答是第一个并且非常有帮助的。剩下的,就像他们说的那样,只是一种练习。 - Michael Levy
HttpClient在API Level 22中已被弃用,并在API Level 23中被移除。您能否尝试更新代码? - Amar Ilindra

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接