How to check internet available to mobile packdata or not..? - ios

Our app support offline and online
So every step we need to check internet available to network or not.
When we using Reachability class then wi-fi off/on check it properly.
And in another we are also use SimplePing it is also work properly with Wi-fi using ping to host.
We are also check ICMP socket programing for this but it is only support to wi-fi.
But when we are using mobile packetdata how can we check internet is available to mobile or not.

NSURL *scriptUrl = [NSURL URLWithString:#"http://google.co.in/"];
NSData *data = [NSData dataWithContentsOfURL:scriptUrl];
if (data)
NSLog(#"Device is connected to the internet");
else
NSLog(#"Device is not connected to the internet");

This is something that a OS detects itself or by the ISP. You can check whether the internet is available through WiFi, or through CellularData or some other medium.
Internet access will automatically disconnected if user has consumed the data.
You can not check this by writing code.

Related

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:

Programatically finding IP of MacBook to which iOS device is connected via cable

When the iOS device is connected to a MacBook via a USB cable is there any programatic way for an app running on the iOS device to discover the IP address of the MacBook?
This would be so that a socket connection could then be established between the iOS device and a server running on the laptop.
The IP address on the USB link between them? I'm not even sure there's one in all cases, I believe there's one only when tethering (personal hotspot) is active.
If you mean the IP address of the Mac on Wi-Fi or Ethernet, then there's no guarantee both devices are actually on the same network (you could have the Mac on a local LAN behind a NAT while the iPhone is on a mobile network behind a different NAT), which would make communication problematic (you'd then have the usual P2P NAT-traversal issues, which in turn require external servers).
If you really want the devices to talk to each other over the network (rather than over the USB cable), you should probably look into Bonjour (which requires both devices to be on the same network) or the more recent Multipeer connectivity frameworks (which can even set up a peer-to-peer Wi-Fi network when needed, I believe.
If you really want to communicate over the cable, you're probably better off looking into talking to the device via libimobiledevice / usbmuxd, which can provide communication with a port on the iOS device. Note however that AFAIK, this works with the app on the Mac talking to a server app on the iOS device rather than the opposite.
Put this method into your class & you can obtain the IP address of current device.
// get the IP address of current-device
- (NSString *)getIPAddress {
NSString *address = #"error";
struct ifaddrs *interfaces = NULL;
struct ifaddrs *temp_addr = NULL;
int success = 0;
// retrieve the current interfaces - returns 0 on success
success = getifaddrs(&interfaces);
if (success == 0) {
// Loop through linked list of interfaces
temp_addr = interfaces;
while(temp_addr != NULL) {
if(temp_addr->ifa_addr->sa_family == AF_INET) {
// Check if interface is en0 which is the wifi connection on the iPhone
if([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:#"en0"]) {
// Get NSString from C String
address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
}
}
temp_addr = temp_addr->ifa_next;
}
}
freeifaddrs(interfaces);
return address;
}

How to tell if the user turned off cellular data for my app?

Although my app is usable without any internet connection, it may exchange data with a web server (in order to show some user statistics). So I advertise the app as "needs no internet connection". Some users subsequently have turned off cellular data for my app, which should be completely fine. But when my app tries to exchange data, these users are bugged with the "Cellular data is turned off for [App Name]." dialog.
This is an annoyance to them and I want to prevent these dialogs and simply skip the whole data exchange thing.
There is Apple's Reachability Sample Code.
But although I turned off WiFi for the whole device and cellular data for the app, Reachability confirms a positive internet connection. To be more specific, it reports
Reachability Flag Status: WR t------ networkStatusForFlags
no matter whether I activated cellular data or not. Of course, when cellular data is turned off, no internet connection is actually available, so the data exchange fails. But the user is presented with the cellular data dialog anyway.
Is there any way to detect whether a internet connection is available on iOS 7 and iOS 8, taking into account the cellular data setting for a specific app – all without bugging the user every time again with the cellular data dialog?
My app currently comes without any settings panel, so I want to avoid setting up a (second, in-app) switch "don't use cellular data". Also, I don't want to restrict data exchange to a WiFi connection since it's just a 2 KB of data per session which isn't a big thing for most users.
I think the only supported way in iOS8 is to send a Ping to a known server and bug the user with the alert panel a few times. On iOS8, Apple displays the panel only twice, then skips it even if the app is restarted, maybe it will show up a day later again. (This is really bad news for ad-supported apps.)
Apple says (https://devforums.apple.com/message/1059332#1059332):
Another developer wrote in to DTS and thus I had a chance to
investigate this in depth. Alas, the news is much as I expected:
there is no supported way to detect that your app is in this state.
Nor is there a way to make a "no user interaction" network connection,
that is, request that the connection fail rather than present UI like
this.
The following articles suggest ways to use ping:
http://www.splinter.com.au/how-to-ping-a-server-in-objective-c-iphone/
http://elbsolutions.com/projects/reachability-with-simpleping-wrapper/
Try using this git project.
How to install you can see inside the Readme on git.
I also used dispatch_once to be sure the Reachability will only be initialized once. This dispatch type is sometimes very useful!
Define variable in class
BOOL _online = NO;
Initialize the variable
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
Reachability *reach =
[Reachability reachabilityWithHostname:gameApiHost];
reach.reachableBlock = ^(Reachability*reach) {
NSLog(#"REACHABLE!"); _online = YES;
};
reach.unreachableBlock = ^(Reachability*reach) {
NSLog(#"UNREACHABLE!"); _online = NO;
};
[reach startNotifier];
});

Get current type of internet connection

I want to get the technology of radio access (internet connection), so detect if the device is connected to Wifi or WWAN connection (and in this case, which type of WWAN : GPRS, EGDE, 3G, 3G+, 3G++, or 4G).
Does CTTelephonyNetworkInfo works for iPhone and iPad on iOS7.1 ?
I've tried to detect a Wifi connection on an iPad but I print a null result.
This is my code :
CTTelephonyNetworkInfo *telephonyInfo = [CTTelephonyNetworkInfo new];
NSLog(#"Current Radio Access Technology: %#", telephonyInfo.currentRadioAccessTechnology);
Someone can told me why ? I'm not sure to understand everything about this...
Thanks for your help
(Source : http://www.objc.io/issue-5/iOS7-hidden-gems-and-workarounds.html, section "Know your Radio")
That's because currentRadioAccessTechnology will return the radio access technology (not whether it's Wifi or WWAN). An example of return value is CTRadioAccessTechnologyLTE.
To get informed about whether your app is connect to Wifi or WWAN, you should use Reachability.
There are several implementations available.

GCDAsyncUdpSocket on iOS missing multicasted datagrams

I have a device on the network that is multicasting a very small file via UDP. The iOS app I am developing is responsible for reading these packets and I have chosen to use GCDAsyncUdpSocket to do so. The file is sent every half second, however I am not receiving it nearly that often (only receiving about every 3-10 seconds).
Thinking that it may be an issue with the device, I began monitoring the traffic with Wireshark. This appeared to reflect what I was seeing in my app until I enabled "Monitor Mode" in Wireshark, at which point every UDP packet was being captured. In addition, the iOS simulator began receiving all of the missing packets since it shares the NIC with the Mac I am developing on.
Is there a way to enable "Monitor Mode" on an iOS device or something I am missing that would allow the missing packets to come in? I also see that there is a readStream method in GCDAsyncUdpSocket. Perhaps I need to use this instead of beginReceiving? Though I do not know how to set up streams in Objective-C if that is the case.
Here is my test code as it is now:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSLog(#"View Loaded");
[self setupSocket];
}
- (void)setupSocket
{
udpSocket = [[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
NSError *error = nil;
if (![udpSocket bindToPort:5555 error:&error])
{
NSLog(#"Error binding to port: %#", error);
return;
}
if(![udpSocket joinMulticastGroup:#"226.1.1.1" error:&error]){
NSLog(#"Error connecting to multicast group: %#", error);
return;
}
if (![udpSocket beginReceiving:&error])
{
NSLog(#"Error receiving: %#", error);
return;
}
NSLog(#"Socket Ready");
}
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data
fromAddress:(NSData *)address
withFilterContext:(id)filterContext
{
NSString *msg = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
if (msg)
{
NSLog(#"RCV: %#", msg);
}
else
{
NSString *host = nil;
uint16_t port = 0;
[GCDAsyncUdpSocket getHost:&host port:&port fromAddress:address];
NSLog(#"Unknown message from : %#:%hu", host, port);
}
}
Solution for anybody who comes looking here in the future:
Based on ilmiacs's answer, I was able to significantly reduce the number of missing packets by pinging the target iOS device. Using a Mac, I ran this in the terminal -
sudo ping -i 0.2 -s 4 <Target IP>
Now that I have it running with a Mac pinging the iOS device, I am going to look into Apple's iOS ping examples and see if I can have the device ping itself to stimulate its own wireless adapter (127.0.0.1).
Through my work on networking apps for iOS devices I have revealed that their network adapters have two different modes, let's call them active and passive. I did not manage to find any documentation on this. Here are my findings:
As long as in active mode, the adapter is quite responsive. I have response times of 3-5ms.
After some time of inactivity, the network adapter of the iOS falls from active to passive mode. The time for this to happen, depends on the actual device model. 3rd gen iPad it is around 200ms. For the iPhone 4 its more like 50ms.
A ping request or a TCP packet will move the adapter from passive to active mode. This may take anything from 50ms to 800ms, with an average of around 200ms.
This behavior is completely reproducible by issuing ping commands. E.g.
ping -i 0.2 <ios-device-ip>
sets the ping interval to 200ms and keeps my iPads network adapter in the active state.
This behavior is completely consistent with your observations, if the adapter (more often than not) ignores UDP packets when in passive mode. The wireshark activity probably keeps it in active mode so then it would get the UDPs.
Check out whether the ping trick helps.
One probably could keep the network adapter of the iDevice in the active state by opening and connecting two sockets on the device itself and regularly sending itself packets. This would introduce some minimal overhead.
As to why apple decided to implement such a feature, I can only speculate about. But probably keeping the adapter active costs sufficient battery power to legitimate such a design choice.
Hope this helps.
I had the same issue.
Starting the network activity indicator solved that problem for me:
UIApplication* app = [UIApplication sharedApplication];
app.networkActivityIndicatorVisible = YES;
If you want to view the packet on the iOS device, you can tether your iOS device to a Mac and mount the wifi adapter using shell command rvictl. You can then use wireshark, tcpdump, etc. to monitor the traffic on your 802.11 interface on your iOS device.
As far as not receiving data until 3 to 7 seconds - Most likely your device is entering into power save mode (IEEE PSM) which is an 802.11 feature that essentially puts the wireless NIC to sleep.
PSM mode can yield poor performance on devices - especially in your case where you have periodic bursts of data every 1/2 second. Your periodic ping is waking the NIC up.

Resources