Warm tip: This article is reproduced from serverfault.com, please click

How to get list of nearby WiFi Networks in Android Xamarin.Forms?

发布于 2020-11-29 16:33:45

I have searched a lot of ways on this part, on how to get a self refreshing app when getting nearby WiFi networks. But nothing has ever worked for me. So I just have tried to check this resource> How to get available wifi networks and display them in a list in android

I tried to "convert" this code into Xamarin.Forms code, but there are some issues.

  1. How to create in App.xaml a TextView, then to populate it with data from MainActivity
  2. What Content View we can set here that the app will properly work. How to set as View like Resources->Layout-> Get Main Activity (and then to create Content view). Like SetContentView(Resource.Layout.MainActivity);
using System;
using Android.App;
using Android.Content.PM;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Android.Content;
using System.Collections.Generic;
using Android.Net.Wifi;
using System.Text;
using Java.Lang;
using Xamarin.Forms;
using StringBuilder = System.Text.StringBuilder;
using Menu = Android.Views.Menu;

namespace MyApp.Droid
{
    [Activity(Label = "MyApp", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize)]
    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
    {
        static TextView mainText;
        readonly Context context = Android.App.Application.Context;
        static WifiManager mainWifi;
        WifiReceiver receiverWifi;
        static List<ScanResult> wifiList;
        readonly System.Text.StringBuilder sb = new System.Text.StringBuilder();

        protected override void OnCreate(Bundle savedInstanceState)
        {
            /* Default MainActivity Data--------------------------*/
            base.OnCreate(savedInstanceState);
            TabLayoutResource = Resource.Layout.Tabbar;
            ToolbarResource = Resource.Layout.Toolbar;
            global::Xamarin.Forms.Forms.Init(context, savedInstanceState);

            /*-------------------------------------------------------*/

            SetContentView();//Here must be set the main content view ???????
            mainText = (TextView)FindViewById(Resource.Id.); // Here must get TextView Id  ???????
            mainWifi = (WifiManager)GetSystemService(Context.WifiService);

            if (mainWifi.IsWifiEnabled == false)
            {
                // If wifi disabled then enable it
                Toast.MakeText(context, "wifi is disabled..making it enabled", ToastLength.Long).Show();
                mainWifi.SetWifiEnabled(true);
            }
            receiverWifi = new WifiReceiver();
            RegisterReceiver(receiverWifi, new IntentFilter(WifiManager.ScanResultsAvailableAction));
            mainWifi.StartScan();
            char[] mine = "Starting Scan...".ToCharArray();
            int length = mine.Length;
            mainText.SetText(mine, 0, length);

            Xamarin.Essentials.Platform.Init(this, savedInstanceState);
            global::Xamarin.Forms.Forms.Init(this, savedInstanceState);

            LoadApplication(new App());
        }


        public override bool OnCreateOptionsMenu(IMenu menu)
        {
            menu.Add(0, 0, 0, "Refresh");
            return base.OnCreateOptionsMenu(menu);

        }

        public override bool OnContextItemSelected(IMenuItem item)
        {
            mainWifi.StartScan();
            char[] mine = "Starting Scan...".ToCharArray();
            int length = mine.Length;
            mainText.SetText(mine, 0, length);
            return base.OnContextItemSelected(item);

        }

        protected override void OnPause()
        {
            RegisterReceiver(receiverWifi, new IntentFilter(WifiManager.ScanResultsAvailableAction));
            base.OnPause();
        }

        protected override void OnResume()
        {
            RegisterReceiver(receiverWifi, new IntentFilter(WifiManager.ScanResultsAvailableAction));
            base.OnResume();
        }


        // Broadcast receiver class called its receive method
        // when number of wifi connections changed

        private class WifiReceiver : BroadcastReceiver
        {

            // This method call when number of wifi connections changed
            public override void OnReceive(Context context, Intent intent)
            {
                if (intent.Action.CompareTo(WifiManager.ScanResultsAvailableAction) == 0)
                {
                    var sb = new StringBuilder();
                    wifiList = (List<ScanResult>)mainWifi.ScanResults;
                    sb.Append("\n        Number Of Wifi connections :" + wifiList.Count + "\n\n");

                    for (int i = 0; i < wifiList.Count; i++)
                    {

                        sb.Append(new Integer(i + 1).ToString() + ". ");
                        sb.Append(wifiList[i].ToString());
                        sb.Append("\n\n");
                    }
                    char[] sb_t = (sb.ToString()).ToCharArray();
                    
                    mainText.SetText(sb_t,0,sb_t.Length);
                }
            }
        }

        public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
        {
            Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);

            base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
        }
    }
}


