Getting the HostName of a Remote iOS Device with NSNetService - ios

After more than a few hours of searching, I got in what looks like a dead end. In this case, all that I am trying to do, is to get all the iOS Devices of the network with Bonjour. I did so like this
self.serviceBrowser = [[NSNetServiceBrowser alloc] init];
[self.serviceBrowser setDelegate:self];
[self.serviceBrowser searchForServicesOfType:#"_apple-mobdev2._tcp." inDomain:#"local."];
This works fine, though what I get is the following:
local. _apple-mobdev2._tcp. [MAC ADDRESS HERE]
I tried to resolve the connection by using the sync port (62078), since service.port returns -1.
for (NSNetService *service in self.services) {
NSLog(#"%#", service);
NSNetService *newService = [[NSNetService alloc] initWithDomain:service.domain type:service.type name:service.name port:62078];
[newService setDelegate:self];
[newService resolveWithTimeout:30];
}
This in its own turn calls netServiceWillResolve: with no problem at all, but, it doesn't make it to netServiceDidResolveAddress:
But neither does this fail. netService:didNotResolve: isn't called either, I believe it is just waiting for a response to be resolved.
To support this claim, once it did make it to the method and actually [service hostName]; did return Yanniss-iPhone, but that happened at a completely random time that I had left the Mac App running for around half an hour. What could have invoked this to run? Or does anyone know of a different way to get the hostName of the remote device? The other answers do not answer my question, since I am looking for the hostName of the remote device, not of the Mac device.
Relative to that, I've found that when you kill and restart iTunes, along with iTunes Helper, the very log I mentioned below is sent again. Which is why I believe the correct log was an iTunes related event. Any help is very much appreciated!

iTunes search bonjour for wifi sync capability. As for the didNotResolve or resolve delay, bonjour services randomly cast itself anywhere between a few seconds to 30 minutes.
I am actually trying to connect to iOS devices too, but I could not get any response or any devices returned. :\

Related

When using NEHotspotConfiguration() to joing a network. Always recieve "unable to join"

I am implementing an APP through Xamarin that will force the iPhone to connect to a specific SSID.
Here is my code
var config = new NEHotspotConfiguration(SSID, Password, isWep: false)
config.JoinOnce = true;
var tcs = new TaskCompletionSource<NSError>();
NEHotspotConfigurationManager.SharedManager.ApplyConfiguration(config, err => tcs.SetResult(err));
There are two test result
Assume the target SSID I want to connect called "SSID-A"
I delete the record of "SSID-A" in the iOS system page. Then deploy this APP to the phone.
I give the correct SSID/Password into the code above.
The system popup a message "Unable to join". Failed to connect to this SSID.
I go to iOS system page. Manually connect to "SSID-A". Check the connection is done.
Then I connect to mobile phone to other SSID. And go back to the APP.
This time. It works.
Why there is a different at here?
What can I do to look more into this problem to solve this?
Thanks!
From applyConfiguration:completionHandler: of apple document, we could see the dicsussion that:
This method attempts to join the network only if it's found nearby. Also, because of the noticeable delay that the Hotspot 2.0 discovery mechanism may incur, the method doesn't attempt to join Hotspot 2.0 networks.
Therefore, Join once seems can not mark sure it works.We could have a try with remove this line, or set false as follows:
config.joinOnce = false;
In addition, it seems a bug in iOS 13 from Apple. You could have a look at this discussion.
In case it helps someone one day I had an issue suddenly start where my device was unable to join a network which has previously been working fine.
To test an error condition I tried connecting to a secure network without adding the passphase to the NEHotspotConfiguration. This attempt to join failed but then subsequently after putting the passphase back in the device wouldn't even display the join request dialog and would just fail with an 'Unable to join' error.
I eventually tried another test phone and this worked just fine so it seemed to be an issue on the device itself. I tried resetting my device's network settings but this made no difference.
The fix was to go into the device's wifi setting, join the network manually, return to my app, attempt to join, disconnect from the network in the device settings, and then forget the network. After that it worked fine on every subsequent attempt.

NEHotspotConfigurationManager unable to Join

I am using NEHotspotConfigurationManager to connect wifi programmatically.
Its an open Network without any password
I am using below code:
if (#available(iOS 11.0, *)) {
NEHotspotConfiguration *config = [[NEHotspotConfiguration
alloc]initWithSSID:SSIDName];
[NEHotspotConfigurationManager.sharedManager applyConfiguration:config completionHandler:^(NSError* error) {
if (error) {
printf([error description]);
}
else
{
printf(#"success");
}
}];
I am connecting to the hostpot/access point of one device, but every time I am getting an error of unable to join but in response it goes to success as the error is nil. Is there any thing I need to add in configuration or add in setting or am I missing anything ?
PS: The wifi is of IOT device
-Thanks in advance
This is an Apple bug in iOS.
Once the request has made it past the Network Extension framework, down to the Wi-Fi subsystem, errors are displayed to the user rather than delivered to your completion handler.
see https://forums.developer.apple.com/thread/96834
What you can do as a workaround:
try to connect
if the error is nil, you may be connected (due to the above mentioned bug this is unclear)
then check which network you are connected to
For more information, including sample code, see my answer here: https://stackoverflow.com/a/56589229/2331445
Additional Hints
Entitlement
Like #zero3nna already mentioned in the comments, the Hotspot Configuration entitlement must be added.
Check SSID name
Make sure you spelled the SSID correctly. I made a test with a NanoESP IoT device and for my device the definition would look like this:
NSString *SSIDName = #"NanoESP";
If you are using a non-existent SSID name (e.g. NanoESP2), there is a dialog that says that it is not possible to join the network.
Due to the above mentioned error you will get a success message in the console of Xcode, which is of course wrong:
Delayed Wi-Fi indicator
I have noticed that using the correct SSID works, but it takes quite some time for this connection to my specific IoT device to appear with the typical icon in the iOS status bar. For some time it's just not shown, see screenshot. To check the status anyway, go to iOS Settings / Wi-Fi:

iOS 10 - WLAN Access Setting Doesn't Appear In Some iOS Devices

Our app is using WLAN to communicate with a wireless device. When our app is installed in iOS 10. Sometimes, udp socket doesn't work. The reason for that is, in iOS 10 they added a new setting or permission under your app that allows the user to switch on or off the user of WLAN or cellular data.
The following would appear in the settings of the app:
When I tap on the Wireless... It will bring me to this UI:
After allowing WLAN use. The app would work fine.
Now, the problem is, sometimes, or in some devices running iOS 10, the settings that I just showed you doesn't appear(I am referring to the setting shown on the first image). So, is there anything I can do to make that settings always appear? It seems that sometimes iOS system doesn't recognize that my app is using wireless data. And it would result in my app would never get to use WLAN forever.
There is no user permission to use WIFI in iOS10.
The application in your screenshot (BSW SMART KIT) is using Wireless Accessories (WAC), i.e. is able to connect to wireless speakers. To accomplish this the Wireless Accessory Configuration capability is required. This is what you can dis/enable in the systems settings (your screenshot).
The switch in the settings shows up after connecting to a device via WIFI through WAC. You can see this behaviour in your sample app (BSW SMART KIT) too.
This sample code might let you get the idea. Detailed information in Apples documentation.
After a time of researching. I ended up seeking help with Apple Code Level Support. Apple states that this problem would most probably occur when you reskin your app. They say that probably it's because of the Image UUID of the main app and the reskinned app are the same. When you install both of them in your phone, the system will treat the reskinned app as the same app compared to the main app. So, if the one app fails to access WLAN, then it will also affect the other one. According to them, this appears to be a bug in iOS. And currently, they don't have any solution for the developers. This is the radar bug number:
What I did to somehow lessen the occurrence of the problem is to add tracking to the Network Restriction by using the following code.
- (void)startCheckingNetworkRestriction
{
__weak AppDelegate *weakSelf = self;
_monitor = [[CTCellularData alloc] init];
_monitor.cellularDataRestrictionDidUpdateNotifier = ^(CTCellularDataRestrictedState state)
{
[[NSOperationQueue mainQueue] addOperationWithBlock:^
{
NSString * statusStr;
switch(state)
{
case kCTCellularDataRestrictedStateUnknown:
{
statusStr = #"restriction status:Unknown";
}
break;
case kCTCellularDataRestricted:
{
statusStr = #"restriction status:restricted";
[weakSelf performUrlSession];
}
break;
case kCTCellularDataNotRestricted:
{
statusStr = #"restriction status:not restricted";
}
break;
default:
{
abort();
}
break;
}
NSLog(#"Restriction state: %#", statusStr);
}];
};
}
Take note that you have to import CoreTelephony to do this.
#import CoreTelephony;
when I detect that the network is restricted. I will open a URL session to force internet access attempt and would hope that the restriction alert dialog would pop out. Once the alert is pop out, then the WLAN Access Settings that I was talking about would definitely appear under the settings. There are times that this doesn't work. If it happens, then you'll just have to rename the bundle ID, and make a couple of changes to your code and then rebuild it a couple of times (Well, that's what I did when I was experimenting this). Reinstalling the app won't do a thing. Restarting and resetting the phone won't do either.
Hope this helps.

NSNetService Not Resolving

I have an existing application (actually a pair of iOS applications) which have a very basic Bonjour implementation so the 'client' can find the 'server' on the network. This worked fine until a recent test (I'm not completely for sure that this is related to iOS8, but this is the first time I've compiled these apps with iOS 8). In this case, all works as expected until the client goes to resolve the address of the server. At this point, it always times out. Also, I've tried a few Bonjour discovery apps from the app store and they timeout also (so I'm assuming this is a problem with the server code).
In the client application my NSNetServiceDelegate methods are called in this order:
netServiceWillResolve:
(then it waits the full timeout period that I specified in resolveWithTimeout:)
netService:didNotResolve:
This code has worked flawlessly in the past. I'm not entirely sure what would cause this behavior.
Here is the code for publishing the service:
- (void)initializeServerServiceStatus
{
NSString *deviceName = [[UIDevice currentDevice] name];
NSString *serviceName = [NSString stringWithFormat:#"iPad Server - %#", deviceName];
self.serverPresentationService = [[NSNetService alloc] initWithDomain:#"local."
type:SERVICE_NAME_IPAD_SERVER
name:serviceName
port:self.port];
self.serverPresentationService.delegate = self;
[self.serverPresentationService publish];
self.isPublishing = YES;
}
I have verified that the netServiceDidPublish: method is called and that the netServiceDidStop: is not called.
UPDATE: I have verified that if the service is published on an iOS 7 device, all works as expected (even if the resolving device is on iOS 8).
UPDATE 2: I have verified that Apple knows of some problems with Bonjour in the iOS 8 release: https://devforums.apple.com/message/1045870#1045870

iOS GameCenter connection from different networks

I have made an iOS multiplayer GameCenter game, but right before publishing found an issue I don't know how to solve. In coding process I used Ray Wenderlich tutorial http://www.raywenderlich.com/3276/how-to-make-a-simple-multiplayer-game-with-game-center-tutorial-part-12
GameCenter view controller is shown, connection creates and game can be played until both devices are on the same Wifi network.
If I turn off Wifi on my phone and use 3G network, then try to start new game - in that case connection isn't made anymore. Both devices find each other, but hangs on "Connecting..." screen. It looks like that
- (void)match:(GKMatch *)theMatch player:(NSString *)playerID didChangeState:(GKPlayerConnectionState)state
is not called. Any ideas how to solve it or at least understand, where exactly is the problem?
I think that in your particular case the problem is that your 3G ISP restricts connections from necessary ports. The Apple docs say:
To use Game Center ... port forwarding must be enabled for ports 443 (TCP), 3478-3497 (UDP), 4398 (UDP), 5223 (TCP), 16384-16387 (UDP), and 16393-16472 (UDP)
I faced this issue too when trying to play on iPad connected via bluetooth to iPhone: there was "Connecting..." screen on each device.
But when I use built-in iPad 3G (with a different tariff plan) everything goes fine.
Just remind, in a normal match-making scenario match:player:didChangeState: may not be called. You should also check match.expectedPlayerCount:
- (void)matchmakerViewController:(GKMatchmakerViewController *)viewController didFindMatch:(GKMatch *)theMatch {
//...
if (theMatch.expectedPlayerCount == 0) {
NSLog(#"Ready to start match!");
}
}
Also I expected a similar problem with "Connecting..." screen, but on Wifi network.
And it was reproduced only on iOS6 and after I tried rematch via -[GKMatch rematchWithCompletionHandler:^(GKMatch *match, NSError *error) {}] before.
One device hanged on "Connecting..." screen but on the other matchmakerViewController:didFindMatch: was successfully called, but what is interesting is that match.expectedPlayerCount was 0 and match.playerIDs array was empty at the same time.
I think such error occurred because I tried to find a new match while previous match tried to reconnect on background thread in the same time. And because of that new match was obtained corrupted.
The decision is to wait for rematchCompletion being called and only then try to find new match. There is no interface in GKMatch to cancel rematch, so I use [[GKMatchmaker sharedMatchmaker] cancel] and after several seconds rematchCompletion is called with error and we are ready to start finding new match.
Also I figured out that old unsued GKMatch instances are not deallocated and continue to live somewhere in GameKit framework. And they may probably cause problems if the work with them is not finished correctly (i.e. not disconnected, or rematch is not canceled in my case ). So do not forget to call -[GKMatch disconnect] and finish any other kind of work before removing the last strong reference to the match object .

Resources