Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mobile Internet doesn't work, after closing the IOT device wifi connection. #385

Open
karthiksensesemi opened this issue Apr 25, 2024 · 9 comments

Comments

@karthiksensesemi
Copy link

I'm using this package for auto-connecting to wifi. Then using the tcp sockets i receive the data.
Later, the IOT device gets disconnected and mobile gets switched to either mobile data or another wifi.

The internet gets blocked, unless i restart the app. The internet doesn't work after the communication.

@GivDavidL
Copy link

I too have this issue, any fix?

@E2-Veera
Copy link

E2-Veera commented Aug 9, 2024

I'm also having this issue any help on this? In my case after IOT device stops the WiFi connection my device should automatically switch to previously configured home wifi.

@karthikmohan4
Copy link

You need to set forceWifiUsage(false) after communicating with IOT device.

@E2-Veera
Copy link

E2-Veera commented Aug 14, 2024

I have handled this feature Natively Please find the source code below with this you can achieve the following (Use method channel to call this native code in flutter)

  1. Connect to WiFi IOT device using ssid and password
  2. Able to communicate to the IOT device using localhost connection
  3. Once the IOT device stops WiFi connection your android mobile will automatically switch to previously configured WiFi connections and also you are able to use the Internet as well within the app

Connection method For Android 10+ devices

public static CompletableFuture<String> connectWifi(MainActivity context, String ssid, String password,boolean useTimeout) {
       CompletableFuture<String> future = new CompletableFuture<>();
       try {
           if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
               Log.d(TAG, "Device is above Android 10....");
               WifiNetworkSpecifier wifiNetworkSpecifier = new WifiNetworkSpecifier.Builder()
                       .setSsid(ssid)
                       .setWpa2Passphrase(password)
                       .build();

               NetworkRequest networkRequest = new NetworkRequest.Builder()
                       .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
                       .setNetworkSpecifier(wifiNetworkSpecifier)
                       .build();

               ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
               ConnectivityManager.NetworkCallback callback =  new ConnectivityManager.NetworkCallback() {

                   // When the IOT device connection is established, the below callback is triggered. And the Mobile Device will be connected to the IOT device.
                   @Override
                   public void onAvailable(Network network) {
                       Log.d(TAG, "Network is available: " + network);
                       //This callback will automatically trigger the WiFi connection Popup
                       // bindProcessToNetwork is used to perform API operations with IOT devices.
                       connectivityManager.bindProcessToNetwork(network);
                       future.complete("connected");
                   }

                   @Override
                   public void onUnavailable() {
                       Log.d(TAG, "Network is unavailable");
                       future.complete("networkUnavailable");
                   }

                   @Override
                   public void onLosing(Network network, int maxMsToLive) {
                       Log.d(TAG, "Network is losing with maxMsToLive: " + maxMsToLive);
                       future.complete("networkLoosing");
                   }

                   // When the IOT device connection is lost, the below callback is triggered. Then the Connectivity Manager is set to null.
                   // So that the WiFi connection can be re-switched to the previously connected WiFi network.
                   @Override
                   public void onLost(Network network) {
                       Log.d(TAG, "Network is lost: " + network);
                       // Setting bindProcessToNetwork null to use the Internet connection After IOT is diconnected.
                       connectivityManager.bindProcessToNetwork(null);
                       // Unregister the callback to enable Network Switching after IOT is diconnected
                       connectivityManager.unregisterNetworkCallback(this);
                       future.complete("networkLost");
                   }
               };

               if (connectivityManager != null) {
                   if(useTimeout) {
                       connectivityManager.requestNetwork(networkRequest,callback,60000);
                   }else{
                       connectivityManager.requestNetwork(networkRequest,callback);
                   }

               } else {
                   Log.d(TAG, "Connectivity Manager is null....");
                   future.complete("notConnected");
               }
           } else {
               Log.d(TAG, "Android level is low so Executing legacy method");
               future.complete(connectToWifiLegacy(context, ssid, password));
           }
       } catch (Exception e) {
           e.printStackTrace();
           Log.e(TAG, "Exception occurred: " + e.getMessage());
           future.completeExceptionally(e);
       }
       return future;
   }

