flutternetwork / WiFiFlutter

Flutter plugin suite for various WiFi services.
https://wifi.flutternetwork.dev
280 stars 174 forks source link

Method native NEHotspotConfigurationManager.shared.removeConfiguration not working on IOS 15 #177

Open mvn-quannguyen2-dn opened 2 years ago

mvn-quannguyen2-dn commented 2 years ago

Hi there,

I am developing an IoT application, your wifi_iot library it helps me a lot in my work, thanks a lot. But now I am facing a problem when using the wifi disconnection function when running the app on IOS 15 device. The specific case is after I connect to wifi using WiFiForIoTPlugin.connect method, then I use WiFiForIoTPlugin.disconnect to disconnect but it doesn't work, although these methods work perfectly when running with IOS 14 and below. I tried to clone the wifi_iot plugin source to install local in the project and debug the plugin's WiFiForIoTPlugin.disconnect method and I see it calls the native removeConfiguration method but nothing happens when calling it. I've tried researching on the internet but haven't seen anyone mention this, maybe iOS 15 is relatively new.

Use wifi_iot 0.3.8 and run it on IOS 15

I look forward to your help, thanks a lot 🙌

mvn-quannguyen2-dn commented 2 years ago

@daadu I look forward to your help, thanks a lot 🙌

daadu commented 2 years ago

CC: @DominikStarke - because he knows iOS environment better.

DominikStarke commented 2 years ago

I just upgraded a phone to iOS 15. Disconnecting from an AP works for me.

A word of warning: If you connect to a known network and disconnect from it, it might happen that the iPhone reconnects to it. You might try the joinOnce flag on connect() and in your phones wifi list ignore your AP.

If this doesn't help please post your entitlements.

mvn-quannguyen2-dn commented 2 years ago

@DominikStarke cc @daadu I see apple released iOS 15.0.1 in the last week, don't know if you are testing the issue on version IOS 15.0 or 15.0.1, as I mentioned above, my project runs fine with iOS 14 and below.

Here is the config ios to using wifi

image image

App requires location permission before getting wifi information

mvn-quannguyen2-dn commented 2 years ago

@DominikStarke This wifi disconnect function on IOS 15 is not stable, sometimes it can disconnect wifi.

A word of warning: If you connect to a known network and disconnect from it, it might happen that the iPhone reconnects to it. You might try the joinOnce flag on connect() and in your phones wifi list ignore your AP.

This warning I know, so the issue I mentioned above, is not in this case

DominikStarke commented 2 years ago

There is no other way to disconnect from networks I'm aware of other than NEHotspotConfigurationManager.shared.removeConfiguration

My test yesterday was with iOS 15.0 and I just retested with 15.0.1. Out of ~200 tests disconnect never failed across multiple iPhones (6, 11).

When disconnecting do you see the "trying to disconnect from 'xxx'" (xxx should be the ssid of your ap) log?

If it doesn't show up can you try to replace disconnect with this snippet:

    if #available(iOS 11.0, *) {
        NEHotspotConfigurationManager.shared.getConfiguredSSIDs { (wifiList) in
            wifiList.forEach {
                print("trying to disconnect from'\($0)'")
                NEHotspotConfigurationManager.shared.removeConfiguration(forSSID: $0)
            }
            result(true)
        }
    } else {
        print("Not disconnected")
        result(nil)
    }

Which is a bit more drastic, as it should disconnect even if the ssid doesn't match.

mvn-quannguyen2-dn commented 2 years ago

@DominikStarke cc @daadu The code you shared above is not working, wifiList.forEach does not return any SSID even though the app is connected to a wifi

When disconnecting do you see the "trying to disconnect from 'xxx'" (xxx should be the SSID of your ap) log?

Yes, when disconnection, I see the log with SSID information, although debug saw the log with SSID information and called the removeConfiguration function, but when running on IOS 15 still can't disconnection, otherwise running on IOS 14 and down, it's normal. My debug picture is below

Screen Shot 2021-10-05 at 6 51 26 PM

DominikStarke commented 2 years ago

Ok, since getConfiguredSSIDs returns nothing:

getConfiguredSSIDs(completionHandler:) Returns the SSIDs or the names of the Wi-Fi hotspot domains that your app has configured and invokes an optional completion handler.

