wifi on iOS

RobertAuerRobertAuer USMember ✭✭

I'm trying to connect to wifi in iOS. I have the Android wifi working great.

The code I'm running in Main.cs is below. Any pointers are appreciated.

using System;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using NetworkExtension;
using TLXStatus.Droid;
using TLXStatus.iOS;
using UIKit;

[assembly: DefaultDependency(typeof(IWifiConnector))]

namespace TLXStatus.iOS { } 

public class Application
{

    static async Task Main(string[] args)
    {
        // if you want to use a different Application Delegate class from "AppDelegate"
        // you can specify it here.
        UIApplication.Main(args, null, "AppDelegate");

        bool x = await ConnectWpa("TLX_F8F005F4DF6B", "");

        var config = new NEHotspotConfiguration("TLX_F8F005F4DF6B", "", false);
        config.JoinOnce = false;
    }

Task<bool> ConnectWpa(string ssid, string password)
{
    try
    {
        var wifiConfig = new NEHotspotConfiguration(ssid, password, false) { JoinOnce = true };
        var wifiManager = new NEHotspotConfigurationManager();

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

        Console.WriteLine("Connected!");
        return Task.FromResult(true);
    }
    catch (Foundation.NSErrorException error)
    {
        Console.WriteLine(error.ToString());
        return Task.FromResult(false);
    }
    catch (Exception e)
    {
        Console.WriteLine(e.ToString());
        return Task.FromResult(false);
    }
}

IWifiConnector wifiConnector;

public interface IWifiConnector
{
    void ConnecttoWifi(string ssid, string password);
}

Best Answer

  • RobertAuerRobertAuer US ✭✭
    Accepted Answer

    NEHotspotConfiguration is for Apple. If you want to connect to Android - you can use the following to get you started.

    This code will make a wi-fi connection in Android. I put this in MainActivity. There may be a better place to put this.

            Socket Client = null;
            TcpClient ClientSocket = new TcpClient();
    
            WifiConfiguration WifiConfig = new WifiConfiguration
            {
                Ssid = formattedSsid,
                PreSharedKey = formattedPassword
            };
    
            int AddNetwork = wifiManager.AddNetwork(WifiConfig);
            WifiConfiguration network = wifiManager.ConfiguredNetworks.FirstOrDefault(n => n.Ssid == formattedSsid);
    
            if (network == null)
            {
                Console.WriteLine($"Cannot connect to network: {ssid} ");
                Console.WriteLine(System.Environment.NewLine);
                return;
            }
            else
            {
                Console.WriteLine($"Connected to: { ssid }");
            }
    
            wifiManager.Disconnect();
            bool enableNetwork = wifiManager.EnableNetwork(network.NetworkId, true);
    
            if (enableNetwork)
            {
                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();
                Thread.Sleep(1000);  // This must be here or we don't make the connection to the "server"
    
                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);
                    System.Environment.Exit(0);
                }
            }
    

    Once you are connected you can send using Client.Send

