I uploaded my app recently to Google Playstore. I used Error Reporter to track the crashes. App is working fine but very frequently I get HttpHostConnectException. Before making every web-call, I checked for Internet Connection. Are there any other reasons for the cause of this exception? How can it be avoided?
P.S. I never get this exception while testing/debugging my app.
HttpHostConnectException is thrown when connection cannot be established to a remote host on a specific port.
Before making every web-call, I checked for Internet Connection.
Checking internet connection is not a full-proof way to decide that the host is reachable. In many instances like using wifi, the device is connected to your router while the router is not connected to the internet. Checking internet connection using classes like ConnectivityManager in such cases returns true but the actual connection is false.
The solution is to check if your host is actually reachable using any http methods.
public boolean isInternetAvailable() {
try {
InetAddress ipAddr = InetAddress.getByName("google.com"); //You can replace it with your name
if (ipAddr.equals("")) {
return false;
} else {
return true;
}
} catch (Exception e) {
return false;
}
}
The above code is taken from this SO post.
I used AsyncHttpClient to handle all my webcalls. It handles my case perfectly. It directly takes to onFailure() on getting HttphostConnectException.
Related
I have a thread that continually does the following CheckConnection() method. It works great when the endpoint Uri of the HttpClient GetAsync is available (the endpoint is only reachable when connected to a local wifi ap). If Wifi is then turned off then obviously it isn't available. The HttpClient has a timeout of 400ms, and also in the method below I've tried to create the GetAsync request with a CancellationTokenSource for good measure. It has a TimeSpan of 400ms. Either way if wifi is off the method fails! It just gets stuck. For example if I turn off Wifi while the app is running, the debugger will report that it has entered CheckConnection but it gets stuck at the GetAsync()
This only happens when there is a data connection available, as in when wifi is disabled it switches to 4G and then gets stuck (I need it to fail fast). This behavior does not occur when changing between WiFi networks, and 4G is turned off.
Any hints as to what I am clearly missing in my logic? Am I right to think this is the source of the bug? In the meantime I will see about how other apps handle switching networks and talking with servers.
Thanks
The Check Connection Method:
public async Task<bool> CheckConnection()
{
Uri uri = new Uri(string.Format(Constants.RestUrl, "work"));
using (var cts = new CancellationTokenSource(_FastTimeout)) // _FastTimeout is 400ms
{
try
{
HttpResponseMessage response = await connectionCheckclient.GetAsync(uri, cts.Token).ConfigureAwait(false);
if ( response.StatusCode == System.Net.HttpStatusCode.OK)
{
Debug.WriteLine(#"\t connected to server");
return true;
}
}
catch (Exception ex)
{
Debug.WriteLine(#"\tERROR not connected to server {0}", ex.Message);
return false;
}
}
return false;
}
What I have discovered is that essentially whenever there is a network change you want to create a new httpclient. So you need some sort of observer setup or a callback method. Either one can be implemented as interfaces in the main Xamarin project, and then the specific platform projects can implement them, registering them with the Xamarin Assembly dependency framework.
I have an android app which is working completely fine in WiFi and 3G connection of all operators except Reliance Jio.
However, I have found that Sometimes the android app is not connecting to my HTTPS web-services when Reliance JIO 4G connection is used, but the same set of HTTPS web-services are working perfectly without any delay when the device is connected to other service providers.
You should check whether the user has an active internet connection before making the request.
use this method to check internet availability only make a request if this returns true, otherwise, toast them internet is not available.
public static boolean isInternetAvailable() {
try {
InetAddress ipAddr = InetAddress.getByName("google.com"); //You can replace it with your domain name
return !ipAddr.equals("");
} catch (Exception e) {
return false;
}
}
My university has an open wifi access point, however it requires you to enter your e-mail before it allows you to use the web. My problem is that the Wifi is stupid in that it seems to drop my connection and force me to enter my e-mail again every 10 minutes.
I wanted to create my own app that I can use to automatically do this step for me, but I cannot seem to find any documentation for a nice and easy way to detect if a Wifi access point has a browser login page. Is there a way in Android to get this information, or is it just to see if my connection to something is always redirected to 1.1.1.1?
See the "Handling Network Sign-On" section of the HttpUrlConnection documentation:
Some Wi-Fi networks block Internet access until the user clicks through a sign-on page. Such sign-on pages are typically presented by using HTTP redirects. You can use getURL() to test if your connection has been unexpectedly redirected. This check is not valid until after the response headers have been received, which you can trigger by calling getHeaderFields() or getInputStream().
They have a snippet of sample code there. Whether this will cover your particular WiFi AP, I can't say, but it is worth a shot.
Ping an external IP address (like google.com) to see if it responds.
try {
Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec("ping -c 1 " + "google.com");
proc.waitFor();
int exitCode = proc.exitValue();
if(exitCode == 0) {
Log.d("Ping", "Ping successful!";
} else {
Log.d("Ping", "Ping unsuccessful.");
}
}
catch (IOException e) {}
catch (InterruptedException e) {}
The only downside is this would also indicate that a web login is required when there is simply no internet connectivity on the WiFi access point.
#CommonsWare I believe this is a better answer than opening a UrlConnection and checking the host, since the host doesn't always change even when displaying the redirect page. For example, I tested on a Belkin router and it leaves whatever you typed in the browser as is, but still displays its own page. urlConnection.getUrl().getHost() returns what it should because of this.
I think #FlyWheel is on the right path, but I would use http://clients1.google.com/generate_204 and if you don't get a 204, you know you are behind a captive portal. You can run this in a loop until you do get a 204 in which case you know you are not behind a captive portal anymore.
#FlyWheel wrote: The only downside is this would also indicate that a web login is required when there is simply no internet connectivity on the WiFi access point.
You can solve this by registering a receiver to android.net.conn.CONNECTIVITY_CHANGE. You can check if Wifi is ON and is connected by looking at the Supplicant State of the connection.
Here is a snippet, but I didn't run it:
WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
WifiInfo wifiInfo = wm.getConnectionInfo();
SupplicantState suppState = wifiInfo.getSupplicantState();
if (wm.isWifiEnabled()) {
if (suppState == SupplicantState.COMPLETED){
// TODO - while loop checking generate_204 (FlyWheels code)Using intent service.
}
}
I can't remember if the SupplicantState is COMPLETED or ASSOCIATED, you will have to check that. You should use an IntentService for checking the generate_204 since broadcast receivers have a short lifetime.
I used the following code using google's 204 endpoint.
private boolean networkAvailable() {
ConnectivityManager mManager = (ConnectivityManager) getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
if(mManager != null) {
NetworkInfo activeNetwork = mManager.getActiveNetworkInfo();
if(activeNetwork== null || !activeNetwork.isConnectedOrConnecting()){
return false;
}
}
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("http://clients1.google.com/generate_204")
.build();
try {
Response response = client.newCall(request).execute();
if(response.code() != 204)
return false; // meaning it either responded with a captive html page or did a redirection to captive portal.
return true;
} catch (IOException e) {
return true;
}
}
Many applications including Google Chrome use http://clients1.google.com/generate_204 to verify that the the connection is not locked under captive portal.
The issue might rather be - today at least - that newer Android versions (5.1+?) keep the 3G/4G connection up and running until the wifi login actually leads to a fully functional wifi connection.
I haven't tried it, but maybe with the enum value CAPTIVE_PORTAL_CHECK of NetworkInfos DetailedState one can try to detect such a mode properly?
I am facing a tricky situation while working on a restricted network. Though I have my System Proxy Set to connect to my Web Server, Below are the two different behaviors observed from Web Browser and from Android Sockets .
1) With Proxy set, The Web Browser Request for the my server URL (host:port) goes well and I get 200 OK with valid Response Data from the Server.
2) With Android App, I do Host Reachability check before making my Connection Request. In Host reach-ability check , I create a java.net Socket and if it returns without any exception i consider my host as reachable. PSB for code snippet.
public static boolean isHostReachable(String hostname, int port) {
boolean isReachable = false;
Socket socket = null;
try {
socket = new Socket(hostname, port);
isReachable = true;
} catch (Exception e) {
.....
} finally {
....
}
return isReachable;
}
The whole logic of Host Reachability check works fine when in work from unrestricted network (lets say my home network).
The problem comes in the Host Reachability Socket Call , when I run my app from a restricted network (with Proxy Set to access my Server). Here my Socket Creation call does not return leading to host reach ability failure !!
There is a clear discrepancy between the browser and my app behavior in restricted network!!
My Question : While the Web Appllication works perfectly fine, What can be reason for the failure of above Socket Creation from Android leading to my Host Reachability failure in restricted network (with Proxy set in System Preference) and any suggestion for me to overcome this ?
i use following code to check 3g,edge connectivity in android phone application
public boolean isConnected()
{
try
{
final ConnectivityManager conn_manager = (ConnectivityManager)
this.getSystemService(Context.CONNECTIVITY_SERVICE);
final NetworkInfo network_info = conn_manager.getActiveNetworkInfo();
if ( network_info != null && network_info.isConnected() )
{
return true;
}
else
{
return false;
}
}
catch (Exception e)
{
return false;
}
}
if i connect it to wifi then this check does not work correctly
actually when wifi is connected to network and internet coverage is not there above check say ok infact its wrong any one guide me how to handle packet lost case like
internet comming then disconnnecting and this process keeps continue in android ?
or am i doing something wrong?
any help would be appreciated.
if i connect it to wifi then this check does not work correctly
Yes, it does, by your own admission.
actually when wifi is connected to network and internet coverage is not there above check say ok
That is what it is supposed to do. Your WiFi network is active, meaning Android is in communication with your access point. That is what "connected" means.
The only way you can tell if you can communicate to some host is to try to communicate to some host. Note that requestRouteToHost() reportedly has issues, so you would need to try something else (e.g., make an HTTP connection to a known good URL).