4

I've been incorporating NEHotspotHelper into my app that manages a captive network, but I'm having multiple issues. I'm not receiving an Authentication Command (kNEHotspotHelperCommandTypeAuthenticate) after my network that is set with a high level of confidence is in the Evaluating State. Also, my WISPr network is never receiving an Evaluate Command( kNEHotspotHelperCommandTypeEvaluate) when the SSID is selected in the Wi-Fi list in Settings. My goal for the WISPr Hotspot is to send a UINotification requiring a user action. ANyone know what I'm missing as far as not receiving kNEHotspotHelperCommandTypeAuthenticate & kNEHotspotHelperCommandTypeEvaluate in the two situations?

I set up HotspotHelper registerWithOptions in my app delegate as such:

 NSMutableDictionary* options = [[NSMutableDictionary alloc] init];  
  [options setObject:@"Hotspot" forKey:kNEHotspotHelperOptionDisplayName];/  

  dispatch_queue_t queue = dispatch_queue_create("com.myapp.ex", 0);  
  BOOL returnType = [NEHotspotHelper registerWithOptions:options queue:queue handler: ^(NEHotspotHelperCommand * cmd) {  
  NEHotspotNetwork* network;  
  NSLog(@"COMMAND TYPE:   %ld", (long)cmd.commandType);

     if (cmd.commandType == kNEHotspotHelperCommandTypeEvaluate || cmd.commandType ==kNEHotspotHelperCommandTypeFilterScanList) {  
       for (network  in cmd.networkList) {  

            NSLog(@"COMMAND TYPE After:   %ld", (long)cmd.commandType);

            if ([network.SSID isEqualToString:@"test-WPA-2"]|| [network.SSID isEqualToString:@"WISPr Hotspot"]) {  

              double signalStrength = network.signalStrength;  
              NSLog(@"Signal Strength: %f", signalStrength);  

              [network setConfidence:kNEHotspotHelperConfidenceHigh];  
              [network setPassword:@"myPassword"];  

              NEHotspotHelperResponse *response = [cmd createResponse:kNEHotspotHelperResultSuccess];  
              NSLog(@"Response CMD %@", response);  

              [response setNetworkList:@[network]];  
              [response setNetwork:network];  
              [response deliver];  
          }    
     }       
}  

}];  
DaveLass
  • 625
  • 1
  • 8
  • 17
  • I have the same issue(( Can set password and annotate wifi network but can't authenticate in background, though apple claims it is possible. Maybe it's radar time ? – Roma Oct 07 '15 at 08:52
  • @Roma Do you have a similar code line as I posted, could you share? – DaveLass Oct 08 '15 at 13:51
  • here is my code. http://pastebin.com/zNvM4iLr As i said before annotaion and set passwords works , background authentication don't(( Let me now when you'll see the code - let's figure out solution together )) – Roma Oct 08 '15 at 14:17
  • I was able to finally get a Authentication Command. In Evaluate, I set the confidence level of the connected network, then passed then delivered that response to Evaluate. Posting code... – DaveLass Oct 08 '15 at 19:09

1 Answers1

4

The first mistake I made in the code above: I was expecting the command type Evaluate to enumerate through the network list. However, the Evaluate command is actually looking to be delivered the connected network. I get the current network with the following code:

                NSArray *array = [NEHotspotHelper supportedNetworkInterfaces];

                NEHotspotNetwork *connectedNetwork = [array lastObject];

                NSLog(@"supported Network Interface: %@", connectedNetwork);

Then check to see if the connected list matches my SSID, if so I set the confidence level of this network and deliver the response to Evaluate:

                        [connectedNetwork setConfidence:kNEHotspotHelperConfidenceLow];

                        //[response setNetworkList:@[network]];
                        [response setNetwork:connectedNetwork];

                        [response deliver];

The next command the handler is given is Authenticate. My complete code looks as following, I am still working on processing the commands after authenticate. The complete code line is:

              BOOL returnType = [NEHotspotHelper registerWithOptions:options queue:queue handler: ^(NEHotspotHelperCommand * cmd) {

              NEHotspotNetwork* network;

              if (cmd.commandType ==kNEHotspotHelperCommandTypeFilterScanList) {

                for (network in cmd.networkList) {

                    //need to check against list of directories

                        if ([network.SSID isEqualToString:@"test-WPA-2"]) {

                            NSLog(@"%@", network.SSID);
                            NSLog(@"SSID is in Directory: %@", network.SSID);

                            double signalStrength = network.signalStrength;
                            NSLog(@"Signal Strength: %f", signalStrength);

                            [network setConfidence:kNEHotspotHelperConfidenceLow];
                            [network setPassword:@"password"];


                            NEHotspotHelperResponse *response = [cmd createResponse:kNEHotspotHelperResultSuccess];
                            NSLog(@"Response CMD %@", response);

                            [response setNetworkList:@[network]];
                            [response setNetwork:network];
                            [response deliver];

                            }
                    }
            }
            if (cmd.commandType == kNEHotspotHelperCommandTypeEvaluate) {

                /* *   When a network is joined initially, the state machine enters
                 *   the Evaluating state. In that state, each HotspotHelper receives a
                 *   command of type Evaluate. If one or more helpers indicates that it
                 *   is able to handle the network, the one with the highest confidence
                 *   level is chosen before entering the Authenticating state. As an
                 *   optimization, the first helper to assert a high confidence wins and
                 *   the state machine ignores the other helpers.
                 *
                 *   If no helpers claim the network, the state machine enters the
                 *   Authenticated state.
                 */

                NSArray *array = [NEHotspotHelper supportedNetworkInterfaces];

                NEHotspotNetwork *connectedNetwork = [array lastObject];

                NSLog(@"supported Network Interface: %@", connectedNetwork);

                NEHotspotHelperResponse *response = [cmd createResponse:kNEHotspotHelperResultSuccess];

                NSLog(@"Response CMD %@", response);

                [connectedNetwork setConfidence:kNEHotspotHelperConfidenceLow];

                //[response setNetworkList:@[network]];
                [response setNetwork:connectedNetwork];

                [response deliver];


           }

           if (cmd.commandType == kNEHotspotHelperCommandTypeAuthenticate) {

            NSLog(@"COMMAND TYPE In Auth ***********:   %ld \n\n\n\n\n\n", (long)cmd.commandType);

            /*
            *   In the Authenticating state, the chosen helper is given a command of type
            *   Authenticate. The helper is expected to perform whatever network
            *   processing is required to make the network available for general
                *   network traffic. If the authentication is successful, the helper
                *   indicates that with a Success result. The state machine enters the
                *   Authenticated state.
                *
                *   On a network that has been authenticated by a helper, the state machine
                *   enters the Maintaining state when the network is joined again, and also
                *   periodically while the system remains associated with the network. In the
                    *   Maintaining state, the helper is expected to perform whatever network
                    *   operations are required to determine if the network is still able to
                        *   carry general network traffic. If that is the case, the helper returns
                        *   Success. If not, and authentication is again required, it returns
                        *   AuthenticationRequired to cause the state machine to re-enter the
                        *   Authenticating state.
                        *
                        *   In the Authenticating state, if the helper determines that it requires
                            *   user interaction to proceed, the helper first arranges to alert
                            *   the user via a UserLocalNotification, then returns a result of
                            *   UIRequired. The state machine enters the PresentingUI state.*/

        }
        if (cmd.commandType == kNEHotspotHelperCommandTypePresentUI) {

            NSLog(@"COMMAND TYPE In Present UI ***********:   %ld \n\n\n\n\n\n", (long)cmd.commandType);

        }

    }]; 
DaveLass
  • 625
  • 1
  • 8
  • 17
  • Wow! that super cool!!! thank you. I will test tomorrow and let you now whether I was able =) – Roma Oct 08 '15 at 21:22
  • Yes, I get a Maintain Command. In the conditional, I check to see if authentication is needed. If so, I deliver a response that includes: [cmd createResponse:kNEHotspotHelperResultAuthenticationRequired] – DaveLass Oct 13 '15 at 20:55
  • yes thank you, I also get it called. BTW did you managed to connect to the network completely without user interaction ? I'm able only to help him with password, by setting it. – Roma Oct 14 '15 at 07:45
  • I'm getting callbacks only when user is in settings-wifi menu. Are you using HotSpotHelper in the same way, or you are providing List of networks in your app ? – Roma Oct 14 '15 at 14:26
  • So then why is `cmd.network` not treated the same as `NEHotspotNetwork *connectedNetwork = [[NEHotspotHelper supportedNetworkInterfaces] lastObject];` – Pierre Feb 23 '17 at 12:01