Answers

  • jym92jym92 Member

    Hi,

    I have a similar project where I want to connect my app to a specific wifi on Android and IOS ...

    Do you find a solution ?
    This code working on Droid app Part ?

    Thanks,

  • RobertAuerRobertAuer USMember ✭✭

    The android side is working, and I have made some progress on the Apple side. This is the code I am using on the Android side for WiFi, set your own port number & ip address. This is in my MainActivity.cs Once I get the bytes - I break them down into the "chunks" I need and use MVVM to update the display.

            Socket Client = null;
            TcpClient ClientSocket = new TcpClient();
    
            WifiConfiguration WifiConfig = new WifiConfiguration
            {
                Ssid = formattedSsid,
                PreSharedKey = formattedPassword
            };
    
            int AddNetwork = wifiManager.AddNetwork(WifiConfig);
            WifiConfiguration network = wifiManager.ConfiguredNetworks.FirstOrDefault(n => n.Ssid == formattedSsid);
    
            if (network == null)
            {
                Console.WriteLine($"Cannot connect to network: {ssid} ");
                Console.WriteLine(System.Environment.NewLine);
                return;
            }
            else
            {
                Console.WriteLine($"Connected to: { ssid }");
            }
    
            wifiManager.Disconnect();
            bool enableNetwork = wifiManager.EnableNetwork(network.NetworkId, true);
    
            if (enableNetwork)
            {
                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();
                Thread.Sleep(1000);  // This must be here or we don't make the connection to the "server"
    
                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);
                    System.Environment.Exit(0);
                }
            }
            else
            {
                Console.WriteLine("Unable to enable network.");
                System.Environment.Exit(0);
            }
    

    I use this to make the call which I put in a try catch.

                    Client.Send(Encoding.ASCII.GetBytes("{\"command\":\"update\"}"));
                    Thread.Yield();
                    Client.Receive(buffer: InStream);
                    Thread.Yield();
    

    On the Apple side, the code is similar, but I'm getting hung on Apple permissions. I would like to run both Android and Apple async but I haven't gotten that far yet.

            var config = new NEHotspotConfiguration(ssid, password, isWep: false);
            config.JoinOnce = false;
    
            var tcs = new TaskCompletionSource<NSError>();
            NEHotspotConfigurationManager.SharedManager.ApplyConfiguration(config, err => tcs.SetResult(err));
            var error = tcs.Task; //await tcs.Task;
            if (error != null)
            {
                var alert = new UIAlertController
                {
                    Title = "Error",
                    Message = error.ToString()
                };
            }
    
            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();
            Thread.Sleep(1000);  // This must be here or we don't make the connection to the "server"
    
            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);
                Debug.WriteLine("*** Reset the server board. ***");
                Debug.WriteLine(ex);
                System.Environment.Exit(0);
            }
    
            while (true)
            {
                Thread.Yield();
                try
                {
                    Client.Send(Encoding.ASCII.GetBytes("{\"command\":\"update\"}"));
                    Thread.Yield();
                    Client.Receive(buffer: InStream);
                    Thread.Yield();
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Reset Board. Error receiving data from host " + ex.Message);
                    return;  // Just move to the next iteration of the while loop. We may want to set a maximum number of this happening. 
                }
    

    Good luck.

  • jym92jym92 Member

    Hi, thanks for your answer !

    finally, I have decided to seperate the job in two part, droid and IOS part.

    So in my Xamarin form project, I create two content page, one for IOS and one for android, on Ios side I advice the user to manually connect to the good wifi. But on the droid page I want to do automacticly.

    It's IOT project, I know the ssid and pasword.

    But my solution not working because I have some reference errors....

    Sorry, I came from C embeded and I'm a new guy in Xamarin C#

    So in my Droid page I did it :

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    using Xamarin.Forms;
    using Xamarin.Forms.Xaml;
    
    
    using System.Runtime.CompilerServices;
    using NetworkExtension;
    using UIKit;
    
    
    [assembly: DefaultDependency(typeof(IWifiConnector))]
    
    namespace lelab.Views
    {
        [XamlCompilation(XamlCompilationOptions.Compile)]
        public partial class RecPageDroid : ContentPage
        {
            public RecPageDroid ()
            {
                InitializeComponent ();
            }
    
            void ConnexionButtonClick(object sender, System.EventArgs e)
                    {
                        int reponse = 0;
                        reponse = ConnectWpa("ESA_wifi_0003", "12345678");
                        if (reponse > 0)
                        {
                            ConnexionStateLabel.Text = "Connecté";
                            ConnexionButton.Background = "Green";
                        }
                        else
                        {
                            ConnexionStateLabel.Text = "Déconnecté";
                            ConnexionButton.Background = "Red";
                        }
                    }
    
            // wifi task
            public int ConnectWpa(string ssid, string password)
                {
                    try
                    {
    
                        var wifiConfig = new NEHotspotConfiguration(ssid, password, false) { JoinOnce = true };
                        var wifiManager = new NEHotspotConfigurationManager();
    
                        wifiManager.ApplyConfiguration(wifiConfig, (error) =>
                        {
                            if (error != null)
                            {
                                Console.WriteLine($"Error while connecting to WiFi network {ssid}: {error}");
                            }
                        });
    
                        Console.WriteLine("Connected!");
                        return 1;
                    }
                    catch (Foundation.NSErrorException error)
                    {
                        Console.WriteLine(error.ToString());
                        return 0;
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.ToString());
                        return 0;
                    }
                }
        }
    }
    

    Do you have any advices ?

  • RobertAuerRobertAuer USMember ✭✭
    Accepted Answer

    NEHotspotConfiguration is for Apple. If you want to connect to Android - you can use the following to get you started.

    This code will make a wi-fi connection in Android. I put this in MainActivity. There may be a better place to put this.

            Socket Client = null;
            TcpClient ClientSocket = new TcpClient();
    
            WifiConfiguration WifiConfig = new WifiConfiguration
            {
                Ssid = formattedSsid,
                PreSharedKey = formattedPassword
            };
    
            int AddNetwork = wifiManager.AddNetwork(WifiConfig);
            WifiConfiguration network = wifiManager.ConfiguredNetworks.FirstOrDefault(n => n.Ssid == formattedSsid);
    
            if (network == null)
            {
                Console.WriteLine($"Cannot connect to network: {ssid} ");
                Console.WriteLine(System.Environment.NewLine);
                return;
            }
            else
            {
                Console.WriteLine($"Connected to: { ssid }");
            }
    
            wifiManager.Disconnect();
            bool enableNetwork = wifiManager.EnableNetwork(network.NetworkId, true);
    
            if (enableNetwork)
            {
                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();
                Thread.Sleep(1000);  // This must be here or we don't make the connection to the "server"
    
                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);
                    System.Environment.Exit(0);
                }
            }
    

    Once you are connected you can send using Client.Send

  • RobertAuerRobertAuer USMember ✭✭

    Please ignore the "accepted answer" tag above - I inadvertently clicked the wrong button.

  • WelingtonBRWelingtonBR Member ✭✭

    Hi Robert,

    May be I'm facing some problems like you. I have to connecto to a specific network and my android code working perfectly.
    My iOS code is very simple but it don't connect, maybe due to entitlement problems. Can you check this post?

    https://forums.xamarin.com/discussion/comment/352214#Comment_352214

    Best Regards,

  • WelingtonBRWelingtonBR Member ✭✭

    Please, could you share the code you ask for user to connect to wifi?

  • RobertAuerRobertAuer USMember ✭✭

    bool isConnected = new NetworkReachability(new IPAddress(0)).TryGetFlags(out NetworkReachabilityFlags flags);

            if (!isConnected)
            {
                await App.Current.MainPage.DisplayAlert("WifiStatus", "No Wifi", "Close");
            }
            else
            {
                await App.Current.MainPage.DisplayAlert("WifiStatus", "Wifi Available", "Close");
            }
    

    Is what I have - but I haven't tested it yet. I'm still trying to get my ViewModel to work in iOS.

  • Hi guys,
    have anyone working code using

    var wifiConfig = new NEHotspotConfiguration(ssid, password, false) { JoinOnce = true };
    var wifiManager = new NEHotspotConfigurationManager();
    wifiManager.ApplyConfiguration(...
    ?

    In my case I see message Error Domain=NEHotspotConfigurationErrorDomain Code=8 "internal error"
    UserInfo={NSLocalizedDescription=internal error.}

    And VS2017 says about NEHotspotConfigurationManager "To be added". If I understand true, it means that this method is not implemented yet.

  • RobertAuerRobertAuer USMember ✭✭
    Correct. iOS you can’t programmatically connect (per James Montemagno) Android you can. I have code for programmaticly connect in Android. If you want it just email me and I’ll send it to you. [email protected]
  • VictorDenisenkoVictorDenisenko Member
    edited December 2018

    Hi Robert,
    you're very kind, but Android version I have working too :-). If there is "To be added", I hope it will be added some time :smile:
    I found just now that Apple WAC (Wireless Accessory Configuration) allows to do that.
    Did you try it?

  • RobertAuerRobertAuer USMember ✭✭

    Sorry I was off on another project for awhile... I have not tried that yet - but I will! Thanks!!

  • RobertAuerRobertAuer USMember ✭✭

    I checked the Wireless Accessory Configuration "box" but I still get the same result. I hear of people being able to connect if they are iOS 11+ but I'm on 12 and I still can't make a wi-fi connection on the Apple side. In an exchange with James Montemagno a few months back - he said you couldn't do it.

Sign In or Register to comment.