在iOS上检测WiFi启用/禁用的更好方法是什么?

时间:2017-02-01 00:29:08

标签: ios iphone xamarin wifi

在令人难以置信的牙齿咬牙切齿之后,我终于有了一种方法可以成功检测iOS上是否启用了WiFi,无论它是否已连接。这种事情至少有几种用途,我不认为这违反了Apple Law(tm)的精神或文字。

然而,它很丑陋,可能永远不会工作。它目前适用于iOS 10.2.1,截至2017年1月31日。我将在下面给出我的答案,并希望有人可以改进它。我对Reachability(不符合要求),CaptiveNetwork,HotspotHelper,SCNetworkConfiguration,Xamarin的System.Net.NetworkInterface等进行了大量研究。这实际上就是我能说的。

1 个答案:

答案 0 :(得分:1)

解决方案的要点是当getifaddrs()报告的两个接口名称为" awdl0"然后启用WiFi。只有一个,它被禁用了。

我认为pebble8888指的是https://github.com/alirp88/SMTWiFiStatus,这是Objective-C,缺乏评论使得很难理解发生了什么或者作者的意图是什么。< / p>

这是我完整而完整的Xamarin / C#解决方案,对任何其他主要语言用户来说都应该是非常易读的:

using System;
using System.Runtime.InteropServices;

namespace Beacon.iOS
{
/// <summary>
/// code stolen from the Xamarin source code to work around goofy interactions between
/// the good-god-why-would-it-work-that-way iOS and the entirely reasonable Xamarin
/// (it doesn't report interfaces that are reported multiple times)
/// </summary>
class XamHack
{
    //
    // Types
    //
    internal struct ifaddrs
    {
#pragma warning disable 0649
        public IntPtr ifa_next;
        public string ifa_name;
        public uint ifa_flags;
        public IntPtr ifa_addr;
        public IntPtr ifa_netmask;
        public IntPtr ifa_dstaddr;
        public IntPtr ifa_data;
#pragma warning restore
    }

    //
    // OS methods
    //
    [DllImport("libc")]
    protected static extern int getifaddrs(out IntPtr ifap);

    [DllImport("libc")]
    protected static extern void freeifaddrs(IntPtr ifap);


    //
    // Methods
    //

    /// <summary>
    /// Our glorious hack.  I apologize to the programming gods for my sins
    /// but this works (for now) and functionality trumps elegance.  Even this.
    /// Reverse engineered from: https://github.com/alirp88/SMTWiFiStatus
    /// </summary>
    public static bool IsWifiEnabled()
    {
        int count = 0;
        IntPtr ifap;

        // get the OS to put info about all the NICs into a linked list of buffers
        if (getifaddrs(out ifap) != 0)
            throw new SystemException("getifaddrs() failed");

        try
        {
            // iterate throug those buffers
            IntPtr next = ifap;
            while (next != IntPtr.Zero)
            {
                // marshall the data into our struct
                ifaddrs addr = (ifaddrs)Marshal.PtrToStructure(next, typeof(ifaddrs));

                // count the instances of the sacred interface name
                if ("awdl0" == addr.ifa_name)
                    count++;

                // move on to the next interface
                next = addr.ifa_next;
            }
        }
        finally
        {
            // leaking memory is for jerks
            freeifaddrs(ifap);
        }

        // if there's two of the sacred interface, that means WiFi is enabled.  Seriously.
        return (2 == count);
    }

} // class
} // namespace