【问题标题】:iPhone Wifi on or off?iPhone Wifi 开启还是关闭?
【发布时间】:2012-10-16 01:04:32
【问题描述】:

在 iOS 框架中,如何检查用户是否启用了 Wifi 无线电?请注意,我对通过 Wifi 的可达性不感兴趣,而是对设备是否被用户关闭感兴趣。谢谢。

【问题讨论】:

  • 你的意思是专门针对用户的吗?
  • Ravi 和 Magma,我有一个应用程序,我需要在代码中检查用户是否关闭了 Wifi 设备或它是否处于打开状态。如果我错了,请纠正我,但根据我的理解,可达性提供了您是否可以通过 Wifi 接口访问互联网的信息,而不是关于其开/关状态的信息。
  • 我一句话——你不能。见彼得的回答
  • 我的回答中有一个骇人听闻的解决方案:stackoverflow.com/questions/29487270/…

标签: iphone ios wifi


【解决方案1】:

基于:http://www.enigmaticape.com/blog/determine-wifi-enabled-ios-one-weird-trick

Wifi 状态可以使用基于 C 的 ifaddress 结构来确定为 ON/OFF:

ifaddrs.h 和

net/if.h

[代码来源:未知。]

- (BOOL) isWiFiEnabled {

    NSCountedSet * cset = [NSCountedSet new];

    struct ifaddrs *interfaces;

    if( ! getifaddrs(&interfaces) ) {
        for( struct ifaddrs *interface = interfaces; interface; interface = interface->ifa_next) {
            if ( (interface->ifa_flags & IFF_UP) == IFF_UP ) {
                [cset addObject:[NSString stringWithUTF8String:interface->ifa_name]];
            }
        }
    }

    return [cset countForObject:@"awdl0"] > 1 ? YES : NO;
}

