NEHotspotHelper.register not received call back iOS11

I am working on NEHotspotHelper and trying to register but not receiving call back. Firstly,

I enabled Capability : Network Extensions enter image description here

Then added this following code,

 let options: [String: NSObject] = [kNEHotspotHelperOptionDisplayName : "ABC" as NSObject]
    let queue: DispatchQueue = DispatchQueue(label: "com.ABC", attributes: DispatchQueue.Attributes.concurrent)

    NSLog("Started wifi scanning.")

    NEHotspotHelper.register(options: options, queue: queue) { (cmd: NEHotspotHelperCommand) in
        NSLog("Received command: \(cmd.commandType.rawValue)")

        if cmd.commandType == NEHotspotHelperCommandType.filterScanList {
            //Get all available hotspots
            let list: [NEHotspotNetwork] = cmd.networkList!
            //Figure out the hotspot you wish to connect to

            print(list)

        } else if cmd.commandType == NEHotspotHelperCommandType.evaluate {
            if let network = cmd.network {
                //Set high confidence for the network
                network.setConfidence(NEHotspotHelperConfidence.high)

                let response = cmd.createResponse(NEHotspotHelperResult.success)
                response.setNetwork(network)
                response.deliver() //Respond back
            }
        } else if cmd.commandType == NEHotspotHelperCommandType.authenticate {
            //Perform custom authentication and respond back with success
            // if all is OK
            let response = cmd.createResponse(NEHotspotHelperResult.success)
            response.deliver() //Respond back
        }
    }

Kindly let me know if I am missing any step.


Solution 1:

You should check the result of the register() function. If it's returning false, something is probably not configured correctly. See the full list of configuration instructions below.

Also in the screenshot you provided, you have the entitlements enabled for Hotspot Configuration, but the API you're calling is for Hotspot Helper. The two features require very different entitlements. You'll need to make sure everything is configured for Hotspot Helper to call that API. Again, see below for full details. See Hotspot Helper vs. Hotspot Configuration for more details about the differences of these similarly named APIs.


To use NEHotspotHelper:

  1. Apply for the Network Extension entitlement.

    This needs to be done at Apple's website here.

  2. Modify your Provisioning Profile.

    Go to http://developer.apple.com. Hit Edit near your profile. On the bottom where it says Entitlements, choose the one that contains the Network Extension entitlement.

  3. Update your app's entitlements file.

    The application must set com.apple.developer.networking.HotspotHelper as one of its entitlements. The value of the entitlement is a boolean set to true.

  4. Add Background Mode

    The application's Info.plist must include a UIBackgroundModes array containing network-authentication.

    Note that unlike all the other background modes that are converted to human readable strings, this one will stay as network-authentication.

  5. Call the NEHotspotHelper.register() function.

    This method should be called once when the application starts up. Invoking it again will have no effect and result in false being returned.

    You should make sure the function returns true. Otherwise something one of the above steps is probably not configured properly.

  6. Understand when this callback will be called.

    From the documentation, it's not entirely clear when exactly this callback will be called. For example, one might assume that NEHotspotHelper could be used to monitor for network connections. However, the callback will (only?) be called when the user navigates to the Settings app and goes to the Wi-Fi page.

    Since your callback will be called only while the user in the Settings app, you should attach to the debugger and use print().

Swift Example

let targetSsid = "SFO WiFi"
let targetPassword = "12345678"
let targetAnnotation: String = "Acme Wireless"

let options: [String: NSObject] = [
  kNEHotspotHelperOptionDisplayName: targetAnnotation as NSString
]

let queue = DispatchQueue(label: "com.example.test")

let isAvailable = NEHotspotHelper.register(options: options, queue: queue) { (command) in
  switch command.commandType {
  case .evaluate,
       .filterScanList:
    let originalNetworklist = command.networkList ?? []
    let networkList = originalNetworklist.compactMap { network -> NEHotspotNetwork? in
      print("networkName: \(network.ssid); strength: \(network.signalStrength)")
      if network.ssid == targetSsid {
        network.setConfidence(.high)
        network.setPassword(targetPassword)
        return network
      }
      return nil
    }
    let response = command.createResponse(.success)
    response.setNetworkList(networkList)
    response.deliver()
  default:
    break
  }
}

assert(isAvailable)

Sources:

  • https://developer.apple.com/documentation/networkextension/nehotspothelper/1618965-register
  • https://medium.com/@prvaghela/nehotspothelper-register-an-app-as-a-hotspot-helper-cf92a6ed7b72
  • https://stackoverflow.com/a/39189063/35690