Questioner
Developper
Viewed
0
Cherry Bu - MSFT 2020-12-01 12:07:44

About getting Wifi list in Xamarin.forms, I do one sample using DependencyService.

Creating interface in PCL:

 public interface IWifi
{
    Task<IEnumerable<string>> GetAvailableNetworksAsync();

}

Implementing the interface on Android platform

[assembly: Xamarin.Forms.Dependency(typeof(ListWifi.Droid.Wifi))]
namespace ListWifi.Droid
{
[Activity(Label = "ListWifi", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize )]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
    protected override void OnCreate(Bundle savedInstanceState)
    {
        TabLayoutResource = Resource.Layout.Tabbar;
        ToolbarResource = Resource.Layout.Toolbar;

        base.OnCreate(savedInstanceState);

        Xamarin.Essentials.Platform.Init(this, savedInstanceState);
        global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
        LoadApplication(new App());
    }
    public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
    {
        Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);

        base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
    }
}

public class Wifi : IWifi
{
    private Context context = null;

    public Wifi()
    {
        this.context = Android.App.Application.Context;
    }

    public async Task<IEnumerable<string>> GetAvailableNetworksAsync()
    {
        IEnumerable<string> availableNetworks = null;

        // Get a handle to the Wifi
        var wifiMgr = (WifiManager)context.GetSystemService(Context.WifiService);
        var wifiReceiver = new WifiReceiver(wifiMgr);

        await Task.Run(() =>
        {
            // Start a scan and register the Broadcast receiver to get the list of Wifi Networks
            context.RegisterReceiver(wifiReceiver, new IntentFilter(WifiManager.ScanResultsAvailableAction));
            availableNetworks = wifiReceiver.Scan();
        });

        return availableNetworks;
    }

 
    [BroadcastReceiver(Enabled = true, Exported = false)]
    class WifiReceiver : BroadcastReceiver
    {
        private WifiManager wifi;
        private List<string> wifiNetworks;
        private AutoResetEvent receiverARE;
        private Timer tmr;
        private const int TIMEOUT_MILLIS = 20000; // 20 seconds timeout

        public WifiReceiver()
        {

        }
        public WifiReceiver(WifiManager wifi)
        {
            this.wifi = wifi;
            wifiNetworks = new List<string>();
            receiverARE = new AutoResetEvent(false);
        }

        public IEnumerable<string> Scan()
        {
            tmr = new Timer(Timeout, null, TIMEOUT_MILLIS, System.Threading.Timeout.Infinite);
            wifi.StartScan();
            receiverARE.WaitOne();
            return wifiNetworks;
        }

        public override void OnReceive(Context context, Intent intent)
        {
            IList<ScanResult> scanwifinetworks = wifi.ScanResults;
            foreach (ScanResult wifinetwork in scanwifinetworks)
            {
                wifiNetworks.Add(wifinetwork.Ssid);
            }

            receiverARE.Set();
        }

        private void Timeout(object sender)
        {
            // NOTE release scan, which we are using now, or we throw an error?
            receiverARE.Set();
        }
    }
}


}

MainPage.xaml:

 <StackLayout>
    <ListView x:Name="wifilist">
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <StackLayout>
                        <Label Text="{Binding .}" />
                    </StackLayout>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

    <Button
        x:Name="btn1"
        Clicked="btn1_Clicked"
        Text="get wifi list" />
</StackLayout>

Mainpage.cs:

private async void btn1_Clicked(object sender, EventArgs e)
    {
        _wifiService = await DependencyService.Get<IWifi>().GetAvailableNetworksAsync();
        wifilist.ItemsSource = _wifiService;

      
    }

If you want to refresh wifi list in some time, you can use Timer to do this:

 private async void btn1_Clicked(object sender, EventArgs e)
    {
        //_wifiService = await DependencyService.Get<IWifi>().GetAvailableNetworksAsync();
        //wifilist.ItemsSource = _wifiService;

        Device.StartTimer(new TimeSpan(0, 0, 60), () =>
        {
            // do something every 60 seconds
            Device.BeginInvokeOnMainThread(async() =>
            {
                _wifiService = null;
                _wifiService = await DependencyService.Get<IWifi>().GetAvailableNetworksAsync();
                wifilist.ItemsSource = _wifiService;
            });
            return true; // runs again, or false to stop
        });

    }

Note: for WiFi Scanning, please permission.

enter image description here