iPhone get SSID without private library

后端 未结 9 788
[愿得一人]
[愿得一人] 2020-11-22 06:00

I have a commercial app that has a completely legitimate reason to see the SSID of the network it is connected to: If it is connected to a Adhoc network for a 3rd party har

相关标签:
9条回答
  • 2020-11-22 06:28

    This works for me on the device (not simulator). Make sure you add the systemconfiguration framework.

    #import <SystemConfiguration/CaptiveNetwork.h>
    
    + (NSString *)currentWifiSSID {
        // Does not work on the simulator.
        NSString *ssid = nil;
        NSArray *ifs = (__bridge_transfer id)CNCopySupportedInterfaces();
        for (NSString *ifnam in ifs) {
            NSDictionary *info = (__bridge_transfer id)CNCopyCurrentNetworkInfo((__bridge CFStringRef)ifnam);
            if (info[@"SSID"]) {
                ssid = info[@"SSID"];
            }
        }
        return ssid;
    }
    
    0 讨论(0)
  • 2020-11-22 06:29

    For iOS 13

    As from iOS 13 your app also needs Core Location access in order to use the CNCopyCurrentNetworkInfo function unless it configured the current network or has VPN configurations:

    So this is what you need (see apple documentation):
    - Link the CoreLocation.framework library
    - Add location-services as a UIRequiredDeviceCapabilities Key/Value in Info.plist
    - Add a NSLocationWhenInUseUsageDescription Key/Value in Info.plist describing why your app requires Core Location
    - Add the "Access WiFi Information" entitlement for your app

    Now as an Objective-C example, first check if location access has been accepted before reading the network info using CNCopyCurrentNetworkInfo:

    - (void)fetchSSIDInfo {
        NSString *ssid = NSLocalizedString(@"not_found", nil);
    
        if (@available(iOS 13.0, *)) {
            if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied) {
                NSLog(@"User has explicitly denied authorization for this application, or location services are disabled in Settings.");
            } else {
                CLLocationManager* cllocation = [[CLLocationManager alloc] init];
                if(![CLLocationManager locationServicesEnabled] || [CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined){
                    [cllocation requestWhenInUseAuthorization];
                    usleep(500);
                    return [self fetchSSIDInfo];
                }
            }
        }
    
        NSArray *ifs = (__bridge_transfer id)CNCopySupportedInterfaces();
        id info = nil;
        for (NSString *ifnam in ifs) {
            info = (__bridge_transfer id)CNCopyCurrentNetworkInfo(
                (__bridge CFStringRef)ifnam);
    
            NSDictionary *infoDict = (NSDictionary *)info;
            for (NSString *key in infoDict.allKeys) {
                if ([key isEqualToString:@"SSID"]) {
                    ssid = [infoDict objectForKey:key];
                }
            }
        }        
            ...
        ...
    }
    
    0 讨论(0)
  • 2020-11-22 06:30

    UPDATE FOR iOS 10 and up

    CNCopySupportedInterfaces is no longer deprecated in iOS 10. (API Reference)

    You need to import SystemConfiguration/CaptiveNetwork.h and add SystemConfiguration.framework to your target's Linked Libraries (under build phases).

    Here is a code snippet in swift (RikiRiocma's Answer):

    import Foundation
    import SystemConfiguration.CaptiveNetwork
    
    public class SSID {
        class func fetchSSIDInfo() -> String {
            var currentSSID = ""
            if let interfaces = CNCopySupportedInterfaces() {
                for i in 0..<CFArrayGetCount(interfaces) {
                    let interfaceName: UnsafePointer<Void> = CFArrayGetValueAtIndex(interfaces, i)
                    let rec = unsafeBitCast(interfaceName, AnyObject.self)
                    let unsafeInterfaceData = CNCopyCurrentNetworkInfo("\(rec)")
                    if unsafeInterfaceData != nil {
                        let interfaceData = unsafeInterfaceData! as Dictionary!
                        currentSSID = interfaceData["SSID"] as! String
                    }
                }
            }
            return currentSSID
        }
    }
    

    (Important: CNCopySupportedInterfaces returns nil on simulator.)

    For Objective-c, see Esad's answer here and below

    + (NSString *)GetCurrentWifiHotSpotName {    
        NSString *wifiName = nil;
        NSArray *ifs = (__bridge_transfer id)CNCopySupportedInterfaces();
        for (NSString *ifnam in ifs) {
            NSDictionary *info = (__bridge_transfer id)CNCopyCurrentNetworkInfo((__bridge CFStringRef)ifnam);
            if (info[@"SSID"]) {
                wifiName = info[@"SSID"];
            }
        }
        return wifiName;
    }
    

    UPDATE FOR iOS 9

    As of iOS 9 Captive Network is deprecated*. (source)

    *No longer deprecated in iOS 10, see above.

    It's recommended you use NEHotspotHelper (source)

    You will need to email apple at networkextension@apple.com and request entitlements. (source)

    Sample Code (Not my code. See Pablo A's answer):

    for(NEHotspotNetwork *hotspotNetwork in [NEHotspotHelper supportedNetworkInterfaces]) {
        NSString *ssid = hotspotNetwork.SSID;
        NSString *bssid = hotspotNetwork.BSSID;
        BOOL secure = hotspotNetwork.secure;
        BOOL autoJoined = hotspotNetwork.autoJoined;
        double signalStrength = hotspotNetwork.signalStrength;
    }
    

    Side note: Yup, they deprecated CNCopySupportedInterfaces in iOS 9 and reversed their position in iOS 10. I spoke with an Apple networking engineer and the reversal came after so many people filed Radars and spoke out about the issue on the Apple Developer forums.

    0 讨论(0)
  • 2020-11-22 06:36

    Here's the cleaned up ARC version, based on @elsurudo's code:

    - (id)fetchSSIDInfo {
         NSArray *ifs = (__bridge_transfer NSArray *)CNCopySupportedInterfaces();
         NSLog(@"Supported interfaces: %@", ifs);
         NSDictionary *info;
         for (NSString *ifnam in ifs) {
             info = (__bridge_transfer NSDictionary *)CNCopyCurrentNetworkInfo((__bridge CFStringRef)ifnam);
             NSLog(@"%@ => %@", ifnam, info);
             if (info && [info count]) { break; }
         }
         return info;
    }
    
    0 讨论(0)
  • 2020-11-22 06:37

    See CNCopyCurrentNetworkInfo in CaptiveNetwork: http://developer.apple.com/library/ios/#documentation/SystemConfiguration/Reference/CaptiveNetworkRef/Reference/reference.html.

    0 讨论(0)
  • 2020-11-22 06:43

    As of iOS 7 or 8, you can do this (need Entitlement for iOS 12+ as shown below):

    @import SystemConfiguration.CaptiveNetwork;
    
    /** Returns first non-empty SSID network info dictionary.
     *  @see CNCopyCurrentNetworkInfo */
    - (NSDictionary *)fetchSSIDInfo {
        NSArray *interfaceNames = CFBridgingRelease(CNCopySupportedInterfaces());
        NSLog(@"%s: Supported interfaces: %@", __func__, interfaceNames);
    
        NSDictionary *SSIDInfo;
        for (NSString *interfaceName in interfaceNames) {
            SSIDInfo = CFBridgingRelease(
                CNCopyCurrentNetworkInfo((__bridge CFStringRef)interfaceName));
            NSLog(@"%s: %@ => %@", __func__, interfaceName, SSIDInfo);
    
            BOOL isNotEmpty = (SSIDInfo.count > 0);
            if (isNotEmpty) {
                break;
            }
        }
        return SSIDInfo;
    }
    

    Example output:

    2011-03-04 15:32:00.669 ShowSSID[4857:307] -[ShowSSIDAppDelegate fetchSSIDInfo]: Supported interfaces: (
        en0
    )
    2011-03-04 15:32:00.693 ShowSSID[4857:307] -[ShowSSIDAppDelegate fetchSSIDInfo]: en0 => {
        BSSID = "ca:fe:ca:fe:ca:fe";
        SSID = XXXX;
        SSIDDATA = <01234567 01234567 01234567>;
    }
    

    Note that no ifs are supported on the simulator. Test on your device.

    iOS 12

    You must enable access wifi info from capabilities.

    Important To use this function in iOS 12 and later, enable the Access WiFi Information capability for your app in Xcode. When you enable this capability, Xcode automatically adds the Access WiFi Information entitlement to your entitlements file and App ID. Documentation link

    Swift 4.2

    func getConnectedWifiInfo() -> [AnyHashable: Any]? {
    
        if let ifs = CFBridgingRetain( CNCopySupportedInterfaces()) as? [String],
            let ifName = ifs.first as CFString?,
            let info = CFBridgingRetain( CNCopyCurrentNetworkInfo((ifName))) as? [AnyHashable: Any] {
    
            return info
        }
        return nil
    
    }
    
    0 讨论(0)
提交回复
热议问题