【问题标题】:Better way to detect WiFi enabled/disabled on iOS?在 iOS 上检测 WiFi 启用/禁用的更好方法?
【发布时间】:2017-02-01 08:29:07
【问题描述】:

经过难以置信的咬牙切齿后,我终于有了一种方法,可以成功检测 iOS 上是否启用了 WiFi,而不管它是否连接。这样的东西至少有几个用途,我不认为这违反了 Apple Law(tm) 的精神或文字。

但是,它很丑陋,可能不会永远有效。截至 2017 年 1 月 31 日,它目前适用于 iOS 10.2.1。我将把我的答案放在下面,希望有人可以改进它。我对可达性(不满足要求)、CaptiveNetwork、HotspotHelper、SCNetworkConfiguration、Xamarin 的 System.Net.NetworkInterface 等进行了大量研究。据我所知,这就是它真正有效的方法。

【问题讨论】:

  • CaptiveNetwork,顺便说一句,对于确定设备是否 WiFi很有用: public bool DeviceHasWifi() { string[] sifa; CaptiveNetwork.TryGetSupportedInterfaces(out sifa); // 如果至少有一个接口支持强制网络,那么它有 WiFi 返回 (0 != sifa.Length); }
  • 永远不需要这样的东西。如果您的应用程序需要 WIFI,只需将其写在您的应用程序描述或应用程序的帮助页面上。检查网络类型不是您的工作。
  • 虽然我同意 大多数 应用程序不需要这样的东西,但您对“从不”的概括是没有根据的
  • 我还是坚持从不。如果您的应用在没有 Wifi 的情况下无法连接,只需显示连接错误和帮助页面。从来没有任何用于检查 WIFI 与 Internet 的应用程序。
  • 我有一个用例,我不是您提到的简单的常见场景,我保证您没有想到,并且在对这个问题进行实际研究我遇到过其他人。

标签: ios iphone xamarin wifi


【解决方案1】:

解决方案的要点是,当 getifaddrs() 报告了两个名称为“awdl0”的接口时,WiFi 就会启用。只有一个,它已被禁用。

我感谢 pebble8888 将我指向 https://github.com/alirp88/SMTWiFiStatus,它是 Objective-C,由于缺少 cmets,因此很难理解正在发生的事情或作者的意图。

这是我完整且完整的 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

【讨论】:

  • 好的,我只能说它在所有设备上的所有情况下仍然适用于我,以及我的应用程序的所有用户。也许更具体?
  • 我在iPhong7P和iPhone8上都测试过,都是iOS11。你测试了什么设备/版本?
  • 我在 iOS 10 上亲自测试过 6s,但一个队友运行的是 iOS 11,我们也有很多用户同时运行这两种操作系统,我们从未在这里看到过抱怨.这将是对功能的重大破坏,所以我相信我们会听到它。你不是在模拟器上运行是吗?您是否单步执行了代码并检查了它所迭代的对象的属性?
  • 嗨艾略特,其实我还没有测试过你的 C# 代码。但我测试了 Swift 和 Objective-C 代码,我相信它们具有相同的逻辑来通过“awdl0”检查 WiFi 状态。而且我可以得到 2“awdl0”(我的第一个回复中的错字。它是 2)无论 WiFi 是打开还是关闭。
  • 谢谢@Eliot Gillum,你是对的。它适用于“硬关闭”,而不是“软关闭”
猜你喜欢
  • 2016-06-14
  • 1970-01-01
  • 1970-01-01
  • 2010-10-27
  • 1970-01-01
  • 2012-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多