Connection method for Android 10 below devices

 private static String connectToWifiLegacy(MainActivity context, String ssid, String password) {
        try {
            WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
            if (wifiManager == null) {
                return "notConnected";
            }
            WifiConfiguration wifiConfig = new WifiConfiguration();
            wifiConfig.SSID = String.format("\"%s\"", ssid);
            wifiConfig.preSharedKey = String.format("\"%s\"", password);

            // Add the network and connect to it
            int netId = wifiManager.addNetwork(wifiConfig);
            if (netId == -1) {
                return "Failed to add network configuration";
            }
            wifiManager.disconnect();
            wifiManager.enableNetwork(netId, true);
            boolean flag = wifiManager.reconnect();
            Log.d(TAG, "Reconnect result: " + flag);
            return "connected";
        } catch (Exception e) {
            e.printStackTrace();
            Log.e(TAG, "Exception occurred: " + e.getMessage());
            return "exception";
        }
    }

@Bojan227
Copy link

Bojan227 commented Oct 22, 2024

I have handled this feature Natively Please find the source code below with this you can achieve the following (Use method channel to call this native code in flutter)

@E2-Veera
I'm connected to WiFi IOT using ssid and when i switch the mode from AP to AP + STA, then Android and iOS will auto-connect back to my home network. Will this code help me resolve this issue for Andorid? Do you know any solution for an iOS app?

@E2-Veera
Copy link

I have handled this feature Natively Please find the source code below with this you can achieve the following (Use method channel to call this native code in flutter)

@E2-Veera I'm connected to WiFi IOT using ssid and when i switch the mode from AP to AP + STA, then Android and iOS will auto-connect back to my home network. Will this code help me resolve this issue for Andorid? Do you know any solution for an iOS app?

Above android solution perfectly working for me dor iOS I've used the following swift code for WiFi Connection, By using this when your IoT device stops the wifi connection then iPhone will automatically switch to Home WiFi


import Foundation
import NetworkExtension
import SystemConfiguration.CaptiveNetwork

enum WifiStatus: String {
    case connected = "connected"
    case alreadyConnected = "alreadyConnected"
    case notConnected = "notConnected"
    case platformNotSupported = "platformNotSupported"
    case profileAlreadyInstalled = "profileAlreadyInstalled"
    
    func stringValue() -> String {
        return self.rawValue
    }
}

class WifiHelper {
    func connectToWifi(ssid: String, password: String, result: @escaping (String) -> Void) {
        if #available(iOS 11.0, *) {
            let configuration = NEHotspotConfiguration(ssid: ssid, passphrase: password, isWEP: false)
            NEHotspotConfigurationManager.shared.removeConfiguration(forSSID: ssid)
            
            NEHotspotConfigurationManager.shared.apply(configuration) { (error) in
                if let error = error {
                    if error.localizedDescription == "already associated." {
                        result(WifiStatus.alreadyConnected.stringValue())
                    } else {
                        if (error as NSError).code == 10 {
                            result(WifiStatus.profileAlreadyInstalled.stringValue())
                        } else {
                            result(WifiStatus.notConnected.stringValue())
                        }
                    }
                } else {
                    if self.isConnectedToCorrectWifi(wifiToCompareWith: ssid) {
                        result(WifiStatus.connected.stringValue())
                    } else {
                        result(WifiStatus.notConnected.stringValue())
                    }
                }
            }
        } else {
            result(WifiStatus.notConnected.stringValue())
        }
    }
    }

Please note that you have to Enable Local Network Permission to communicate with IoT devices for that you need to add the below permission in info.plist NSLocationAlwaysUsageDescription

@Bojan227
Copy link

Bojan227 commented Oct 23, 2024

@E2-Veera
Thank you for your answer. Is there a way to prevent connecting to the home wifi and just connect to the IoT device automatically. What I'm doing is the following, I'm connecting to the IoT device, making a request, after the request the IoT device reboots and I want to reconnect again to the same IoT device, but not to the home wifi..

I'm doing the same from my laptop, but the windows laptop won't switch the network which is an optimal solution for me...

@E2-Veera
Copy link

@E2-Veera Thank you for your answer. Is there a way to prevent connecting to the home wifi and just connect to the IoT device automatically. What I'm doing is the following, I'm connecting to the IoT device, making a request, after the request the IoT device reboots and I want to reconnect again to the same IoT device, but not to the home wifi..

I'm doing the same from my laptop, but the windows laptop won't switch the network which is an optimal solution for me...

If want to connect to the same IoT after disconnection then you have to request the connection again.
Android:
In android Once the Iot stops the wifi connection then onLost() callback will trigger and in that we are unregitering the network associated with it. So in the onLost callback change your logic to connect again. In android Q and above version this will work without user consent (for the 1st time only user will prompt with connect or cancel popup),

iOS:
but in iOS when you request for WiFi connection user will prompt with a dialog box. Without user consent you can't connect any wifi within the app on iOS environment.

@Bojan227
Copy link

@E2-Veera Thanks a lot, that makes sense.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants