【问题标题】:Using a WiFi without Internet Connection在没有 Internet 连接的情况下使用 WiFi
【发布时间】:2026-02-22 19:55:02
【问题描述】:

在我的应用程序中,我连接到具有自己的 WiFi 网络的设备。 在 android 6 及更高版本中,系统会在几秒钟后询问我是否要连接到该网络,即使没有互联网连接也是如此。 只有在批准该消息后,我才能连接到我的设备。 我尝试以编程方式连接到网络,而不是强制用户每次都去他的设置并手动连接。我使用以下代码连接到设备网络:

private void connectToWiFi(WifiManager wifiManager, String wifiName) {

    WifiConfiguration configuration = new WifiConfiguration();
    configuration.SSID = "\"" + wifiName + "\"";
    configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
    wifiManager.addNetwork(configuration);
    List<WifiConfiguration> list = wifiManager.getConfiguredNetworks();
    for (WifiConfiguration i : list) {
        if (i.SSID != null && i.SSID.equals("\"" + wifiName + "\"")) {
            wifiManager.disconnect();
            wifiManager.enableNetwork(i.networkId, true);
            wifiManager.reconnect();
            break;
        }
    }
}

并且还试图强制应用使用 WiFi 连接,而不是我正在使用的蜂窝数据:

NetworkRequest.Builder builder;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        builder = new NetworkRequest.Builder();
        builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);

        connectivityManager.requestNetwork(builder.build(), new ConnectivityManager.NetworkCallback() {
            @Override
            public void onAvailable(Network network) {
                String ssid = wifiManager.getConnectionInfo().getSSID();
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    connectivityManager.bindProcessToNetwork(null);
                    if (ssid.equals("\"" + Prefs.getWifiName(PUFMainActivity.this) + "\"")) {
                        connectivityManager.bindProcessToNetwork(network);
                        connectivityManager.unregisterNetworkCallback(this);
                    }
                }
            }
        });

    }

尽管只要蜂窝数据处于活动状态,设备就不会出现连接。如果我禁用蜂窝数据,那么它工作正常。 我需要知道是否有一种方法可以在不告诉用户禁用他的蜂窝数据的情况下以编程方式执行我想要的操作。

谢谢

【问题讨论】:

  • 嗨@YYjo,你有这个问题的答案吗?
  • @KenRatanachaiS。不幸的是没有。据我所知,它在 android 上效果不佳。

标签: android


【解决方案1】:

尽管只要蜂窝数据处于活动状态,设备就不会 似乎是连接的。如果我禁用蜂窝数据,那么它可以工作 很好。

我遇到了类似的问题。默认解决方案对我不起作用,所以我使用了 Network 类中的 bindSocket 方法,显然它工作得很好。我不知道这个解决方案是否适用于您的问题,但这里有一些代码:

ConnectivityManager connectivityManager = (ConnectivityManager) context.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
Network[] networks = connectivityManager.getAllNetworks();
for(Network network : networks){
   NetworkInfo networkInfo = connectivityManager.getNetworkInfo(network);

   if(networkInfo.getType() == ConnectivityManager.TYPE_WIFI){
       wifiNetwork = network; // Grabbing the Network object for later usage
   }
}

在套接字之后:

if(android.os.Build.VERSION.SDK_INT >= 22) {
   wifiNetwork.bindSocket(socket);
}

更新: 您也可以使用NetworkCallback 来获取Network 对象。

NetworkRequest.Builder builder;
builder = new NetworkRequest.Builder();
builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
ConnectivityManager connectivityManager = (ConnectivityManager) context.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
connectivityManager.requestNetwork(builder.build(), new ConnectivityManager.NetworkCallback() {
   @Override
   public void onAvailable(Network network) {
      wifiNetwork = network;
   }
});

【讨论】:

  • 你从哪里得到那个套接字变量?
  • 抛出 java.net.SocketException: Socket is connected while we try to bindSocket
  • 有没有人知道他从哪里得到那个套接字变量?还是只是一个任意变量?
【解决方案2】:

对于那些仍在试图解决这个问题的人,基于

wifiNetwork.bindSocket(socket)

由@MayconPrado 提供

是的,那个套接字变量是提前声明的。该答案假定您通过网络发送 UDP 或 TCP 数据包。

部分但更完整的代码看起来类似于

val socket = DatagramSocket(somePortNumber)
wifiNetwork.bindSocket(socket)
val udpPacket = DatagramPacket(/** args specific to use case **/)
socket.send(udpPacket)

会对此发表评论,但我从未向 SO 发帖,所以我有 1 个代表 ATM。

【讨论】:

    【解决方案3】:

    您的代码从 Marshmallow 开始看起来是正确的,但请注意您的解决方案在 Lollipop(API 级别 21 和 22)中不起作用。

    问题可能是因为您可能试图在连接 WiFi 网络之后强制应用使用 WiFi 连接。

    您需要将 NetworkCallback BEFORE 更改为您希望仅通过 WiFi 进行通信的 WiFi 网络。这是因为一旦您连接到所需的网络,就会调用 onAvailable() 并执行 bindProcessToNetwork()

    考虑查看my complete solution,我使用了相同的方法,但也支持 Lollipop。我在 Android 版本 5.1.1、6.0、6.0.1、7.1.1 和 8.1.0 中对其进行了测试。

    【讨论】:

      最近更新 更多