Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a WiFi without Internet Connection

Tags:

android

In my app I am connecting to a device that has it's own WiFi network. In android 6 and above the system asks me after a few seconds if I want to connect to this network even though there is no internet connection. Only after approving that message I can connect to my device. I tried connecting to the network programmatically and not force the user to go to his settings and connect manually every time. I used the following code to connect to the devices network:

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;
        }
    }
}

and also trying to force the app to use the WiFi connection and not the cellular data I am using :

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);
                    }
                }
            }
        });

    }

Although as long as the Cellular data is active the device doesn't apear to be connected. If I disable the Cellular data then it works fine. I need to know if there is a way to do what I want programmatically without telling the user to disable his Cellular data.

Thanks

like image 814
YYJo Avatar asked Feb 19 '17 16:02

YYJo


2 Answers

Although as long as the Cellular data is active the device doesn't apear to be connected. If I disable the Cellular data then it works fine.

I was facing a similar problem. The default solution didn't work for me so I used the bindSocket method from Network class, and apparently it is working just fine. I don't know if this solution applies to your problem, but here's some code:

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
   }
}

and after the socket:

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

UPDATE: You can use a NetworkCallback to grab the Network object as well.

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;
   }
});
like image 176
Maycon Prado Avatar answered Oct 28 '22 07:10

Maycon Prado


For those still attempting to figure this out, based on the

wifiNetwork.bindSocket(socket)

provided by @MayconPrado

Yes, that socket variable was declared ahead of time. That answer assumes you are sending UDP or TCP packets over the network.

The partial but more complete code would look something along the lines of

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

Would have commented this, but I have never posted to SO, so I have 1 rep ATM.

like image 44
Marshall Ladd Avatar answered Oct 28 '22 07:10

Marshall Ladd