Here is a sample of my code
TextView textStatus = (TextView) findViewById(R.id.editText1);
ServerSocket serverSocket = new ServerSocket(SERVERPORT);
.
.
Socket client = serverSocket.accept();
.
.
textStatus.append("TEXT");
client.close();
This makes the android application force close. If I remove textStatus.append, than it works. Again, if I remove Socket client = ... and client.close(), it displays the TEXT on the screen.
So, the socket client = serverSocket.accept(); is affecting textStatus variable in some way.
Can anyone tell me what is wrong ?
textStatus is probably null. Check to make sure that R.id.editText1 is the actual id that you're using in your XML file.
Also, any potentially long running task should not be done on the UI thread. You're going to have very bad app preformance. Please see the Painless Threading article and try moving your server communication off to a different thread. Or consider using an IntentService instead. I prefer the IntentService.
Related
I seem to be having a small problem with MulticastSocket on Android: writing an SSDP-related application. The socket works just fine when I set everything up the first time, but when I stop discovery, and try to restart things, I just get a SocketException: Socket Closed. I'm not closing the socket, I'm simply stopping the Kotlin Coroutine that is responsible for calling socket.receive() in a loop. Example:
fun listenForPackets(): Flow<DatagramPacket> {
return flow {
multicastSocket.use {
val incomingBuffer = ByteArray(MULTICAST_DATAGRAM_SIZE)
while (true) {
val incomingPacket = DatagramPacket(incomingBuffer, incomingBuffer.size)
it.receive(incomingPacket)
emit(incomingPacket)
incomingPacket.length = incomingBuffer.size
}
}
}
}
The problem
So the problem is that when I try to call that function again, I get a SocketException: Socket Closed. The socket initialization code is run once, meaning that toggling discovery on/off will use the same socket multiple times; the following code is run once throughout the whole application:
multicastSocket = MulticastSocket(MULTICAST_PORT)
multicastSocket.reuseAddress = true
multicastSocket.joinGroup(multicastGroup)
multicastLock.acquire()
What I have tried
My first thought was that I was not cancelling the Kotlin Coroutine correctly. As a result, I switched to using typical Java Threads, to no avail. Starting the thread the first time works, but, restarting discovery yields the same problem. I have also tried to not leave the group, and keep the multicastLock acquired - same problem.
What works
What works is having the initialization code (where I assign the socket, join the group, and acquire lock) run every time I need to start a scan. At the end of the scan, I reset all of the variables (leave group, release lock, close socket). So my question becomes - is this the correct approach? Or am I simply doing something else wrong?
Just to re-iterate, I'm discovering packets just fine, the issue is with restarting the discovery. Thank you in advance for any help!
I am connecting to an XMPP server in Android using Smack. Here is my code:
static void openConnection() {
try {
if (null == connection || !connection.isAuthenticated()) {
XMPPTCPConnectionConfiguration.Builder configuration = XMPPTCPConnectionConfiguration.builder();
configuration.setHost(SERVER_HOST);
configuration.setPort(SERVER_PORT);
configuration.setServiceName(SERVICE_NAME);
configuration.setUsernameAndPassword(new TinyDB(context.getApplicationContext()).getString("username"), new TinyDB(context.getApplicationContext()).getString("password"));
configuration.setDebuggerEnabled(true);
connection = new XMPPTCPConnection(configuration.build());
connection.setUseStreamManagement(true);
connection.setUseStreamManagementResumption(true);
ReconnectionManager reconnectionManager = ReconnectionManager.getInstanceFor(connection);
reconnectionManager.enableAutomaticReconnection();
reconnectionManager.setReconnectionPolicy(ReconnectionManager.ReconnectionPolicy.RANDOM_INCREASING_DELAY);
connection.connect();
connection.login();
}
} catch (XMPPException xe) {
xe.printStackTrace();
} catch (SmackException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
So when I call openConnection() should I do that in an AsyncTask or is that not necessary? I am a little confused.
You should manage your XMPP(TCP)Connection within an Android Service. The service state (running/stopped) should reassemble the connection state: When the service is running the connection should be established or the service should try to establish the connection (if data connectivity is available). If the service stops, then also disconnect the connection.
When i call openConnection() should i do that in an asynctask or that is not neccesary?
Shortly, YES. Everything related with networking should be moved to another thread to avoid blocking main thread. Hence doInBackground() of AsyncTask runs on another thread, which is where you should call that function.
Yes, as the official documentation points it out:
AsyncTask enables proper and easy use of the UI thread. This class
allows to perform background operations and publish results on the UI
thread without having to manipulate threads and/or handlers.
I chose not to use AsyncTask for my smack project after searching around.
its threading model have been quite different between Android version and need to take care about, also after honeycomb, it is single thread, long blocking this will cause issue on the whole device that also use AsyncTask , xmpp and bosh can cause long blocking up to seconds/minutes
AsyncTask has implicit reference to activity and such a long operation will cause memory issues, or easy memory leakage when exception handling is not proper
AsyncTask 's result will be lost if reference activity got reset, but activity in Android can be reset as easy as a simple device rotation or network configuration change, too many save and restore instance to make this usable as every xmpp operation may be long task
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();
When I execute this code in android emulator
dataByte = new byte[1024];
ds = new DatagramSocket();
ds.setSoTimeout(3000);
dp = new DatagramPacket(dataByte, dataByte.length);
ds.connect(InetAddress.getByName(params[0]), Integer.valueOf(params[1]));
dp.setData("remdroid_test".getBytes());
ds.setSoTimeout(3000);
ds.receive(dp);
It results in not responding, what should i do?
Alternative suggestions on how to test a udp connection using Android are welcome.
If you are executing this code inside an Activity, then you are blocking the UI thread. If you block the UI for too long, then Android will force close your application.
One solution is to use an AsyncTask. The best option is probably to run it on a Thread from within a Service though.
I'm developping my first Android App. I need to execute a command in a shell as the root user so I've introduced this code in my App:
process = Runtime.getRuntime().exec("su");
Then I obtain an output stream to the process and I use it to execute the command:
os = new DataOutputStream(process.getOutputStream());
os.writeBytes("tcpdump\n");
Then I obtain an input stream which I want to use for displaying the results of the process:
is = new DataInputStream(process.getInputStream());
I would like to bind the obtained DataInputStream to a TextView in the layout so the text that it displays gets updated in real time as the process goes on showing results.
I've been searching trought the java.io API for android and I can't find an easy way to do this. I've been thinking in running a thread with a loop which continously checks if there is new data in the input stream and then copy it to the TextView but this seems a crappy solution.
I would thank you if anyone knows a way to do this.
Channel channel = session.openChannel("shell");
OutputStream os = new OutputStream() {
#Override
public void write(int oneByte) throws IOException {
TextView textView1 = (TextView) findViewById(R.id.textView1);
char ch = new Character((char) oneByte);
textView1.setText(textView1.getText() + String.valueOf(ch));
System.out.write(oneByte);
}
};
// channel.setOutputStream(System.out);
channel.setOutputStream(os, true);
Combine TextView.append method with Handler
Here is good example:
http://android-developers.blogspot.com/2007/11/stitch-in-time.html
I've been able to set a Handler and start a runnable which will read from the input stream every 200ms.
Despite this, it seems that the input stream isn't receiving any characters form the process standard output and everytime I call a read() method it gets blocked waiting for characters that never come. I've been trying following this two websites instructions without sucess:
http://gimite.net/en/index.php?Run%20native%20executable%20in%20Android%20App
http://code.google.com/p/market-enabler/wiki/ShellCommands
Thanks.
After one day of research and tests, I found that the only solution for this problem is using AsyncTask.
You can adapt this code, which is working fine: https://stackoverflow.com/a/9063257
It also works replacing ProcessBuilder() with Runtime.getRuntime() if you like it.