如何在Android Xamarin.Forms中获取附近WiFi网络列表?

3

我在这个部分上搜索了很多方法,试图让应用程序在附近的 WiFi 网络可用时自我刷新,但是没有任何方法适用于我。所以我尝试查看了这个资源:

如何在 Android 中获取可用的 WiFi 网络并在列表中显示它们

我试图将这段代码转换为 Xamarin.Forms 代码,但是遇到了一些问题:

  1. 如何在 App.xaml 中创建一个 TextView,并从 MainActivity 中填充数据
  2. 我们可以设置哪种 ContentView,以使应用程序正常工作。如何像 SetContentView(Resource.Layout.MainActivity); 一样设置 View(然后创建 ContentView)。
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);
        }
    }
}



@开发者,你可以使用DependencyService在Xamarin.forms中从MainActivity传递数据到PCL,但我不确定你的第二个问题,你想知道如何在Xamarin.forms中获取wifi列表吗? - Cherry Bu - MSFT
是的,我想在Xamarin.Forms中获取附近的WiFi列表。如果出现或消失网络,则必须刷新列表。但是我甚至无法获取一个简单的WiFi列表... - Developper
1个回答

5

关于在Xamarin.forms中获取Wifi列表,我使用DependencyService编写了一个示例。

在PCL中创建接口:

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

}

在Android平台上实现接口

[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;

      
    }

如果希望在一定时间内刷新wifi列表,可以使用计时器(Timer)来实现:
 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
        });

    }

注意:对于WiFi扫描功能,请获取权限。

输入图像描述


哇!那个运行得非常好!我简直不敢相信。谢谢!>) - Developper
我在使用代码 get _wifiService = await _wifiService1.GetAvailableNetworksAsync(); 时遇到了问题,提示对象引用未设置为对象的实例。请帮助我解决。 - shalin gajjar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接