From old posts such as Android java.net.UnknownHostException: Host is unresolved (strategy question), it suggested to use the following code:
try {
InetAddress i = InetAddress.getByName(URLName);
} catch (UnknownHostException e1) {
e1.printStackTrace();
}
So does it mean when a DNS entry is not being cached in the device, e.g. after bootup, it will return java.net.UnknownHostException: Host for the 1st time, even for a valid DNS?
It depends on the version of android.
Provided you have an Internet connection and that your application declares that it needs Internet access in the manifest file, then the address should resolve without any problems.
http://developer.android.com/reference/java/net/InetAddress.html
In Android 4.0 (Ice Cream Sandwich) and earlier, DNS caching was performed both by
InetAddress and by the C library, which meant that DNS TTLs could not be honored
correctly. In later releases, caching is done solely by the C library and DNS TTLs
are honored.
So if the address you are asking for is not older than the time to live, the cache will answer. If it is not in the cache or has expired then the OS will try to find it by going to a DNS server. The exception is thrown only when your Internet connection is not up, or when there is no DNS response, not when the cache request fails.
That said, if you are writing your application for older androids, then this problem may pester you still.
There are ways to deal with it:
Android: Flush DNS
Related
There is a task:
Get the names of all known wifi networks/paired devices. (actually done, was pretty easy)
Get the name of a network/device with the latest connection.
So, can I somehow get the connection time&date of each known network/device?
I'm looking for a solution to resolve .local host names with Android 4.0.4 (no NSD, due to API level 15). On the device I don't have any service to discover, just the hostname.
Could you please provide an example how to resolve? I integrated the jmDNS, but don't know how to use for host name resolving.
win-cmd:
ping kcmeasurement.local
Pinging kcmeasurement.local [10.202.0.29] with 32 bytes of data:
Reply from 10.202.0.29: bytes=32 time<1ms TTL=64
...
Thank you,
Daniel
I had almost the same requirements as your question, apart from the requirement to use jmDNS, so I solved it with NSD. I realize this doesn't address your question exactly, but thought it might still be somewhat helpful for yourself and others to see how I solved it.
I setup an NSD discovery listener and an NSD resolve listener, and within the discovery listener code, added a filter for the target host name (e.g. "kcmeasurement", or in my case, "garagedoor").
There is a blog post here which explains in detail how to do that. Refer to steps 3-4, which are dealing with the Android App code required.
http://www.dodgycoder.net/2015/02/setting-up-bonjourzeroconfmdnsnsd.html
For your case, I would imagine you would have to do the equivalent process but just using the jmDNS library instead of NSD.
You should be able to use the InetAddress class to resolve the hostname for a given IP address. For example, using the IP address provided in the original question, try the following:
try
{
String hostname = InetAddress.getByName("10.202.0.29").getHostName();
}
catch (UnknownHostException e)
{
Log.e("MyApplication", "Attempt to resolve host name failed");
}
Since this is a network operation, make sure that it is not performed on the UI thread.
EDIT
You should be able to resolve a local hostname with jmDNS as follows:
InetAddress localHost = InetAddress.getByName("10.202.0.29");
JmDNS jmdns = JmDNS.create(localHost);
String localHostName = jmdns.getHostName();
I'm using this to upload some file. It works if I in a local connection, but if I use a external connection, i get this message: 425 Can't open data connection. from the ftp server.
I use the org.apache.commons.net.ftp.FTPClient and org.apache.commons.net.ftp.FTPFile libs.
public static String gravaImagem(String photoFile) {
FTPClient mFtp = new FTPClient();
try {
mFtp.connect(FTPHOST, PORTA);
mFtp.login(USUARIO, SENHA);
mFtp.setFileTransferMode(FTPClient.BINARY_FILE_TYPE);
mFtp.setFileType(FTPClient.BINARY_FILE_TYPE);
String origem = Environment.getExternalStorageDirectory().getPath()+File.separator+"Pictures"+File.separator+"ImageSec"+File.separator+photoFile;
FileInputStream fis = new FileInputStream(origem);
mFtp.storeFile(photoFile, fis);
mFtp.logout();
mFtp.disconnect();
} catch (SocketException e) {
e.printStackTrace();
return "Fail. (ERR#CON3)";
} catch (IOException e) {
e.printStackTrace();
return "Fail. (ERR#CON4)";
}
return "Imagem enviada ao servidor.";
}
Debug shows no exceptions.
From the internet:
First - the most common solution: change the active/passive mode
settings. But that might not work, and if it does its only a band-aid
covering up the real problem.
As I've mentioned in the past, one of the most common reasons that
this error occurs is a misconfiguration of the FTP server software
itself, related to SSL connections and firewalls, in which the
connection tries to establish itself on a bogus ip address. Read more
about FTP SSL through a NAT firewall here, some potential solutions
are included.
There are other less likely causes, such as:
The server is configured to always use the same port for passive mode connections, or the client is configured to always use the
same port for active mode connections, although in this case
usually the software in question should raise a different error
first, but I've seen this happen.
In passive mode, the firewall in front of the FTP server doesn't have the correct ports open. So the server tells the client to
connect to ipaddress 1.2.3.4 on port x, but the firewall doesn't
allow incoming connections on port x. Most firewalls are smart
enough to open up the port when it sees the PASV response. Vice
versa for active mode and the firewall in front of the FTP client.
From me:
I've used this library on andoird and it worked well, so see my copy/paste section.
I'm trying to set up SSL (with SSL resumption) using HttpsURLConnection with my own trust manager.
I am only able to perform ssl handshakes and connections. No SSL resumption - The previous sessions are never reused!
I searched all over, but no luck.
All answers refer to HttpClient (which is not an option).
My setup is as follows:
I create an SSL Context which I store for later use.
I then create an SSL Factory using this SSL context which I also store for it to be used with all connections.
I start a connection where everything goes well:
I receive a sessionID, a complete handshake is done and the connection is sent to the server.
One minute later, I start another connection. For some weird reason, this connection does not send the sessionID I had earlier.
I print the SSLContext's session - The last session is still there and is valid.
For some reason this new connection does not use it, thus another session is created and is added to the sessions' cache.
I tried both android version 2.3 and 4.1 as well on 2 different devices.
Following many google results I even tried to add Keep-Alive as some users proposed, as well as other voodoo that led to no different results.
Did anyone run into this? Is there something I'm missing?
What could cause my connections not to use the last session?
Thanks in advance!
What you'd like to do is use reflection to override members in class android.net.SSLCertificateSocketFactory, the members are:
HOSTNAME_VERIFIER
mTrustManagers
mKeyManagers
Do it by getting the class:
Class<?> sslClass = Class.forName("android.net.SSLCertificateSocketFactory");
Field classField = sslClass.getDeclaredField("defaultTrustManager");
classField.setAccessible(true);
classField.set(null /*If Feild is static*/, youObjectHere /*Needs casting*/);
classField.set(objectInstance /*If Feild is not static*/, youObjectHere /*Needs casting*/);
and then:
Override these with you own variables. This will allow for SSL resumption for Android API 14 and above (I tested on 14).
BEWARE
You'd need to maintain this code and keep up with any changes Google might do.
Hope it helped! Good luck!
I tried connecting to an IP address (e.g. http://222.222.222.222:8080) and a URL (e.g. http://www.website.com) while my wiFi is disabled. I noticed that if I don't have a wiFi and I tried connecting to an IP address, it gives me a ConnectException error. On the other hand, if I don't have a wiFi and I tried connecting to a URL, it gives me an IOException error. Why am I receiving different Exception for the 2 cases when the only difference is I supplied an IP address for the first one and a URL for the other? Can someone enlighten me on this one? I am asking this for clarification.
Thank you!
You're getting different errors because different steps are failing.
When you're trying to connect to port 80 of an IP address, it is a connect(2) system call that is failing. There are many different reasons why connect(2) could fail; you'll need to inspect the message from the exception to provide a good error message to the user.
When you're trying to connect to port 80 of a textual address, the libraries will first try to resolve the hostname into an IP address using getaddrinfo(3). The name resolution may or may not fail based on having network access -- if you were trying to connect to localhost, for example, no network access is usually required, as the nameservice lookup can be handled entirely on the local device. Because the nameservice failure happens because you cannot contact a nameserver, it makes sense to give a different error message (and exception), even if the underlying cause is the same for a given set of tests. You might not be able to contact the nameservers for any variety of reasons. Again, you'll need to inspect the message from the exception to give a good error message to the user.