安卓检查网络连接

276

我想创建一个使用互联网的应用程序,并尝试创建一个函数来检查是否有连接可用,如果没有,则转到具有重试按钮和说明的活动。

这是目前我的代码,但我收到了错误提示Syntax error, insert "}" to complete MethodBody.

到目前为止,我一直在尝试修改它,但是还没有成功...

public class TheEvoStikLeagueActivity extends Activity {
    private final int SPLASH_DISPLAY_LENGHT = 3000;
     
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.main);
     
        private boolean checkInternetConnection() {
            ConnectivityManager conMgr = (ConnectivityManager) getSystemService (Context.CONNECTIVITY_SERVICE);
            // ARE WE CONNECTED TO THE NET
            if (conMgr.getActiveNetworkInfo() != null
                    && conMgr.getActiveNetworkInfo().isAvailable()
                    && conMgr.getActiveNetworkInfo().isConnected()) {

                return true;

                /* New Handler to start the Menu-Activity
                 * and close this Splash-Screen after some seconds.*/
                new Handler().postDelayed(new Runnable() {
                    public void run() {
                        /* Create an Intent that will start the Menu-Activity. */
                        Intent mainIntent = new Intent(TheEvoStikLeagueActivity.this, IntroActivity.class);
                        TheEvoStikLeagueActivity.this.startActivity(mainIntent);
                        TheEvoStikLeagueActivity.this.finish();
                    }
                }, SPLASH_DISPLAY_LENGHT);
            } else {
                return false;
                     
                Intent connectionIntent = new Intent(TheEvoStikLeagueActivity.this, HomeActivity.class);
                TheEvoStikLeagueActivity.this.startActivity(connectionIntent);
                TheEvoStikLeagueActivity.this.finish();
            }
        }
    }

            

1
最佳答案在这里 https://dev59.com/bnI_5IYBdhLWcg3wBuRs#27312494。只需ping一下,看看设备是否真正连接到互联网。 - Bugs Happen
如果有人想查看“ConnectivityManager”的官方文档,可以访问:https://developer.android.com/training/monitoring-device-state/connectivity-monitoring - Kalu Khan Luhar
20个回答

495

此方法检查移动设备是否连接到互联网,如果连接则返回true:

private boolean isNetworkConnected() {
    ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

    return cm.getActiveNetworkInfo() != null && cm.getActiveNetworkInfo().isConnected();
}

在清单文件中,
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

编辑: 该方法实际上检查设备是否连接到互联网(有可能连接到网络但未连接到互联网)。

public boolean isInternetAvailable() {
    try {
        InetAddress ipAddr = InetAddress.getByName("google.com"); 
        //You can replace it with your name
            return !ipAddr.equals("");

        } catch (Exception e) {
            return false;
    }
}

79
这个答案是不正确的。如果你连接的是一个无法路由到互联网的网络,这种方法将错误地返回 true。请注意,getActiveNetworkInfo 的 javadoc 中说你应该检查 NetworkInfo.isConnected(),但这也不足以检查你是否连接到互联网。我正在进一步研究,但你可能需要 ping 一个互联网上的服务器来确保你确实连接到了互联网。 - miguel
4
它是否也检测3G、EDGE、GPRS等网络? - Dr.jacky
29
要小心使用 isInternetAvailable() 方法,因为它可能会在“主线程上的网络”异常情况下失败,导致即使你有网络连接也返回 false。请注意不改变原意,简明扼要地翻译。 - Oren
8
对我来说,isInternetAvailable()总是返回false。即使绕过catch语句也是如此。我使用的是3G网络。 - Yster
4
DNS地址会被缓存。作为一个测试,循环运行这种方式,然后将路由器从互联网上拔掉。它会一直返回true...尽管当DNS缓存超时(这个时间会因DNS客户端而异)时,它最终会失败。唯一确定的方法是尝试连接到互联网上的某个东西,并希望它们不介意你向它们发送大量连接请求。 - Jeffrey Blattman
显示剩余22条评论

103

检查确保它与网络“连接”:

public boolean isNetworkAvailable(Context context) {
    ConnectivityManager connectivityManager = ((ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE));
    return connectivityManager.getActiveNetworkInfo() != null && connectivityManager.getActiveNetworkInfo().isConnected();
}

