Is there an event for disconnecting from the internet on iOS? - ios

I have an application that requires an internet connection for a certain library I use (XIMSS for Communigate). It receives status updates from a server and I can't alter the source of the lib. Is there a way to detect that the device disconnected from the internet? I'd like to avoid having to ping a server every x seconds to see if there is still a connection.

Apple's Reachability does this for you. Notifies you as your connectivity changes.

In iOS you can check like that :-
-(BOOL)returnInternetConnectionStatus{
ReachabilityLattest *reach = [ReachabilityLattest reachabilityForInternetConnection];
NetworkStatus internetStatus = [reach currentReachabilityStatus];
if ((internetStatus != NotReachable)) {
return TRUE;
} else {
return FALSE;
}
}
For more detail you can download from here Reachability Sample Code
Hope this helps you !

Note that all the pointers to Reachability are a good start, and you definitely need Reachability, but for a messaging app it is generally not sufficient. Reachability never sends packets. It just tells you whether the device could even try to send a packet if you asked it to. So it basically tells you that you have an IP address and know a gateway. It does not tell you that you could reach the server you care about, and it absolutely does not tell you whether that server can reach you (which is a very important question for messaging apps).
In most cases, if Reachability were sufficient, you wouldn't need Reachability. Apple strongly recommends (and for good reason) that you not check Reachability before sending packets. Just send the packets and deal with the error if it comes. But that doesn't help for apps that have to receive data at random times.
If connectivity is poor (particularly due to poor cell coverage), or if there is a firewall between you and the server, you can easily get positive results from Reachability even though you are no longer getting messages from the server. The only way to detect this situation is to send a packet and receive a packet (i.e. "ping").
Reachability is also not sufficient to notice when your connection changes. For instance, if you change IP addresses (pretty common when you're driving around town), Reachability won't always tell you (it may if you use SCNetworkReachabilityCreateWithAddressPair(); it's been awhile since I've worked on this problem; but the Reachability example code doesn't work this way in any case).
So Reachability is a good first start, but at the end of the day you still require a heartbeat if you want to detect that the server is no longer talking to you. The key thing to remember is that in IP, there is no such thing as "a connection." There are just packets. You can send them and you can receive them. But if you aren't receiving them, there's no way to distinguish "no one is sending them" from "they are not arriving." The illusion TCP gives of "connections" only exists when packets are being exchanged.
(BTW, dealing with network connectivity in a messaging app is probably the hardest iOS code I've ever worked on. Testing is a nightmare. I used to stick my phone in the fridge to cut off its network access. At least now there is the network conditioner…)

[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(ReachablilityChange:) name:kReachabilityChangedNotification object:nil];
Add notifier for Reachability Change Notification.This will call the reachabilityChange when the network change occur, In ReachablilityChange function detect
NetworkStatus hostStatus = [hostReachable currentReachabilityStatus];
Get status in hostStatus
if(hostStatus == NotReachable)
{Do your code here;}

Related

What network protocol does Reachability use on iOS?

I am sure there is little % of iOS developers who haven't used Reachability, directly or via some framework like Alamofire.
What I am interested what it actually does? The best guess I can make is that given host it opens sockets and then listens for said host. But what network protocol does it use, is it simple UDP (it is not http as far as I can observe), where it periodically sends packages to said host and awaits answer?
Reachability sends no packets at all. It doesn't even tell you that a host is actually reachable. It just tells you that if you made a network request, then the system has an active network interface that it would try to use. That's all. There's no promise those packets would arrive (let alone that you'd get a response), just that iOS would try to send them.
Reachability really only has a couple of uses (and most of the time shouldn't be used). It is useful if "no network is available" would cause you to modify your user interface, or to tell you that it might be a good time to re-try a previously failed connection. (Since iOS 12, you should really use NWPathMonitor for this. I don't know any good uses for Reachability since iOS 12.)
The only way that you can know that a request will actually succeed is to try to send it and see if you get a response. That's why it is not recommended that you test Reachability before sending requests. Just send the request and deal with the errors if they come, since it is always possible to have an error, even if Reachability said you could connect.

Why Apple is not bringing support to check whether a connection has active internet connection?

When I checked the apple Reachability class, it does return true even though the connected network doesn't have an active internet connection. So I'm having few doubts here -
Why is Reachability class made to throw YES if the packet can leave the local device even though it doesn't ensure it is delivered at the endpoint? Are there any special reasons to limit the ability?
Reachability has reachabilityWithHostName method still, YES will be thrown by class even if we add familiar hostname in the same network. If it doesn't ensure endpoint packet delivery why they provided this method?
Is there any other way to check whether there is an active internet connection in the connected network other than Reachability? Do we need to add our custom APIs or logic to tackle this thing?
I did connect an android phone to the same network, it instantaneously notified me the connection has no internet connection.

Determine whether iPhone is really connected to the internet or just behind a restricted hotspot

I'm having quite a lot of trouble on identifying rigorously the kind of network access an iPhone has. I have seen many questions like this one on StackOverflow but none of them helped me. For example I have already seen this: How to check for an active Internet connection on iOS or OSX?
But I want to know precisely when the 3 following cases occur:
Wifi and 3G are disabled
Wifi or 3G are enabled but there is no internet connection. It could be due to 3G not really working, even though it is showing up on the status bar, or the WiFi is a hotspot asking to log in before letting you access the Internet or last scenario: The WiFi source is a local network but does not provide any Internet connection.
Everything works fine
Of course I have tried various stuff, like this for instance:
// Allocate a reachability object
Reachability* reach = [Reachability reachabilityWithHostname:#"www.google.com"];
// Set the blocks
reach.reachableBlock = ^(Reachability*reach)
{
/* NOT REACHABLE */
dispatch_async(dispatch_get_main_queue(), ^{
iarcSBInternetWarning.visible = NO;
});
};
reach.unreachableBlock = ^(Reachability*reach)
{
/* REACHABLE */
iarcSBInternetWarning.visible = YES;
};
// Start the notifier, which will cause the reachability object to retain itself
[reach startNotifier];
But this seems just to say wether Wifi or 3G are enabled and does not check for possible internet restrictions. I would be highly delighted by any answer helping me identifying the three scenarios.
Of course analyzing a direct HTTP request output from a personal server API returning a specific byte sequence would work but that is not what I would like to do. I'd prefer using any kind of Reachability API.
I've used Apple's reachability API, it does not seem to recognize hotspot redirections.
If this is not possible with the Reachability APIs, then what would be the lowest resource-consuming method to make a simple request to a server, check that it is reachable before a specified timeout, and that the URL was not redirected to a hotspot login page (maybe only check the headers, not the whole server byte sequence output)? Is it a good idea to run such a script every 15 seconds, or would it use too much battery and/or network data?
The simplest method to check outbound connectivity is to GET Google's generate204 page and check the response code
http://www.google.com/generate_204
Or you can use
http://www.apple.com/library/test/success.html which is the page the OS uses

Reachability lying about disconnected wifi network

I use Stackmob SDK (which will end soon) and I assume they use AFNetworking for reachability. If a device is connected to a wifi network which is disconnected from the Internet, the reachability check will be positive and the following statement will be true:
if ([self.appDelegate.client.networkMonitor currentNetworkStatus] == SMNetworkStatusReachable) {
// reachable
}
How can I fine tune this check to overcome the present limitation? How can I check for real network reachability within this if statement, or is there any better Reachability check out there?
If your question is "can I send data to that host and receive a response", then Reachability can only answer "no" or "maybe". It cannot answer "yes" because there are many connectivity factors that Reachability does not check.
Reachability only checks the first hop. It defines reachability as the ability for packets to leave the device in the direction of that host. If the device is connected to a network that claims to be able to route to that host then Reachability is satisfied. If the router is lying or the host is down or there are unfriendly backhoes in Kansas then Reachability's result will be optimistic.
The only sure way to answer the question "can I send data to that host and receive a response" is to actually attempt to send data to that host and receive a response. Reachability can help you give up when connectivity is definitely not available. If you try and fail, Reachability's network-change notifications can help you decide when to try again without wasting power.

iOS reachability says reachable with no internet connection on 3g

I am developing an iPhone app and whenever I make a call to my web service I want to make sure that the user is connected to the internet.
I used the Reachability class provided by Tony Million on github, link is her for anyone who wants to grab it. https://github.com/tonymillion/Reachability
The I just followed the examples and set everything up and have the following code
Reachability* reach = [Reachability reachabilityWithHostname:#"www.google.com"];
reach.reachableBlock = ^(Reachability*reach)
{
// call web service here
};
reach.unreachableBlock = ^(Reachability*reach)
{
// alert user not reachable
};
[reach startNotifier];
Now I test this in the simulator and everything works perfectly fine, my service is being called when connected to the wifi. And if I switch the wifi off, I see an alert displayed which is exactly what I need.
Now I test this on the device and get decent results but not exactly what I need. It is important to note that my phone does not have a data package.
So here are the scenario's
I connect my phone to wifi and run the app, perfect, a call is made to the web service. Nothing to worry about here.
I disconnect my phone from the wifi and run the app again, I EXPECT the alert to come up telling me that its not connected but then I see the UI activity indicator spinning in my app which means the app has detected a connection of some sort and is trying to connect to my web service. But this will never happen, I know it is detecting the cellular 3g as I go into settings->general->usage->cellular usage, reset the stats to 0. After a while, I can see data being sent and received.
I go to settings->general->cellular->turn 3g off, run the app and now it shows the alert of no connectivity.
I know a lot of people have data packages and also I have see apps hit the marketplace with the level of reachability I have mentioned above, I just feel this could be improved in the scenario I just explained.
I have a 3g connection but I do not know how
[Reachability reachabilityWithHostname:#"www.google.com"];
gets pinged, or perhaps its not ?
Although I did switch my wifi off and opened safari, it behaves the same way, it shows that its loading for quite a while and then just says safari could not open ...
Is this just something that cannot be accomplished ?
Finally, I even saw the sample, Tony Million provided on the github page, when run on my phone, it shows reachable despite wifi being off and me not having a data package.
I looked at a few stack over flow answers where users asked about checking for internet connectivity but most answers either revolved on the "type" wifi, wwan etc rather than detecting if it is a valid internet connection rather than being connected to a network.
Thank you for your time.
After quite a few a few days of research I found a solution that was useful for me and hopefully somebody in the future might find it useful.
I created a singleton class with the above reachability code so that I could use it and check it whenever I make web calls easily. Although this did not solve my issue as I mentioned before but this is the first check.
Then I went ahead and just did the regular stuff to get data from the url
NSdata * data [NSData dataWithContentsOfURL:myurlhere];
if([data length] == 0)
{
show alert view here
}
else
{
doing stuff with the items in data
}
So using a combination of reachability (this does not always work in some cases like mine where a cellular network uses 3g or 4g) and checking the data downloaded can serve as a good check point for the app.
First, you need to check your cellular data permission for your app in settings.

Resources