Programmatically Connecting to WiFi in Your Xamarin.Forms App

Article summary

With the dawn of the Internet of Things, smart homes, and connected devices, mobile apps have become key elements of creating harmony between everything. Most IoT devices require users to provision their devices on a home wireless network, which can sometimes cause poor user experience. However, apps have the ability to ease these pain points by programmatically connecting to wifi networks.

In this post, I’ll go over how to add this feature to your Xamarin.Forms app. This creates a smoother pairing process for users and their new IoT devices.

Shared Code

To begin, we’ll need to add an interface for the wifi connector. This interface will be implemented by each native wifi connector, both of which will have their own platform-specific version of the ConnectToWiFi method.


namespace MyApp
{
public interface IWifiConnector
 {
  void ConnectToWifi(string ssid, string password);
 }
}

This method will take two strings: the SSID and the password for the network where we want to connect. You can obtain these strings in a number of ways. For example, you could ask the user to manually enter the information. Alternatively, you could hard-code the values. Or you could even use a QR code scanner to obtain the strings from a barcode. For this example, it doesn’t matter how we get the values, as long they’re available when we’re ready to connect.

Both the Android and iOS versions will use the Xamarin.Forms DependencyService to inject each class where it needs to go. But first, you’ll need to register each class by adding the following attribute to each version of the class:


[assembly: Dependency(typeof(WifiConnector))]

To use the WifiConnector, add the following line of code to access the interface from anywhere in your Forms app:


var wifiConnector = Xamarin.Forms.DependencyService.Get();

Android

Connecting to wifi within your Xamarin.Forms Android app requires you to enable two permissions:
CHANGE_WIFI_STATE and ACCESS_WIFI_STATE.
These will be added to the AndroidManifest.xml file.


<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

Xamarin uses the WifiManager class in Android to connect to wifi networks. This manager allows access to wifi information from configured networks to the current wifi state. We will use it to add a new network to the device’s list of configured networks.

The wifi manager is created by grabbing the WifiService from the Android context. The service comes back from the context as a Java object, so we’ll have to cast it as a Xamarin WifiManager to continue.


var wifiManager = (WifiManager)Android.App.Application.Context
                        .GetSystemService(Context.WifiService);

Before we can add the network to our configured networks, though, we have to create a wifi configuration from the SSID and password that were passed into the method. When we create the configuration, we need to make sure to format the strings with extra quotes, as per the Android documentation.


var formattedSsid = $"\"{ssid}\"";
var formattedPassword = $"\"{password}\"";

var wifiConfig = new WifiConfiguration
 {
  Ssid = formattedSsid,
  PreSharedKey = formattedPassword
 };

Now we’ll add the network configuration to our list of configured networks.


var addNetwork = wifiManager.AddNetwork(wifiConfig);

Once we add the network configuration, we can double-check that the network is properly configured. If not, we don’t want to keep trying to connect to it. However, if all is well, we can continue our attempt to connect.


var network = wifiManager.ConfiguredNetworks
                 .FirstOrDefault(n => n.Ssid == ssid);

if (network == null)
 {
  Console.WriteLine($"Cannot connect to network: {ssid}");
  return;
 }

At this point, we’ll need to disconnect from any wireless network where we’re currently connected. Then we can enable the network to create the actual connection.


wifiManager.Disconnect();
var enableNetwork = wifiManager.EnableNetwork(network.NetworkId, true);

Finally, we’re connecting to the network we want. Although Android does not notify the user that their wifi network is changing, it would be helpful to share that information with the user at this point.

iOS

With the release of iOS 11 in Fall 2017, Apple provided a way for developers to implement wifi connections within their apps. This also allowed for any cross-platform frameworks, including Xamarin.Forms, to implement the classes required for configuring wireless networks.

Before we can actually connect to a wifi network from our app, we have to add the Hotspot service to our provisioning profile. You can access this through the Apple Developer Portal.

Xamarin makes use of the NEHotspotConfigurationManager from the NetworkExtensions library to handle connections to wireless networks.


var wifiManager = new NEHotspotConfigurationManager();

Just like Android, the iOS version of the WifiConnector implements the IWifiConnector, so the ConnectToWifi method takes the SSID and password for the requested network. We’ll use these parameters to create a configuration (this time an NEHotSpotConfiguration), passing in the SSID, password, and WEP flag (false because we’re using a WPA/WPA2 connection).


var wifiConfig = new NEHotspotConfiguration(ssid, password, false);

From this, we’ll use the configuration manager we created to “apply” this configuration, passing in a lambda to handle any errors that may occur when trying to connect. If no errors occur, the operating system will notify the user that the app wants to change the wireless network.


wifiManager.ApplyConfiguration(wifiConfig, (error) =>
 {
  if (error != null)
  {
   Console.WriteLine($"Error while connecting to WiFi network {ssid}: {error}");
  }
 });

Once the user selects “Join,” the phone will connect to the network. Success!