(see https://developer.apple.com/documentation/networkextension/nehotspotconfigurationmanager/2866695-getconfiguredssids)

This same limitation applies to NEHotspotConfigurationManager.shared.removeConfiguration

Your app can use this method to delete a configuration that it has added, but not a configuration added by another app or by the user.

(see https://developer.apple.com/documentation/networkextension/nehotspotconfigurationmanager/2866727-removeconfiguration)

This means if you connected to the AP manually through the iPhones settings screen or a different app you cannot disconnect from it. In order to verify this go the wifi settings screen and ignore the network, then with your app try to connect & disconnect from the wifi again. This is unfortunately a limitation of iOS, which cannot be lifted.

mvn-quannguyen2-dn commented 2 years ago

@DominikStarke Sorry, the restriction you mentioned above, I know that restriction. The wifi I want to disconnect on is a wifi connection by the app, not wifi that was manually entered earlier in the settings of the iPhone or another app. It's weird, it works fine on IOS 14 and below, but not on IOS 15. It's strange that the removeConfiguration function works fine on your device

mvn-quannguyen2-dn commented 2 years ago

@DominikStarke I also Forgot WiFi in my iPhone settings and checked it before connecting with the app

DominikStarke commented 2 years ago

That's weird. Not just my phone. I picked up 6 other iPhones with iOS 15 and 15.0.1 in the office today and none had issues disconnecting.

mvn-quannguyen2-dn commented 2 years ago

@DominikStarke Thank you very much for supporting me, tomorrow I will try it on many other devices and see how it goes

Seraffimo commented 2 years ago

I am having the exact same issue. Code worked fine on iphone, ios 14.7. Upgraded that phone to ios 15.0.2. Changed nothing else, it worked on 14.8, failed on 15.0.2. I tried to create a new SSID across both the AP and the iphone (the upgraded phone) to see if somehow that would work. It did not. Deleting/reinstalling app, does not work. Clean build folders ... etc. did not work. Not sure if it matters, but the iot device I am connecting to (ESP32), is not connected to the internet. Happy to help debug this issue (mnv) if you have not found a solution yet.

I did find that all networking activity from the app does stop. It is just the last step of dropping off the hotspot and reconnecting to the prior wifi ap that does not happen.

mvn-quannguyen2-dn commented 2 years ago

@Seraffimo cc @DominikStarke I still haven't found a solution, the success rate of disconnection is very low on IOS 15, hardly works

Seraffimo commented 2 years ago

After logging a support ticket with Apple and going through several iterations with their engineers, they confirmed it as a repeatable issue on their side. A feedback request has been logged that will eventually become an official bug. Key to the repeatability was having the joinOnce property set to true - and running on 15.X. Logs of same app running on 14.4 and then 15.10 show that the removeConfiguration(forSSID:) does not trigger the auto-join cycle in IOS 15 for some reason.

daadu commented 2 years ago

@Seraffimo Thanks for reporting this with Apple.

Any changes required from our end?

mvn-quannguyen2-dn commented 2 years ago

@Seraffimo cc @daadu Thank you for reporting the above issue to apple and giving me the above solution, the solution of set joinOnce=false worked, but I check on many devices, wifi disconnect error, sometimes still happens, but the probability of it happening is very low. I just discovered a trick that can temporarily solve this problem until Apple takes care of it, that is when connecting to wifi we will call the connection method twice the first time the app connects, then we have can disconnect normally without any problem.

daadu commented 2 years ago

@mvn-quannguyen2-dn do you mean the below from plugin readme?

(1) : On iOS, you can only disconnect from a network which has been added by your app. In order to disconnect from a system network, you have to connect to an other!

mvn-quannguyen2-dn commented 2 years ago

@daadu No, I mean we will call methods connection (WiFiForIoTPlugin.connect) twice repeatedly the first time the app connects to wifi. Of course, disconnect from wifi that is already connected from the app, not the wifi the user connects to in the iPhone settings. It's just a trick to temporarily solve this problem that I'm using

daadu commented 2 years ago

Ok, just curious how is it solving the problem? I'll have to check the sole thread @Seraffimo mentioned.

@Seraffimo can you post the link to the thread?

JooYoo commented 11 months ago

Hey guys. Thanks for create this library. It works good to Flutter Android.

My situation:

NEHotspotNetwork nehelper sent invalid result code [1] for Wi-Fi information request
Not connected to a network
JooYoo commented 10 months ago

The solution for me is the following:

  1. Activate Access Wi-Fi Information capability: AppleDeveloperPortal / Identifiers / [ YOUR APP IDENTIFIER ] / check Access Wi-Fi Information.
  2. Add one more entry in Runner.entitlements as following
<key>com.apple.developer.networking.wifi-info</key>
<true/>
  1. Make sure the app already get the Location permissions.
silaspedrosa commented 10 months ago

What I've recently learned is that you can only call .removeConfiguration for wifi networks your app has connected to. You can get a list of which connections iOS thinks your app has connected to by calling .getConfiguredSSIDs (https://developer.apple.com/documentation/networkextension/nehotspotconfigurationmanager/2866695-getconfiguredssids).

In my case, I was connecting to a device that shows a WiFi Captive Portal. During the short time between connecting to the WiFi and the appearance of the Captive Portal, .getConfiguredSSIDs would return the ssid, but once the CaptivePortal appears, for some reason, .getConfiguredSSIDs doesn't return the ssid anymore, showing that iOS no longer thinks your app configured that ssid.

It might have something to do with the lack of internet from the device's wifi, it could be that the Captive Portal is treated in a specific way by iOS that messes with the .getConfiguredSSIDs. Anyhow, it sounds like a bug. We're going to disable the Captive Portal on our side and see if it solves the issue.