Swift 3 版本(需要带有#include <ifaddrs.h> 的桥接头):

func isWifiEnabled() -> Bool {
    var addresses = [String]()

    var ifaddr : UnsafeMutablePointer<ifaddrs>?
    guard getifaddrs(&ifaddr) == 0 else { return false }
    guard let firstAddr = ifaddr else { return false }

    for ptr in sequence(first: firstAddr, next: { $0.pointee.ifa_next }) {
        addresses.append(String(cString: ptr.pointee.ifa_name))
    }

    freeifaddrs(ifaddr)
    return addresses.contains("awdl0")
}

【讨论】:

  • 这确实有效!它基于以下出色的分析:enigmaticape.com/blog/…
  • 注意:在我的 iPhone 4s (iOS 8.3) 上,这很遗憾总是返回 NO - 无论 Wi-Fi 的状态如何。
  • 记得在使用完接口后调用 freeifaddrs。
【解决方案2】:

正如@magma 评论中提到的,您可能必须使用可达性源代码。 到目前为止,根据我的经验和其他人一直在谈论的内容,没有布尔值可以告诉您用户是否在“设置”中关闭了 Wi-Fi。通过检查设备是否可以访问互联网,您只需推断并得出结论(假设)用户已关闭 Wi-Fi。

【讨论】:

    【解决方案3】:

    使用可达性是正确的方法。

    您无法访问应在 App Store 上发布的应用程序中的直接设置。 这被视为应用程序根本没有理由处理的私人用户领域。

    但如果没有更多解释,我并不认为需要找出设置。

    这不是应用程序应该感兴趣或担心的。您有网络访问权限,或者您没有网络访问权限。如果没有可用的,那么它的原因并不重要。

    您不会问诸如“您没有福特吗?”之类的问题。 “你没有宝马吗?”而不是从一个好的应用程序设计中问“你有车吗?”

    Raechability 也与互联网无关。它会告诉您设备理论上是否可以通过 TCP/IP 网络访问。这意味着一些网络通信可用。然后您可以检查什么类型(例如 Wifi 与 3G/LTE)。这正是 Reachability 的用途。

    如果您出于某种原因真的想在收音机打开并且它是针对一种企业应用程序的情况下关闭,您可以查看私有框架,导入它们并处理它们未记录的方法,这些方法受制于随任何更新而改变。

    对于 Wifi,应该是:/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/PrivateFrameworks/MobileWiFi.framework

    【讨论】:

    • 当你说“没有理由......根本......”时要小心你的应用程序可能想要有礼貌,并且只在 wifi 上上传分析信息而不用完用户的配额(并非世界上每个人都有无限的计划)。您可能不想通过手机网络下载 500 MB 的可选游戏数据,或者像 Apple 的 AppStore 应用一样,拒绝通过手机连接下载超过一定大小的应用。
    • 另一种您可能关心 WiFi 开启或关闭(特别是与外部实体无关)的情况是在多点连接环境中,打开 wifi 是可选的,但可以改善用户体验可衡量的。
    • 另一个想知道 WiFi 是打开还是关闭的原因是您是否正在监视地理区域。如果打开wifi,进入/退出事件会更加及时和准确。在小区域的情况下,没有 wifi,可能会完全错过该区域,并且不会生成任何事件。在 Wifi 关闭的情况下,您可以选择继续使用 GPS 直接检测区域。
    • @BradBrighton 我认为必须打开 WiFi 或蓝牙才能使 Multipeer Connectivity 正常工作。
    • @paranoidcoder 一个或另一个,正确的。在一般情况下,MPC 意味着对于开发者的利益是不透明的。但是,由于带宽较低,如果 BT 开启且 wifi 关闭,则某些配置或数据减少操作可能有意义。
    【解决方案4】:

    iOS 没有公共 API 可以告诉您 Wi-Fi 是打开还是关闭。

    但是,您可以使用 SystemConfiguration 框架中提供的公共 API CNCopyCurrentNetworkInfo() 来获取有关当前 Wi-Fi 网络的信息。这告诉您 Wi-Fi 是打开还是关闭,而是告诉您设备是否加入了 Wi-Fi 网络。也许这足以满足您的目的。

    另请注意,此 API 在 Simulator 中不起作用,因为 CNCopySupportedInterfaces() 始终返回 NULL。

    #include <SystemConfiguration/CaptiveNetwork.h>
    
    BOOL hasWiFiNetwork = NO;
    NSArray *interfaces = CFBridgingRelease(CNCopySupportedInterfaces());
    for (NSString *interface in interfaces) {
        NSDictionary *networkInfo = CFBridgingRelease(CNCopyCurrentNetworkInfo((__bridge CFStringRef)(interface)));
        if (networkInfo != NULL) {
            hasWiFiNetwork = YES;
            break;
        }
    }
    

    【讨论】:

      【解决方案5】:

      Swift 2.3 版本

      func isWifiEnabled() -> Bool {
          var addresses = [String]()
      
          var ifaddr : UnsafeMutablePointer<ifaddrs> = nil
          guard getifaddrs(&ifaddr) == 0 else { return false }
      
          var ptr = ifaddr
          while ptr != nil { defer { ptr = ptr.memory.ifa_next }
               addresses.append(String.fromCString(ptr.memory.ifa_name)!)
          }
      
          var counts:[String:Int] = [:]
      
          for item in addresses {
              counts[item] = (counts[item] ?? 0) + 1
          }
      
          freeifaddrs(ifaddr)
          return counts["awdl0"] > 1 ? true : false
      }
      

      Swift 4.0 版本

      func isWifiEnabled() -> Bool {
          var addresses = [String]()
      
          var ifaddr : UnsafeMutablePointer<ifaddrs>?
          guard getifaddrs(&ifaddr) == 0 else { return false }
          guard let firstAddr = ifaddr else { return false }
      
          for ptr in sequence(first: firstAddr, next: { $0.pointee.ifa_next }) {
              addresses.append(String(cString: ptr.pointee.ifa_name))
          }
      
          var counts:[String:Int] = [:]
      
          for item in addresses {
              counts[item] = (counts[item] ?? 0) + 1
          }
      
          freeifaddrs(ifaddr)
          guard let count = counts["awdl0"] else { return false }
          return count > 1
      }
      

      【讨论】:

        【解决方案6】:

        PrivateFrameworks 在 sdk 中不可用,也不可供任何企业开发人员使用。

        如果我们知道您想要实现什么,我知道 wifi 无线电功率状态,我们可能会建议一个替代解决方案,但从苹果公司如何处理他们向开发人员公开的内容来看,我认为这不会直接成为可能。

        使用可达性,您可以确定 wifi 是否打开,但要知道 wifi 是否关闭,请掷硬币。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-07-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多