【问题标题】:Android - Check internet connection through an specific network (WIFI)Android - 通过特定网络(WIFI)检查互联网连接
【发布时间】:2018-09-15 00:22:49
【问题描述】:

基本上,我需要检查我的 Wifi 连接是否可以访问互联网。我知道最有效的方法是使用 sock.connect() 但我需要确保连接将通过 Wifi 网络完成,这是我的主要问题, 我搜索了几天,但没有很好的回应。

有很多像How do I see if Wi-Fi is connected on Android? 这样的解决方案,但它们只检查设备是否连接到路由器。我需要知道路由器是否可以上网

我的最佳近似是这样的:

        Socket sock = new Socket();
        ConnectivityManager
                cm = (ConnectivityManager) mContext.getApplicationContext()
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
            Network net = cm.getActiveNetwork();
            net.bindSocket(sock);
        }
        sock.connect(new InetSocketAddress("8.8.8.8", 53), 1500);
        sock.close();

但这有一些限制。最大的限制是仅适用于 API >= 23。 另外,如果我在中国,我认为主机名“8.8.8.8”将不起作用,对吧?

最后,如果我的设备连接到 wifi 网络,cm.getActiveNetwork() 只会成为 WIFI 网络,这并不完全正确,因为可以修改默认活动网络。

我需要知道的是:

  • API >= 16 是否有任何可行的替代方案?
  • 有在中国可以正常使用的好主机名吗?

任何帮助将不胜感激, 提前致谢!

【问题讨论】:

标签: android


【解决方案1】:

是的,您必须与远程服务器核实才能确定。

一种常见的方式是这样的:

NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo();
boolean isConnected = activeNetwork != null && activeNetwork.isConnectedOrConnecting();
if (isConnected) {
    try {
        InetAddress ipAddr = InetAddress.getByName("google.com");
        if (ipAddr.isReachable(5000)) {
            // Internet access OK!
        }
    } catch (Exception e) {
        // Error handling...
    }
}

调用 getByName 时首选域名而不是 IP (https://docs.oracle.com/javase/7/docs/api/java/net/InetAddress.html#getByName(java.lang.String))

如果您想避免连接管理器,您可以为 WifiManager.NETWORK_STATE_CHANGED_ACTION 事件注册一个 BroadcastReceiver,您将知道您是否连接到 WiFi(几乎立即收到当前状态)。

至于地区问题,我没有想法,也许使用 NTP 服务器而不是 google(更无辜的服务器)或尝试百度!?

【讨论】:

  • 是的,我做了类似的事情,但我想通过 wifi 连接检查互联网访问。使用您的解决方案,我不能保证这一点。 isReachable() 也无法正常工作,我将它用于其他目的,您可以访问互联网,并且 isReachable() 无论如何都可能返回 false :(
  • 确实,您不能 100% 确定。您可以依靠这样一个事实,即如果连接了 WiFi,那是执行网络操作的最可能方式,而不是通过移动数据左右(但您不能确定)。确实 isReachable 并不完美。存在 DNS 缓存问题(许多罪魁祸首,本地、路由器、ISP),所以生活很艰难。你可以试试这个而不是 isReachable: if (!ipAddr.equals(""))...
【解决方案2】:

最后,我想出了一个解决方案:

    public interface Consumer {
    void accept(Boolean internet);
}

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

    private Consumer mConsumer;

    public InternetCheck(Consumer consumer) {
        mConsumer = consumer;
        execute();
    }

    @Override
    protected Boolean doInBackground(Void... voids) {
        Socket socket = null;
        try {
            WifiManager wifiManager = (WifiManager) mContext.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
            if (wifiManager != null) {
                socket = new Socket();
                socket.setKeepAlive(false);
                String localIpAddress = getIpAddress(wifiManager);
                socket.bind(new InetSocketAddress(localIpAddress, 0));
                socket.connect(new InetSocketAddress("8.8.8.8", 53), 1500);
                return true;
            }
            return false;
        } catch (IOException e) {
            //unbind();
            return false;
        }finally {
            if(socket != null && !socket.isClosed()) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    protected void onPostExecute(Boolean internet) {
        mConsumer.accept(internet);
    }
}

public static String getIpAddress(WifiManager wifiManager) {
    WifiInfo wifiInfo = wifiManager.getConnectionInfo();
    int ipAddress = wifiInfo.getIpAddress();
    return String.format(Locale.getDefault(), "%d.%d.%d.%d", (ipAddress & 0xff), (ipAddress >> 8 & 0xff),
            (ipAddress >> 16 & 0xff), (ipAddress >> 24 & 0xff));
}

在看到this question 之后,我找到了解决方案。有了这个,我获得了我的 wifi 连接的 IP 地址,通过这个,我能够将套接字 (socket.bind(...)) 绑定到 wifi 连接,并检查我的路由器是否可以访问互联网。

我希望这个解决方案在未来对某人有所帮助:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-02
    • 2021-06-21
    • 2017-05-23
    • 2012-06-12
    • 1970-01-01
    • 2016-09-19
    • 2018-02-02
    • 1970-01-01
    相关资源
    最近更新 更多