First, regarding the use of fetchCurrentWithCompletionHandler, the header documentation on this symbol does list out the requirements:
This method returns SSID and BSSID of the current Wi-Fi network when the requesting application meets one of following 4 requirements -.
1. application is using CoreLocation API and has user's authorization to access precise location.
2. application has used NEHotspotConfiguration API to configure the current Wi-Fi network.
3. application has active VPN configurations installed.
4. application has active NEDNSSettingsManager configuration installed.
An application will receive nil if it fails to meet any of the above 4 requirements.
An application will receive nil if does not have the "com.apple.developer.networking.wifi-info" entitlement.
Next, regarding your linker issue; it looks like you are running a Qt application based on the path in your image: /iotmeter/app/Qt/IoTMeter/ios/src/iOSNative.mm. I would recommend that you extract your code out of the Qt project and test it from a blank test bed project. If you can get it working there, you know that you have to resolve a linking issue in the configuration of your Qt project.
Try it with this Swift code and CoreLocation on iOS 14.
import UIKit
import NetworkExtension
import os
import CoreLocation
class ViewController: UIViewController {
var locationManger: CLLocationManager?
override func viewDidLoad() {
super.viewDidLoad()
}
// MARK: - Public CoreLocation Methods
@IBAction func startLocationManager() {
guard locationManger == nil else {
// If locationManager is being started for the second time, for instance in .confirmNetwork, don't set accuracy and delegate again.
locationManger?.requestWhenInUseAuthorization()
locationManger?.startUpdatingLocation()
return
}
locationManger = CLLocationManager()
locationManger?.delegate = self
locationManger?.desiredAccuracy = kCLLocationAccuracyKilometer
locationManger?.requestWhenInUseAuthorization()
locationManger?.startUpdatingLocation()
}
@IBAction func testNetwork() {
NEHotspotNetwork.fetchCurrent(completionHandler: { (network) in
if let unwrappedNetwork = network {
let networkSSID = unwrappedNetwork.ssid
os_log("Network: %{public}@ and signal strength %d", networkSSID , unwrappedNetwork.signalStrength)
} else {
os_log("No available network")
}
})
}
}
// MARK: - CLLocationManagerDelegate Methods
extension ViewController: CLLocationManagerDelegate {
// MARK: - CLLocationManagerDelegate Methods
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let lastLocation = locations.last {
print("<LocationManager> lastLocation:\(lastLocation.coordinate.latitude), \(lastLocation.coordinate.longitude)")
}
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
// Detect the CLAuthorizationStatus and enable the capture of associated SSID.
if status == CLAuthorizationStatus.authorizedAlways ||
status == CLAuthorizationStatus.authorizedWhenInUse {
// Stubbing out authorization checks
}
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
if let error = error as? CLError, error.code == .denied {
print("<LocationManager> Error Denied: \(error.localizedDescription)")
// Notify the user of any errors.
manager.stopUpdatingLocation()
}
}
}
Next, add two buttons onto the Storyboard that trigger the startLocationManager first and then the testNetwork function second.
Next, add this to your entitlements file:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.networking.wifi-info</key>
<true/>
<key>com.apple.external-accessory.wireless-configuration</key>
<true/>
</dict>
</plist>
And then lastly add the location usage description keys to your Info.plist for what makes sense in your application:
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Gather location updates to get SSID</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Gather location updates to get SSID</string>
Let me know if that works out better, and then try and refactor your Qt project to use the same recipe. If that still does not work, you will need to resolve how your Qt project is linking the NetworkExtension framework.
Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com