检查确保它与互联网“连接”:

public boolean isInternetAvailable() {
    try {
        InetAddress address = InetAddress.getByName("www.google.com");
        return !address.equals("");
    } catch (UnknownHostException e) {
        // Log error
    }
    return false;
}

需要许可:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

https://dev59.com/bnI_5IYBdhLWcg3wBuRs#17583324


6
如何查找已连接到WiFi但实际未使用WiFi数据的方法。 - Ganesh Katikar
8
只告诉你是否连接到网络,而不是互联网。如果您想要崩溃(用于互联网安全代码),那么请使用此选项。 - Oliver Dixon
1
这与被接受的答案有何不同? - Seshu Vinay
1
@SeshuVinay 看日期,我是在4年前发布的。 - Jared Burrows
1
getAllNetworkInfo() 在 API 级别 29 中已被弃用。 - AskNilesh
显示剩余4条评论

83

您可以简单地对一个在线网站(如Google)进行ping测试:

public boolean isConnected() throws InterruptedException, IOException {
    String command = "ping -c 1 google.com";
    return Runtime.getRuntime().exec(command).waitFor() == 0;
}

4
不是最佳选择,虽然不错。整个逻辑依赖于google.com,假设google在几分钟内宕机,你的应用程序也将无法工作几分钟。 - Zeeshan Shabbir
2
那么你有什么建议? - Bugs Happen
10
@ZeeshanShabbir说得对,如果太阳耀斑影响到Google主要操作所在的国家/地区,那么你的应用程序可能会受到影响。在这种情况下,你可以尝试ping一些地址来检查网络连接是否正常。此外,我认为即使某个中心出现故障,Google也不会完全瘫痪,必须有大多数中心被关闭才会受到影响,前提是你的网络运营商能够经受住全球停电的考验 :D - TheAnimatrix
31
如果您的应用程序依赖于远程服务器(用于身份验证、获取数据、与数据库通信等),则可以使用该服务器地址代替Google,这样您就可以同时检查Internet连接和服务器可用性。如果您的服务器已经宕机,即使仍然有Internet连接,应用程序也无法正常工作。在这种情况下,您可能还想使用“-i”选项设置ping命令的超时时间间隔,例如:ping -i 5 -c 1 www.myserver.com - razz
2
在存在 WiFi 登录页面的情况下,这个方法会误报 true 吗? - Foobar
显示剩余13条评论

42

以上方法适用于连接Wi-Fi或通过手机数据包连接网络的情况。但在使用 Wi-Fi 连接时,可能会出现需要登录的情况,比如在咖啡馆里。这种情况下,你的应用程序将会失败,因为虽然你连接了 Wi-Fi 但却没有连接到互联网。

这个方法很好用。

    public static boolean isConnected(Context context) {
        ConnectivityManager cm = (ConnectivityManager)context
                .getSystemService(Context.CONNECTIVITY_SERVICE);

    NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
    if (activeNetwork != null && activeNetwork.isConnected()) {
        try {
            URL url = new URL("http://www.google.com/");
            HttpURLConnection urlc = (HttpURLConnection)url.openConnection();
            urlc.setRequestProperty("User-Agent", "test");
            urlc.setRequestProperty("Connection", "close");
            urlc.setConnectTimeout(1000); // mTimeout is in seconds
            urlc.connect();
            if (urlc.getResponseCode() == 200) {
                return true;
            } else {
                return false;
            }
        } catch (IOException e) {
            Log.i("warning", "Error checking internet connection", e);
            return false;
        }
    }

    return false;

}
请将此方法放在独立的线程中使用,因为它会进行网络调用,如果不遵循此规则将会抛出 NetworkOnMainThreadException 异常。
同时,请勿将此方法放置在 onCreate 或其他任何方法中,应将其放置在一个类中并访问。

3
这是解决问题的一个好方法。但可能只需要一次简短的确认信号就足够了。 - dazito
当你只需要简单地检查互联网响应时,使用线程带来的困难不值得付出。Ping可以轻松完成工作。 - MbaiMburu
最佳方法(句号)。套接字、InetAddress 方法在设备连接到没有互联网连接的 Wifi 网络时容易出错,即使没有互联网连接,它仍将继续指示互联网是可达的。 - Gayal Rupasinghe
1
我使用了这个方法,效果非常好。在2022年晚期,您需要使用https而不是http,因为运行时拒绝在明文中进行请求,如果出现此异常,您将始终返回false,即离线状态。将http更改为https后,效果非常好。 - Davide Piras

