Hi all I have been struggling with this for a while now and cannot find a solution.
In java this code works:
InetAddress serverAddr = InetAddress.getByName("myservice.local");
Socket socket = new Socket(serverAddr, PoolServerAddress.DEFAULT_PORT);
The same in android doesn't work. I have tried removing ".local" and adding all the necessary permsissions in the manifest:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
I have also tried adding multicast lock bfore executing that code but no way to solve this.
I get the following exceptions:
06-03 13:18:14.438: W/System.err(31636): java.net.UnknownHostException: Unable to
resolve host <server_name>: No address associated with hostname
06-03 13:18:14.438: W/System.err(31636): at
java.net.InetAddress.lookupHostByName(InetAddress.java:434)
06-03 13:18:14.438: W/System.err(31636): at
java.net.InetAddress.getAllByNameImpl(InetAddress.java:239)
06-03 13:18:14.438: W/System.err(31636): at
java.net.InetAddress.getByName(InetAddress.java:292)
06-03 13:18:14.438: W/System.err(31636): at
com.example.jelly_test.MainActivity.connect(MainActivity.java:113)
06-03 13:18:14.438: W/System.err(31636): at
com.example.jelly_test.MainActivity$ResolvingThread.run(MainActivity.java:71)
06-03 13:18:14.438: W/System.err(31636): Caused by: libcore.io.GaiException:
getaddrinfo
failed: EAI_NODATA (No address associated with hostname)
06-03 13:18:14.438: W/System.err(31636): at libcore.io.Posix.getaddrinfo(Native
Method)
06-03 13:18:14.438: W/System.err(31636): at
libcore.io.ForwardingOs.getaddrinfo(ForwardingOs.java:55)
06-03 13:18:14.438: W/System.err(31636): at
java.net.InetAddress.lookupHostByName(InetAddress.java:415)
06-03 13:18:14.438: W/System.err(31636): ... 4 mor
If I provide ip instead of service it works but I need to be able to provide the name. Also I have tried adding JmDNS resolving the name into ip but it is slow and only works on internal services at the office but some of our services are external to the network but they are still accessible with the java version but not android. Is there anything else I could try? Thanks a lot as am running out of ideas....!
EDIT: I think my problem is due to the fact that there is a bug in android and it only accepts FQDN such as: myservice.company.com
As requested here are the options I have found to temporary solve this problem as even in the latest Android version (4.4 at the time of writing) the bug has still not been fixed.
Make sure ou add all the required permissions indicated in the question, to the manifest.
Option 1: Use JmDNS library to discover a list of available servers and find yours, if you don't know how here is a good tutorial: http://home.heeere.com/tech-androidjmdns.html This method is slow and I ahve found that some services do no show (they have to advertised with zeroconf)
Option 2: Ask your users to enter fully qualified domain name such as name.comany.com instead of name.local
Option 3: This is really a hack but if you know that the FQDN is of type someName.myComp.com and the user entered someName.local you have to remove ".local" and try to guess what the domain is:
private String getTargetIp(String host) {
System.out.println("Will try to create socket with "+host);
MulticastLock multicastLock = null;
String ipToReturn = null;
Socket socket = null;
try {
WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
multicastLock = wifiManager.createMulticastLock("any_name");
multicastLock.acquire();
DhcpInfo info = wifiManager.getDhcpInfo();
int ip = info.ipAddress;
InetAddress local = getInetAddress(ip);
String localHostName = local.getCanonicalHostName();
Log.d(TAG, "Device ip addr1 = "+local +" name= "+localHostName);
String[] temp = localHostName.split("\\.");
//replace the first part with our name and obtain FQDN
String targetFullHostName=localHostName.replace(temp[0], host);
Log.d(TAG, "targetFullHostName = "+targetFullHostName);
//this is not mandatory but here we are trying to retrieve the ip address
//it maybe also a way to check if we guessed right
InetAddress serverAddr = InetAddress
.getByName(targetFullHostName);
socket = new Socket(serverAddr,
PoolServerAddress.DEFAULT_PORT);
ipToReturn = socket.getInetAddress().getHostAddress();
Log.d(TAG, "socket remote address=" + ipToReturn);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}catch(Exception e){
Log.e(TAG, "Other Exception");
}
finally {
if (multicastLock != null)
multicastLock.release();
if(socket!=null)
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return ipToReturn;
}
Option 4: Starting with api level 16, you can use Android Service Discovery listener to list available services and find the one you are looking for. This works in a similar way to JmDNS: you discover all services and try to find yours in the list. Here is the link to the doc: http://developer.android.com/training/connect-devices-wirelessly/nsd.html#discover