Let me tell you a bit about my app, when the app is in the background, I send some session data to my session_endpoint first, and if sending is failed, I get the exception that the host is unknown from try/catch and send it to same host, which is for sending exceptions exception_endpoint.
So my question is, how is it possible that I can send data to my exception_endpoint and cannot send to session_endpoint, is it about resolving domain ? sending methods are the same by the way. I lose my precious session data. How can I overcome this issue ?
I get java.net.UnknownHostException: Unable to resolve host.
There are several options how you can handle that exception. The simplest way is to cache the requests and fire them on the next app start.
You could also use the alarm manager to try it later or maybe even better use the JobScheduler, there you can define that you require network connectivity. If you need to support older platforms try the nice lib Android-Job. There you can define for much more platforms the scheduling.
Related
I have an Android application where I connect frequently to a web service that I control using SSL exclusively. The first thing a user does that results in network activity is login and I currently use the Ion library for this although I tend to think my issue is not specific to Ion. This works as expected except for one specific user that has limited all internet access on the Android device to only work with my web service. They have done this by using their router to create a firewall that blocks all traffic except the specified domains. When this firewall is turned on they can't login via the app because of the following error:
java.net.SocketException
recvfrom failed: ECONNRESET (Connection reset by peer)
They can use the browser to go to my website and access the same web service with the firewall turned on and everything works fine. In addition, they can turn the firewall off, login successfully (i.e. successfully initial the first connection), turn it back on and subsequent network connections continue to work. The user can even log off and log back in without issue. It continues to work with the filter on until they quit the app. When they then restart the app and try to login the error returns. This seems like very odd behavior and I'm not entirely sure it is an ion issue but I'm not sure what to do. Does anyone have any ideas on what could be causing this issue?
UPDATE:
Per a comment, I tested my application with Volley. It does appear that Volley works with the filter turned on. I would prefer to stick with Ion though due to some of its other feature so if anyone has any ideas on how to make Ion work in this scenario I would greatly appreciate the help.
I've been through different questions about this topic, however, none of them have cleared my doubts on the best approach notifying the client side of a server-client IM app.
The Problem:
The whole problem is how to notify the client application of updates. I've alread seen the following approaches:
Clients keeps checking for updates: From time to time, client app performs a check in the server to see if there are updates for that specific user;
Problem: it is not performatic at all. Suppose you have one million users and each one of them checks for new updates every second. Serve would have to deal with one million requests per second. Wont work.
Client app opens a socket: The client app opens a socket and sends its address to the server. Server, by its turn, persists this information and connects to the socket whenever it needs to notify the client of some update.
Problem: Often the client will be connected to a NAT, so, the IP it has access to is in a non-visible range. In order to send messages to this client, a port forwarding in the NAT would have to be configured, which can't be done.
Despite of the technology, I think this approach will always be used, however, I have no idea how the problem described above can be solved.
Google Cloud Message (GCM): use the GCM service to notify the client of any update. Problem: It does't seems right to use a third server to handle the IM and it raises concerns about the scalability of the system. When the number of messages and users increases exponentially, it seems that the service will go down. Despite that, it seems that passing the information for two servers before delivering to the targets just adds bottlenecks in the process.
A combination of 2 and 3: uses GCM to reach the client when the last persist addres is no longer available.
Problem: same as described in 2
XMPP: I've seen many answers indicating the use of XMPP for IM applications, however, XMPP is a protocol - as per what I've foun in the web. I don't see how it can solve the problem described in 2 for instance.
Given the options above, can someone indicate me what line should I try to go for? Which one of these approaches has the best chances of success?
Thank y'all in advanced.
Use Google Cloud Messaging. Opposing to what you stated this service is built to scale to billions of users it will generally not introduce performance bottlenecks.
What you basically want to do is to use the messaging service to wake up devices. If you insist you can then still use your client server approach and thus your own protocol to have the client lookup new messages from the backend.
An app I am working on relies on connecting to a private, remote server to login via an API.
The other day, I got an ANR message and I think it was due to the server being offline (its a Windows Server that was being updated).
In my app, I am using the following code:
new ReadJSONFeedTask().execute(url).get();
Which turns an AsyncTask into a synchronous task (I believe!)
And because the server was offline, I think the app got hung up, causing the ANR (it's my only lead at the moment, and all seems to make sense, despite the code above is inside a Service class, which shouldn't cause an ANR, should it?)
So, I want to try an simulate the server being offline. I tried replacing the URL with one that simply doesn't work, by removing some letters from the hostname, but that only triggered an "UnknownHostException".
Is there any way to achieve this kind of simulation? I know there are tools for browsers to simulate low bandwidth etc, but have no idea what could be done when my app is running on Android and is trying to connect to a remote server that I can't really reboot at will.
I'm writing a Java app which has a feature to check whether it's connected to the internet by periodically trying to access a server. My first idea was to Ping the server - but turned out to be complicated to achieve in Java. So I remade it to send HTTP HEAD requests and check for the HTTP response code instead. I have two questions:
1) Are HTTP HEAD requests "as reliable" as pings? Ping would be my first natural choice to check if something is available. Maybe just because it's so easy to run on the command line.
2) If I send HTTP HEAD requests to a third-party website to check if it is accessible, is there some standard frequency at which these should be sent? Eg if I send them every second, would that be discouraged or even get me blocked from those services?
An HTTP HEAD is generally more reliable than a ping, as ICMP connections are often blocked and HTTP is usually open. Checking for a connectivity every second sounds pretty excessive, but it really depends on your use case what third party site you are trying to "ping".
I can't comment on whether its more effective to use HEAD or trying to do something like drop to the system and do a ping; but I don't think either of them is the solution you should be doing. IMHO, it isn't necessary to poll your connection. There are a lot of situations where a connection could be dropped and I don't think polling will provide much in the way of mitigating the problem. Also, the user might be annoyed. I know that if I were using an application, and then started doing something else, and all of a sudden I got a "connection lost to 3rd party error" from an application I wasn't even paying attention to; I would be very annoyed.
If your application depends on a connection being present, then I think its fair to handle this with exception handlers. I'm willing to be bet that whatever API you're using throws some kind of exception whenever you attempt a network action and you aren't able to establish a connection. So, what I would do is in whatever class you're initializing the network action, I would follow this paradigm:
try {
performNetworkAction();
} catch (NoConnectionFoundException e) {
// handle the situation here
}
Your application shouldn't be able to determine when a connection was lost, just how to react when you attempt a network action and no connection is found.
That being said - you still may disagree with me. If that is the case then the frequency of polling allowed/recommended might be documented in the API for the service you're using. Also, if the resource from the 3rd party is static, you should cache it as opposed to getting it over and over again.
I wanted to expand #Dave's answer, and a comment would not suffice.
When you lose internet connectivity, a java.io.IOException is thrown. Look at the sub-classes of IOException - UnknownHostException, SocketException and ProtocolException are the ones that usually smell of "No Internet Connection"
Create a central place for handling exceptions (this is good practice in itself). If you get any of the IOException's I mentioned above, set isInternetAvailable to false.
Instead of polling for internet connection, switch to retrying the operation you want to perform. You achieve the same thing
Use a backoff strategy - exponential backoff works great. For example, after it fails the first time, you wait for 5s. After the second failure, you wait for 25s and so on. Gmail webapp uses this strategy. Twitter commons has utility classes for backoff.
I don't want to tell the hard way that the internet is unavailable when I catch an exception from url.openStream().
Is there a simple way to tell if the computer is connected to the internet in Java?
In this scenario, "connected to the internet" means being able to download data from a specific url.
If I try to download from it and it is not available, then the program hangs for a bit. I dont want that hanging. Therefore, i need a fast way of querying whether the website is available or not.
The problem you are trying to avoid is waiting for for your http connection to determine that the URL you are trying to access is really unavailable. In order to achieve this you need to stop using url.openStream() which is a shortcut for openConnection().getInputStream() and get some finer control over your connection.
URLConnection conn = url.openConnection();
conn.setConnectTimeout(timeoutMs);
conn.setReadTimeout(timeoutMs);
in = conn.getInputStream();
This code will allow you to timeout the connection attempt if either the connection or the read exceeds the time you provide in the timeoutMs paramater.
Use
Process p1 = java.lang.Runtime.getRuntime().exec("ping www.google.com");
System.out.println(p1.waitFor());
// return code for p1 will be 0 if internet is connected, else it will be 1
There is no such thing as "Internet availability".
Imagine that your HTTP request go through a transparent HTTP proxy, you are trying to access a blacklisted site and you get a HTTP response from the proxy server telling you about access denied. Is Internet available in this scenario or not?
I think you shall be more specific about your problem.
You might be able to tell if a compouter is connected to a network but even if it is there's no guarantee the networking is working or that it's connected to the internet.
This is one of those "suck it and see" problems.
What's wrong with trying to connect? And why are you concerned whether or not they're connected to the internet?
If the criteria is whether you can access a given web server the only way to find out, is to access that web server.
You can, however, do it in a background thread at start up so the application is not delayed by it. Then the "yes/no" answer is available when the actual downloading is desired. Put a message in the status line so the user knows what is going on and is not suprised about uninitiated "connect to network" if s/he is not connected when your program is started.
I don't know much about the low level HTTP plumbing available in Java, but you could always issue an http HEAD request for the url in advance. This causes the server to send back only the headers and not the data. With a 1-3 second timeout, you should be able to avoid any lengthy delays.
If you program is hanging while waiting to download then you are probably using the GUI thread to do the download. If you use a background thread, your program won't hang even if it take a long time to timeout/download.
You could send an ICMP message to a very well known host...
You can check for a NTP server if your firewall does not forbids.
Any way I think the best option is to try to open an URL as you try to avoid, because is the service most commonly to be opened.
You can check for one or two dynamic URL that change constantly. For instace, some web that shows time. For instance this one i found googleing. More than one because the sites can be down ;-)