31

您可以使用以下代码片段来检查互联网连接。

它将有用的两种方式,您可以检查可用的网络连接的类型,以便您可以按照这种方式处理您的过程。

您只需要复制以下类并直接粘贴到您的包中即可。

/**
 * @author Pratik Butani
 */
public class InternetConnection {

    /**
     * CHECK WHETHER INTERNET CONNECTION IS AVAILABLE OR NOT
     */
    public static boolean checkConnection(Context context) {
        final ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

        if (connMgr != null) {
            NetworkInfo activeNetworkInfo = connMgr.getActiveNetworkInfo();

            if (activeNetworkInfo != null) { // connected to the internet
                // connected to the mobile provider's data plan
                if (activeNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
                    // connected to wifi
                    return true;
                } else return activeNetworkInfo.getType() == ConnectivityManager.TYPE_MOBILE;
            }
        }
        return false;
    }
}

现在你可以使用如下方法:

if (InternetConnection.checkConnection(context)) {
    // Its Available...
} else {
    // Not Available...
}

不要忘记取得许可 :) :)

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

您可以根据您的需求进行修改。

谢谢。


1
这里不需要 android.permission.ACCESS_WIFI_STATE 权限。 - Thomas
您正在检查设备当前连接的是wifi网络还是蜂窝网络。然而,当设备连接到无法访问互联网的wifi网络时,这种方式并不足够。 - Gayal Rupasinghe

24

被接受的答案的编辑显示了如何检查互联网上的内容是否可以被访问。当这种情况不成立时(使用没有互联网连接的wifi),我等待了太久才得到答案。不幸的是,InetAddress.getByName没有超时参数,所以下面的代码解决了这个问题:

private boolean internetConnectionAvailable(int timeOut) {
    InetAddress inetAddress = null;
    try {
        Future<InetAddress> future = Executors.newSingleThreadExecutor().submit(new Callable<InetAddress>() {
            @Override
            public InetAddress call() {
                try {
                    return InetAddress.getByName("google.com");
                } catch (UnknownHostException e) {
                    return null;
                }
            }
        });
        inetAddress = future.get(timeOut, TimeUnit.MILLISECONDS);
        future.cancel(true);
    } catch (InterruptedException e) {
    } catch (ExecutionException e) {
    } catch (TimeoutException e) {
    } 
    return inetAddress!=null && !inetAddress.equals("");
}

这对于一个我不需要管理“可达性”状态的奇怪检查来说效果很好。 - Hunter-Orionnoir
这个方法即使我已经连接到互联网也返回false。有什么想法吗? - Mahendra Chhimwal
这应该是被接受的答案。 - no_profile
InetAddress.equals() 的源代码被设置为始终返回 false(Android 30),不得不使用 tostring 然后 equals。 - Richard Muvirimi
有用的答案,但有时候我在这一行遇到ANR问题。inetAddress = future.get(timeOut, TimeUnit.MILLISECONDS); - M. Bilal Asif

14

所有官方方法只能告诉设备是否开放网络,
如果您的设备连接到WiFi但WiFi没有连接到互联网,那么这些方法将失败(这种情况经常发生)。没有内置的网络检测方法可以告诉您这种情况,因此创建了异步回调类,该类将在 onConnectionSuccess 和 onConnectionFail 中返回结果。

new CheckNetworkConnection(this, new CheckNetworkConnection.OnConnectionCallback() {

    @Override
    public void onConnectionSuccess() {
        Toast.makeText(context, "onSuccess()", toast.LENGTH_SHORT).show();
    }

    @Override
    public void onConnectionFail(String msg) {
        Toast.makeText(context, "onFail()", toast.LENGTH_SHORT).show();
    }
}).execute();

异步任务的网络调用

public class CheckNetworkConnection extends AsyncTask < Void, Void, Boolean > {
    private OnConnectionCallback onConnectionCallback;
    private Context context;

