检测Android设备是否具有Internet连接

Bud*_*ril 133 android internet-connection android-internet

我需要告诉我的设备是否有Internet连接.我找到了许多答案,如:

private boolean isNetworkAvailable() {
    ConnectivityManager connectivityManager 
         = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
    return activeNetworkInfo != null;
}
Run Code Online (Sandbox Code Playgroud)

(摘自检测Android上是否有可用的Internet连接.)

但这是不对的,例如,如果我连接到无法访问Internet的无线网络,此方法将返回true ... 是否有方法可以判断设备是否具有Internet连接,而不是仅仅连接什么?

THe*_*per 180

你是对的.您提供的代码仅检查是否存在网络连接.检查是否存在活动Internet连接的最佳方法是尝试通过http连接到已知服务器.

public static boolean hasActiveInternetConnection(Context context) {
    if (isNetworkAvailable(context)) {
        try {
            HttpURLConnection urlc = (HttpURLConnection) (new URL("http://www.google.com").openConnection());
            urlc.setRequestProperty("User-Agent", "Test");
            urlc.setRequestProperty("Connection", "close");
            urlc.setConnectTimeout(1500); 
            urlc.connect();
            return (urlc.getResponseCode() == 200);
        } catch (IOException e) {
            Log.e(LOG_TAG, "Error checking internet connection", e);
        }
    } else {
        Log.d(LOG_TAG, "No network available!");
    }
    return false;
}
Run Code Online (Sandbox Code Playgroud)

当然,您可以将http://www.google.comURL 替换为您要连接的任何其他服务器,或者您知道的服务器具有良好的正常运行时间.

正如Tony Cho在下面的评论中指出的那样,请确保您不在主线程上运行此代码,否则您将获得NetworkOnMainThread异常(在Android 3.0或更高版本中).请改用AsyncTask或Runnable.

如果你想使用google.com,你应该看看Jeshurun的修改.在他的回答中,他修改了我的代码并使其更有效率.如果你连接到

HttpURLConnection urlc = (HttpURLConnection) 
            (new URL("http://clients3.google.com/generate_204")
            .openConnection());
Run Code Online (Sandbox Code Playgroud)

然后检查204的响应代码

return (urlc.getResponseCode() == 204 && urlc.getContentLength() == 0);
Run Code Online (Sandbox Code Playgroud)

那么你不必先获取整个谷歌主页.

  • 但是如果谷歌在某些国家被禁止了怎么办? (37认同)
  • 这也应该落在后台线程上(而检查`ConnectivityManager`不需要这个).否则,在Android 4.x +设备上,您将获得"NetworkOnMainThread"异常. (11认同)
  • @varunbhardwaj你可以采取不同的网站(如http://baidu.com部署在中国的应用程序时),或者如果第一个失败,以确保没有任何连接,您可以尝试第二个站点. (9认同)
  • 我+1你的答案,并知道在我的应用程序中使用它,但有一个大角落的情况依赖一些网站,我的问题仍然没有答案.无论如何伟大的解决方法thanx. (2认同)
  • @blackcrow取决于您/用户愿意等待的时间.我个人认为1000ms是下限,平均6000ms,长15000ms.但是如果检查在后台运行而用户没有等待它,则可以使用更长的超时. (2认同)

Jes*_*run 88

我已经稍微修改了THelper的答案,使用Android已经使用的已知黑客来检查连接的WiFi网络是否可以访问Internet.这比抓住整个Google主页更有效率.有关详细信息,请参阅此处此处.

public static boolean hasInternetAccess(Context context) {
    if (isNetworkAvailable(context)) {
        try {
            HttpURLConnection urlc = (HttpURLConnection) 
                (new URL("http://clients3.google.com/generate_204")
                .openConnection());
            urlc.setRequestProperty("User-Agent", "Android");
            urlc.setRequestProperty("Connection", "close");
            urlc.setConnectTimeout(1500); 
            urlc.connect();
            return (urlc.getResponseCode() == 204 &&
                        urlc.getContentLength() == 0);
        } catch (IOException e) {
            Log.e(TAG, "Error checking internet connection", e);
        }
    } else {
        Log.d(TAG, "No network available!");
    }
    return false;
}
Run Code Online (Sandbox Code Playgroud)

  • 这将比上面的答案中的方法更有效.抓住谷歌主页是非常低效的,特别是如果他们碰巧有涂鸦. (4认同)
  • 如果您想在中国测试连接,也可以使用http://g.cn/generate_204而不是http://clients3.google.com/generate_204 (3认同)
  • 你好,现在的app可以用这个做法吗? (2认同)

Bil*_*hid 16

public boolean isInternetWorking() {
    boolean success = false;
    try {
        URL url = new URL("https://google.com");
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setConnectTimeout(10000);
        connection.connect();
        success = connection.getResponseCode() == 200;
    } catch (IOException e) {
        e.printStackTrace();
    }
    return success;
}
Run Code Online (Sandbox Code Playgroud)

如果互联网实际可用,则返回true

确保您拥有这两项权限

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
Run Code Online (Sandbox Code Playgroud)

  • 这对我不起作用...原因:android.os.StrictMode $ AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1273)处的android.os.NetworkOnMainThreadException,java.net.InetAddress.lookupHostByName(InetAddress.java:431)在 (2认同)