Conversation
  • khoicva says:

    Hi, Molly Alger
    How to get the wireless list with NetworkExtensions?
    I tried to find the solution but is no easy
    Can you help me, thanks!

    • Molly Alger Molly Alger says:

      With iOS, it is possible to get a list of the networks that have been configured by your app by calling _wifiManager.GetConfiguredSsids(). The parameter for this will be an action to handle the string array of configured SSIDs, such as removing all the networks. More information about this can be found in the Apple developer docs.

  • khoicva says:

    Hi, Molly Alger

    In a Xamarin IOS project, when I connect to special wireless
    Althought i have enabled Hotspot in provision profile but one error still occur
    Error content is: “Exception of type ‘Foundation.NSErrorException’ was thrown.”

    My source like:
    public async Task ConnectToWifi_IOS(string ssid, string password)
    {
    try
    {
    var config = new NEHotspotConfiguration(ssid, password, false);
    await wifiManager.ApplyConfigurationAsync(config);
    Console.WriteLine(“Connected!”);
    }
    catch (Foundation.NSErrorException error)
    {
    Console.WriteLine(error.Message);
    return false;
    }
    catch (Exception e)
    {
    Console.WriteLine(e.Message);
    return false;
    }
    return true;
    }

  • Hello, how about iOS 9.3 and newer?

    The sample found in iOS 11 before, maybe!

  • @khoicva

    Just set the Entitlements.plist in “Enabled HotSpotConfiguration”, so that found without exception and pop up appearing

  • Gersh says:

    Is this in a public repository?

  • Ingweland says:

    On Android, when searching for configured network, you should query against formattedSsid. So following line var network = wifiManager.ConfiguredNetworks.FirstOrDefault(n => n.Ssid == ssid); should be var network = wifiManager.ConfiguredNetworks.FirstOrDefault(n => n.Ssid == formattedSsid);

  • Robert Auer says:

    Has anyone gotten this to work? Even with the last change from Ingweland, I have yet to make a connection.

    • Maciek says:

      Everything works fine! What problem do you have?

      • Robert Auer says:

        Android side works fine – no problem there.
        This does not work: (Apple side)
        NEHotspotConfigurationManager wifiManager = new NEHotspotConfigurationManager();
        NEHotspotConfiguration wifiConfig = new NEHotspotConfiguration(ssid, password, false);
        wifiManager.ApplyConfiguration(wifiConfig, (error) =>
        {
        if (error != null)
        {
        Debug.WriteLine($”Error while connecting to WiFi network {ssid}: {error}”);
        Thread.CurrentThread.Abort();
        }
        else
        {
        Debug.WriteLine(“Connected!”);
        }
        });

        // make this async
        SocketPermission permission = new SocketPermission(
        NetworkAccess.Connect, // Connection permission
        TransportType.Tcp, // Defines transport types
        “”, // Gets the IP addresses
        SocketPermission.AllPorts // All ports
        );

        // Ensures the code has permission to access a Socket
        permission.Demand();

        Socket Client = null;
        TcpClient ClientSocket = new TcpClient();

        Client = ClientSocket.Client;
        Client.ReceiveBufferSize = 4096;

        try
        {
        Client.Connect(config_ipaddress, config_portnumber);
        }
        catch (Exception ex)
        {
        Client.Disconnect(false);
        Console.WriteLine(“*** Reset the server board. ***”);
        Console.WriteLine(ex);
        Environment.Exit(0);
        }

        Unfortunately – for some odd reason that I am going back and forth on with Microsoft – I can’t write to the console or set a break point in Visual Studio 2017. (using latest version)

  • Alexandre Picquot says:

    Apple is giving me a hard time getting access to the Hotspot service: is there any specific explanation or wording to make sure the request in granted ?

  • Franky says:

    Hello Molly
    Great explanation but I wonder if there is any nugget-plugin that include this functionality. it will help novice programmers.
    thanks

  • Ashok says:

    Hi Molly Alger,

    Please let me know how to get all available Wifi networks list in my XForms.iOS? I can get in XForms.Android using WifiManager.ScanResults property but in iOS i can’t to find the solution. Can you help me.

    Thanks in Advance,
    Ashok N

  • Ashok says:

    Hi Molly Alger,

    Please let me know how to get all available Wifi networks list in my XForms.iOS? I can get in XForms.Android using WifiManager.ScanResults property but in iOS i can’t to find the solution. I am new for iOS, can you help me.

    Thanks in Advance,
    Ashok N

  • Maciek says:

    Hi Molly!

    Thanks for great post ;) I have question.

    I create application “Connecting to WiFi in iOS”. Everything works fine but iOS always asks a question “Wants to Join Wi-Fi Network”. Is there any possibility that it would not ask? For my application, this popup is a problem. Maybe list of preferred network?

    • Victor says:

      Hi Maciek,
      you said that your app works fine, but my Visual Studio 2017 says about GetConfiguredSsidsAsync(), GetConfiguredSsids() and ApplyConfiguration() “To be added”, that means they are not implemented yet. The version of Xamarin.iOS is 4.12.3.77 (it is last version).
      My code is exactly as in this post and comments.
      What Xamarin.iOS.dll do you use? Can you show your code?

  • Victor says:

    Hi Molly,
    My Visual Studio 2017 says about GetConfiguredSsidsAsync(), GetConfiguredSsids() and ApplyConfiguration() “To be added”. The version of Xamarin.iOS is 4.12.3.77 (it is last version).
    Does it mean all example in your post do not working now?

    • Robert Auer says:

      I contacted James Montemagno – he said you can’t programmatically connect to a wifi on an iPhone. The user would have to select the wifi and you go from there. On Android you can, and I have it working in Android in Xamarin.

  • Lucas Sossai says:

    Hi Molly, thank you for the article, it was really good written.
    I have one doubt, I managed to disconnect from my current network and connect to the one I want, but it stays connected for like 2, 3 seconds and go back to the old network. Is this happening to anyone else?

  • Popof says:

    Hi Molly,

    Thanks for the information! Is there also a way to show the list of wifi networks available for both iOS and Android?

  • Comments are closed.