Writing in the front

Recently I received an email from Apple saying that the interface for obtaining WiFi SSID CNCopyCurrentNetworkInfo no longer returns the VALUE of THE SSID. If you don’t look carefully, you will be surprised. It is a bomb to the related apps of the Internet of things. If you look at the email carefully, you can obtain the user’s location permission before returning to the SSID.

Dear Developer,

As we announced at WWDC19, we're making changes to further protect user privacy and prevent unauthorized location tracking. Starting with iOS 13, the CNCopyCurrentNetworkInfo API will no longer return valid Wi-Fi SSID and BSSID information. Instead, The information returned by default will be: SSID: "Wi-Fi" or "WLAN" (" WLAN" will be returned for the China SKU) "00:00:00:00:00:00" If your app is using this API, We encourage you to adopt alternative approaches that don't require Wi-Fi or network information information from CNCopyCurrentNetworkInfo will still be provided to VPN apps, apps that have used NEHotspotConfiguration to configure the current Wi-Fi network, and apps that have obtained permission to access user location through Location Services. Test your app on the latest iOS 13 beta to make sure it works properly. If your app requires valid Wi-Fi SSID and BSSID information to function, you can do the following: For accessory setup apps, use the NEHotSpotConfiguration API, which now has the option to pass a prefix of the SSID hotspot your app expects to connect to. For other types of apps, Use the CoreLocation API to request the user's consent to access location information. Learn more by reading the updated  documentation or viewing the the Advances in Networking session video from WWDC19. You can also submit a TSI for code-level support. Best regards, Apple Developer RelationsCopy the code

Solution: Obtain location permissions

- (NSString*) getWifiSsid {
    if(@available(iOS 13.0, *)) {// The user explicitly refuses, and can pop up to prompt the user to manually open permissions in the Settingsif ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied) {
            NSLog(@"User has explicitly denied authorization for this application, or location services are disabled in Settings."); //[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];return nil;
        }
        CLLocationManager* cllocation = [[CLLocationManager alloc] init];
        if(! [CLLocationManager locationServicesEnabled] || [CLLocationManager authorizationStatus] == KCLAuthorizationStatusNotDetermined) {/ / play box prompts the user whether open position permissions [cllocation requestWhenInUseAuthorization]; usleep(500); // Wait recursively for the user to selectreturn [self getWifiSsid];
        }
    }
    NSString *wifiName = nil;
    CFArrayRef wifiInterfaces = CNCopySupportedInterfaces();
    if(! wifiInterfaces) {return nil;
    }
    NSArray *interfaces = (__bridge NSArray *)wifiInterfaces;
    for (NSString *interfaceName in interfaces) {
        CFDictionaryRef dictRef = CNCopyCurrentNetworkInfo((__bridge CFStringRef)(interfaceName));
        
        if (dictRef) {
            NSDictionary *networkInfo = (__bridge NSDictionary *)dictRef;
            NSLog(@"network info -> %@", networkInfo);
            wifiName = [networkInfo objectForKey:(__bridge NSString *)kCNNetworkInfoKeySSID];
            CFRelease(dictRef);
        }
    }
    
    CFRelease(wifiInterfaces);
    return wifiName;
}
Copy the code

To get the results

  • Agreed print results
2019/08/09 14:23:47:121 network info -> {
    BSSID = "4c:ed:fb:a0:91:e4";
    SSID = "Asus_c039";
    SSIDDATA = <41737573 5f633033 39>;
}
Copy the code
  • Results if the user does not obtain location permissions
2019/08/09 14:34:01:586 network info -> {
    BSSID = "00:00:00:00:00:00";
    SSID = WLAN;
    SSIDDATA = <574c414e>;
}
Copy the code
  • It can be obtained directly if the project itself has location permissions enabled.

Solution – use NEHotspotConfiguration

It was also mentioned in the email that it could be obtained through NEHotspotConfiguration, but I didn’t understand what it meant before. Later, we found that the WiFi connected by APP using NEHotspotConfiguration interface can still pass CNCopyCurrentNetworkInfo SSID and BSSID.

NEHotspotConfiguration *c = [[NEHotspotConfiguration alloc] initWithSSID:@"Asus_c039" passphrase:@"leedarson@638" isWEP:NO];
NEHotspotConfigurationManager *m = [NEHotspotConfigurationManager sharedManager];
[m applyConfiguration:c completionHandler:^(NSError * _Nullable error) {
    NSLog(@"error :%@",error); }]; NSString - (NSString*) getWifiSsid {NSString* wifiName = nil; CFArrayRef wifiInterfaces = CNCopySupportedInterfaces();if(! wifiInterfaces) {return nil;
    }
    
    NSArray *interfaces = (__bridge NSArray *)wifiInterfaces;
    
    for (NSString *interfaceName in interfaces) {
        CFDictionaryRef dictRef = CNCopyCurrentNetworkInfo((__bridge CFStringRef)(interfaceName));
        
        if (dictRef) {
            NSDictionary *networkInfo = (__bridge NSDictionary *)dictRef;
            NSLog(@"network info -> %@", networkInfo);
            wifiName = [networkInfo objectForKey:(__bridge NSString *)kCNNetworkInfoKeySSID];
            
            CFRelease(dictRef);
        }
    }
    
    CFRelease(wifiInterfaces);
    return wifiName;
}
Copy the code

8.21 Updated NEHotspotConfiguration