小智 13

如果您的目标是Lollipop或更高版本,则可以使用新的NetworkCapabilities类,即:

public static boolean hasInternetConnection(final Context context) {
    final ConnectivityManager connectivityManager = (ConnectivityManager)context.
            getSystemService(Context.CONNECTIVITY_SERVICE);

    final Network network = connectivityManager.getActiveNetwork();
    final NetworkCapabilities capabilities = connectivityManager
            .getNetworkCapabilities(network);

    return capabilities != null
            && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
}
Run Code Online (Sandbox Code Playgroud)

  • `connectivityManager.getActiveNetwork();` 需要 API lvl23,它是 Marshmallow 而不是 Lollipop。 (4认同)

Xiv*_*Xiv 6

您不一定需要建立完整的HTTP连接。您可以尝试仅打开与已知主机的TCP连接,如果成功,则可以连接Internet。

public boolean hostAvailable(String host, int port) {
  try (Socket socket = new Socket()) {
    socket.connect(new InetSocketAddress(host, port), 2000);
    return true;
  } catch (IOException e) {
    // Either we have a timeout or unreachable host or failed DNS lookup
    System.out.println(e);
    return false;
  }
}
Run Code Online (Sandbox Code Playgroud)

然后只需检查:

boolean online = hostAvailable("www.google.com", 80);
Run Code Online (Sandbox Code Playgroud)


Aya*_*Aya 5

根据接受的答案,我用一个监听器构建了这个类,这样你就可以在主线程中使用它:

第一:InterntCheck 类,它在后台检查互联网连接,然后使用结果调用侦听器方法。

public class InternetCheck extends AsyncTask<Void, Void, Void> {


    private Activity activity;
    private InternetCheckListener listener;

    public InternetCheck(Activity x){

        activity= x;

    }

    @Override
    protected Void doInBackground(Void... params) {


        boolean b = hasInternetAccess();
        listener.onComplete(b);

        return null;
    }


    public void isInternetConnectionAvailable(InternetCheckListener x){
        listener=x;
        execute();
    }

    private boolean isNetworkAvailable() {
        ConnectivityManager connectivityManager = (ConnectivityManager) activity.getSystemService(CONNECTIVITY_SERVICE);
        NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
        return activeNetworkInfo != null;
    }
    private boolean hasInternetAccess() {
        if (isNetworkAvailable()) {
            try {
                HttpURLConnection urlc = (HttpURLConnection) (new URL("http://clients3.google.com/generate_204").openConnection());
                urlc.setRequestProperty("User-Agent", "Android");
                urlc.setRequestProperty("Connection", "close");
                urlc.setConnectTimeout(1500);
                urlc.connect();
                return (urlc.getResponseCode() == 204 &&
                        urlc.getContentLength() == 0);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            Log.d("TAG", "No network available!");
        }
        return false;
    }

    public interface InternetCheckListener{
        void onComplete(boolean connected);
    }

}
Run Code Online (Sandbox Code Playgroud)

第二:在主线程中实例化一个类的实例并等待响应(如果您之前使用过 Android 的 Firebase api,您应该很熟悉!)。

new InternetCheck(activity).isInternetConnectionAvailable(new InternetCheck.InternetCheckListener() {

        @Override
        public void onComplete(boolean connected) {
           //proceed!
        }
    });
Run Code Online (Sandbox Code Playgroud)

现在在 onComplete 方法中,您将了解设备是否已连接到互联网。