I am developing a google glass/android application. It is a video streaming application that has a server/client setup where the phone/glasses is the server and hooks the pc up with the session description for playing the video. It works great on the android and everything runs fine but as soon as I try to test it on the google glass it throws an error at this line
sSocket = new ServerSocket(sPort);
The exception message says "EADDRINUSE" which I'm assuming means the port is already opened but I never opened it. Even if I had opened it and my program didn't close it I changed the port a couple of times and it still says it's in use.
Thanks
Tyler,
Google Glass, like android, consistently will have many of it's ports occupied by applications running in the background. When creating a socket for your server to listen on, you have two choices:
1) Have a predetermined list of ports you can choose to have your server listen on.
If you choose to do this, then you can simply have a datastructure (list, queue, heap [if you have some priority of which ports you would like to use], etc) which contain all of your ports, then you can simply traverse them until you find an open port.
This can be achieved in the following manner:
private ServerSocket allocatePort(List<Integer> myArray) throws IOException {
for (int individualPort : myArray) {
try {
return new ServerSocket(individualPort);
} catch (IOException io) {
continue; // An exception will be thrown if this port is currently in use. It's OK, let's try another port.
}
}
// When no ports are available, let's throw an exception stating we were unable to find an open port.
throw new IOException("we were unable to find an open port");
}
Then simply invoke this method within your as follows:
int[] arrayOfPorts = {5000, 5001, 5002, 8000, 8001, 8002, 8003};
List<Integer> myArray = new ArrayList<>();
myArray = IntStream.of(arrayOfPorts).boxed().collect(Collectors.toList());
ServerSocket sSocket = allocatePort(myArray);
2) If you don't mind which port to listen in on, you can use the constructor to pick any available port.
This can be achieved as follows:
ServerSocket sSocket = new ServerSocket(0);
You can read up more on ServerSocket's Javadocs. Notice under the parameter's subsection:
port - the port number, or 0 to use a port number that is automatically allocated.
Please let me know if you have any questions!
Related
With this setup, I've been able to get two android phones to send and receive UDP broadcasts. I can also use this setup to send a UDP broadcast from a physical Android device to an iPhone.
However, my problem is that it doesn't seem to work the other way around. The send function is ran on the iPhone, and the receive function is being run on the Android phone. The Android phone never gets the broadcast. It seems like something is wrong with the iPhone's sending function. Here's the setup:
The Android side that has worked for me before:
const port = 37069;
const address = '224.0.0.1';
void receive() async {
final socket = await RawDatagramSocket.bind(address, port);
socket.multicastHops = 1;
socket.broadcastEnabled = true;
socket.writeEventsEnabled = true;
socket.listen((RawSocketEvent event) {
print("still listening...");
final packet = socket.receive();
print("The packet was $packet");
print("It came from ${packet?.address}");
});
}
and this is the iPhone side, that seems to be the problem. I'm not getting errors, so I'm wondering if there are any permissions in the Info.plist file that need to be added?
void broadcast() {
// for the iphone
RawDatagramSocket.bind(address, port).then((RawDatagramSocket socket) {
socket.multicastLoopback = false;
socket.broadcastEnabled = true;
socket.readEventsEnabled = true;
for (int i = 0; i < 150; i++) {
socket.send("Sent #$i".codeUnits, InternetAddress(address), port);
print("sent $i");
}
socket.close();
});
}
I've tested this same setup in my project, and it has worked in the following situations:
Android -> Android
Android -> iOS
but, iOS -> Android doesn't work. When I run the app, I can see that the iPhone is indeed sending the data, but the Android isn't receiving anything. Is the Android side the problem? What am I doing wrong?
I ended up using a package called Bonsoir to achieve what I wanted to.
It lets you broadcast and receive network services, and I'm pretty sure its the same underlying technology as household programs like Airplay and Google Casting. It's also very reliable and simple to use.
To send a certain string, I passed in a string argument in the form of a dictionary into the attributes attribute within the BonsoirService class.
The package can be found here.
Ok so I am doing something that seems like it should be very easy. I am basically trying to open up a ServerSocket connection and then wait for the client to connect.
Here is my code.
ServerSocket serverSocket = new ServerSocket(6543);
Socket clientSocket = serverSocket.accept();
Whenever my code hits, serverSocket.accept();, I am throwing the following exception.
bind failed: EADDRINUSE (Address already in use)
So obviously my next step was to check and see if another port would work, it did not. Next I restarted the device and tried running the app and I got the same exception. I have given my app INTERNET permission and the device is rooted.
Here are my network interfaces that show up.
lo: ::1%1
lo: 127.0.0.1
eth0: //IPV6 address
eth0: 192.168.1.127
EDIT 1
Here is the serverSocket object info that I get when debugging.
ServerSocket[addr=192.168.1.121/192.168.1.121,port=0,localport=1234]
EDIT 2
I have the following available constructors in my ServerSocket
new ServerSocket(int port)
new ServerSocket(int port, int backlog)
new ServerSocket(int port, int backlog, InetAddress localAddress)
I tried using the 3rd constructor and same exception.
new ServerSocket(4567, 0, InetAddress.getLocalHost());
Alright so I finally figured out why my application was throwing an exception and if anyone has some feedback on this or would like to provide an answer as to why this was happening. I would greatly appreciate it.
So in my Thread that I created I need to postback to the main thread to update some TextView's based upon what was happening with the server connection. Well since I can't update the main thread from my self created thread I needed to add a Handler object to that Thread in order to update the UI. Removing that Handler completely allowed my application to successfully create the ServerSocket without throwing an exception.
Does the Handler somehow run the code before hand or what was happening here?
The code.
RemoteServerRunnable test = new RemoteServerRunnable();
Handler handler = new Handler();
handler.post(test);
test.start();
I'm having a little trouble here, on one hand I have a server listening on port 23000 and on the other an Android App acting as the client. While connection seems to work in the Emulator (this is built for 2.3.3 by the way) using the typical 10.2....IP, when trying on a Samsung Galaxy Tab I keep on getting the famous:
"Address family not supported by protocol exception"
Eventually, code looks like this:
InetSocketAddress inetAddress;
//this is done to keep backward compatibility prior 2.0.4 release
if(host == null || host.equals("")) {
//check if defaultIp is also empty
if (defaultIPAddress == null || defaultIPAddress.equals(""))
throw new UnknownHostException();
//otherwise start listening on defaultIp
else
{
inetAddress = new InetSocketAddress(defaultIPAddress, port);
}
}
//start listening on host
else
{
inetAddress = new InetSocketAddress(host, port);
}
// open the socket channel
this.channel = SocketChannel.open(inetAddress);
this.channel.configureBlocking(false);
this.channel.socket().setTcpNoDelay(true);
It fails when trying to open the socket at
this.channel = SocketChannel.open(inetAddress);
Needless to say, I have the required permissions in my Manifest, as said previously, this is working fine in the Emulator.
Besides, this is no network issue, both machines are connected to a Wireless Wifi created using a router I have at hand, with no firewalls, proxys, completely open, to put it that way...
Any ideas?
Thanks!
Alex
If anybody lands on this question and is having the same issue, this was caused because I was trying to open the Socket in the same thread of the main Activity. Looks like this is a) not advisable and b) not permitter any longer. Thus, move your connecting code to a separate thread and you should be safe.
I'm writing an Android app which receives information from a Bluetooth device. Our client has suggested that the Bluetooth device (which they produce) will change its name depending on certain conditions - for the simplest example its name will sometimes be "xxx-ON" and sometimes "xxx-OFF". My app is just supposed to seek this BT transmitter (I use BluetoothAdapter.startDiscovery() ) and do different things depending on the name it finds. I am NOT pairing with the Bluetooth device (though I suppose it might be possible, the app is supposed to eventually work with multiple Android devices and multiple BT transmitters so I'm not sure it would be a good idea).
My code works fine to detect BT devices and find their names. Also, if the device goes off, I can detect the next time I seek, that it is not there. But it seems that if it is there and it changes name, I pick up the old name - presumably it is cached somewhere. Even if the bluetooth device goes off, and we notice that, the next time I detect it, I still see the old name.
I found this issue in Google Code: here but it was unclear to me even how to use the workaround given ("try to connect"). Has anyone done this and had any luck? Can you share code?
Is there a simple way to just delete the cached names and search again so I always find the newest names? Even a non-simple way would be good (I am writing for a rooted device).
Thanks
I would suggest 'fetchUuidsWithSdp()'. It's significance is that, unlike the similar getUuids() method, fetchUuidsWithSdp causes the device to update cached information about the remote device. And I believe this includes the remote name as well as the SPD.
Note that both the methods I mentioned are hidden prior to 4.0.3, so your code would look l ike this:
public static void startServiceDiscovery( BluetoothDevice device ) {
// Need to use reflection prior to API 15
Class cl = null;
try {
cl = Class.forName("android.bluetooth.BluetoothDevice");
} catch( ClassNotFoundException exc ) {
Log.e(CTAG, "android.bluetooth.BluetoothDevice not found." );
}
if (null != cl) {
Class[] param = {};
Method method = null;
try {
method = cl.getMethod("fetchUuidsWithSdp", param);
} catch( NoSuchMethodException exc ) {
Log.e(CTAG, "fetchUuidsWithSdp not found." );
}
if (null != method) {
Object[] args = {};
try {
method.invoke(device, args);
} catch (Exception exc) {
Log.e(CTAG, "Failed to invoke fetchUuidsWithSdp method." );
}
}
}
}
You'll then need to listen for the BluetoothDevice.ACTION_NAME_CHANGED intent, and extract BluetoothDevice.EXTRA_NAME from it.
Let me know if that helps.
I encountered a very strange problem while sending files, such as pictures, text and zip files to server via ftp. Most of the time, it works fine. But sometimes, the server only has part of the file.
On Android, I use com.enterprisedt.net.ftp.
Here is the code piece to send a file:
public void ftpUploadFiles(ArrayList<String> fileList, boolean bDeleteAfterUploaded)
{
if(fileList.size() <= 0)
return;
// set up to transfer the files
FileTransferClient ftp = null;
try
{
//Make sure there is only FTP in the whole system at any given time.
synchronized(this)
{
// create client
ftp = new FileTransferClient();
// set remote host
ftp.setRemoteHost("xxxxxxx");
ftp.setUserName("xxxxxx");
ftp.setPassword("xxxxx");
// connect to the server
ftp.connect();
ftp.getAdvancedFTPSettings().setConnectMode(FTPConnectMode.PASV);
//1. Upload each file
for(int i = 0 ; i < fileList.size(); i++)
{
if(!FileKit.fileExist(fileList.get(i)))
continue;
ftp.uploadFile(fileList.get(i), FileKit.getFileName(fileList.get(i)));
if(bDeleteAfterUploaded)
FileKit.fileDelete(fileList.get(i));
}
ftp.disconnect();
} //End of synchronized
} catch (Exception e)
{
FileKit.handleException(e);
}
}
FileKit is a static wrap-up class for regular file functions. ftpUploadFiles() is called in a separate thread by an Intent so it can run in background. What seems to happen is, the ftp stops before finish transferring the file completely, so the server only gets part of the file. Based on the code above, what could possibly cause the problem? Or is it possible that is a issue with com.enterprisedt.net.ftp?
Thanks.
Your code appears to handle complete files only. So it should either succeed or fail for complete files only. That leaves only the com.enterprisedt.net.ftp package, which may send files in parts, for example when network failures occur.
There can be a problem if the transfer is interrupted due to network congestion, etc. "If the network connection is interrupted, the server may still think you are connected (as quit() has not been called). Hence a new connection and attempt to resume may fail for the reason given below." (https://enterprisedt.com/forums/viewtopic.php?t=960)
So I think that either the ftp software has a bug on network failure, or your code isn't handling the ftp software's handling of network failures.