7 Comments

Programmatically Connecting to WiFi in Your Xamarin.Forms App

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!