    public CheckNetworkConnection(Context con, OnConnectionCallback onConnectionCallback) {
        super();
        this.onConnectionCallback = onConnectionCallback;
        this.context = con;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    @Override
    protected Boolean doInBackground(Void...params) {
        if (context == null)
            return false;

        boolean isConnected = new NetWorkInfoUtility().isNetWorkAvailableNow(context);
        return isConnected;
    }

    @Override
    protected void onPostExecute(Boolean b) {
        super.onPostExecute(b);

        if (b) {
            onConnectionCallback.onConnectionSuccess();
        } else {
            String msg = "No Internet Connection";
            if (context == null)
                msg = "Context is null";
            onConnectionCallback.onConnectionFail(msg);
        }

    }

    public interface OnConnectionCallback {
        void onConnectionSuccess();

        void onConnectionFail(String errorMsg);
    }
}

实际的类将会向服务器发送ping请求

class NetWorkInfoUtility {

    public boolean isWifiEnable() {
        return isWifiEnable;
    }

    public void setIsWifiEnable(boolean isWifiEnable) {
        this.isWifiEnable = isWifiEnable;
    }

    public boolean isMobileNetworkAvailable() {
        return isMobileNetworkAvailable;
    }

    public void setIsMobileNetworkAvailable(boolean isMobileNetworkAvailable) {
        this.isMobileNetworkAvailable = isMobileNetworkAvailable;
    }

    private boolean isWifiEnable = false;
    private boolean isMobileNetworkAvailable = false;

    public boolean isNetWorkAvailableNow(Context context) {
        boolean isNetworkAvailable = false;

        ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

        setIsWifiEnable(connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnected());
        setIsMobileNetworkAvailable(connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).isConnected());

        if (isWifiEnable() || isMobileNetworkAvailable()) {
            /*Sometime wifi is connected but service provider never connected to internet
            so cross check one more time*/
            if (isOnline())
                isNetworkAvailable = true;
        }

        return isNetworkAvailable;
    }

    public boolean isOnline() {
        /*Just to check Time delay*/
        long t = Calendar.getInstance().getTimeInMillis();

        Runtime runtime = Runtime.getRuntime();
        try {
            /*Pinging to Google server*/
            Process ipProcess = runtime.exec("/system/bin/ping -c 1 8.8.8.8");
            int exitValue = ipProcess.waitFor();
            return (exitValue == 0);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            long t2 = Calendar.getInstance().getTimeInMillis();
            Log.i("NetWork check Time", (t2 - t) + "");
        }
        return false;
    }
}

1
请注意,据我所知,只有在已获取 root 权限的应用程序中才能使用“Runtime”。 - Zulqurnain Jutt
我找到的最佳解决方案是,在连接到WiFi网络或手机数据时检测互联网是否可用,做得非常好。 - zakaria
很遗憾,Ping命令在一些三星设备上被禁止使用。 - Ayyappa

14

不能在另一个方法内创建方法,需要将 private boolean checkInternetConnection() { 方法移出 onCreate 方法。


你可以创建一个线程来持续查看网络可用性并通知您,在一定时间间隔后进行重试。 - Vipin Sahu

9

不需要太复杂,最简单的框架方式就是使用ACCESS_NETWORK_STATE权限并编写一个连接方法。

public boolean isOnline() {
    ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    return cm.getActiveNetworkInfo() != null && cm.getActiveNetworkInfo().isConnectedOrConnecting();
}

如果您有特定的主机和连接类型(wifi/mobile)在心中,您还可以使用requestRouteToHost

您还需要:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

在您的Android清单文件中。

有关更多详细信息,请点击此处


1
此函数始终返回TRUE。 - DolDurma
这对我有效。这个链接可能有帮助... https://dev59.com/bnI_5IYBdhLWcg3wBuRs - Zar E Ahmer

7
请使用以下方法:
public static boolean isOnline() {
    ConnectivityManager cm = (ConnectivityManager) context
            .getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo netInfo = cm.getActiveNetworkInfo();
    return netInfo != null && netInfo.isConnectedOrConnecting();
}

需要的权限如下:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

重复并不准确地返回true,这是由于非互联网路由连接所导致的。 - Eliot Gillum

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