Reading from socket inputstreams causing android UI to freeze - java

I'm trying to write this program which updates itself on the current status of a variable. How I intended it to work is by having a timed task to constantly send the string "update" to the server. The server will recognize the string and will send the necessary values for the variable on the android device. However, I am facing some problems. The string "update" is sending without error but when the corresponding value from the server is sent back, the program does not seem to be able to read the reply. Here is the code:
//Open socket and initialize data streams
try {
socket = new Socket(serverIpAddress, applicationport);
//in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//in = new DataInputStream(socket.getInputStream());
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
socket.getOutputStream())), true);
} catch (UnknownHostException ex) {
// TODO Auto-generated catch block
ex.printStackTrace();
ShowDialog("Login Error" + ex.getMessage());
} catch (IOException ex) {
// TODO Auto-generated catch block
ex.printStackTrace();
ShowDialog("Login Error" + ex.getMessage());
}
//Create new daemon timer
updateData = new Timer(true);
updateData.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
out.println("update");
UpdateMethod();
}//run
}, 1000, 10000);//schedule the delays start/interval here
};
private void UpdateMethod() {
//This method is called directly by the timer
//and runs in the same thread as the timer.
//It calls the method that will work with the UI
//through the runOnUiThread method.
this.runOnUiThread(Timer_Tick);
};//timermethod
private Runnable Timer_Tick = new Runnable() {
public void run() {
try {
//in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//String getx1 = null;
//getx1 = in.readLine();
//if (getx1 != null) {
//float updatex1 = Float.parseFloat(getx1);
//get_x1 = getx1;
//}
in = new DataInputStream(socket.getInputStream());
/*try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
x1display = (TextView) findViewById(R.id.x1display);
x1display.setText(in.readUTF());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally {
if (in != null){
try {
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
};
As you can see, I have tried experimenting with both DataInputStream and BufferedReader as well but to no avail.
Edit: It seems that trying to read from the input stream is causing my UI to freeze up. I have no idea what is wrong as my code seems to be without errors..
Any help or advice would be greatly appreciated!
Thank you!

The code looks fine to me. But its not working so looks like you need to chop it up.
Test if the socket stuff is working without the Timer. Make a socket connection and read its response without the Timer and UI code
If that works, introduce the Timer but not the UI code
If that works, do the whole thing (which is failing now)
Somewhere in this test process you should be able to find the culprit

As you have already said, reading blocks the thread. You shouldn't ever read something inside the UI thread! Furthermore, as I remember correctly, closing input before closing output does some nasty things. I would suggest closing the socket instead and putting the BufferedReader back in. This is how it should look like:
//Open socket and initialize data streams
try {
socket = new Socket(serverIpAddress, applicationport);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
socket.getOutputStream())), true);
} catch (UnknownHostException ex) {
ex.printStackTrace();
ShowDialog("Login Error" + ex.getMessage());
} catch (IOException ex) {
ex.printStackTrace();
ShowDialog("Login Error" + ex.getMessage());
}
//Create new daemon timer
updateData = new Timer(true);
updateData.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
out.println("update");
runOnUiThread(new Runnable() {
#Override
public void run() {
try {
x1display = (TextView) findViewById(R.id.x1display);
x1display.setText(in.readUTF());
} catch (IOException e) {
e.printStackTrace();
}
});
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}}, 1000, 10000);//schedule the delays start/interval here
By the way, don't use printStackTrace(): Why is exception.printStackTrace() considered bad practice?

Related

Android Socket Read Problems

I have created a socket that connects to a Raspberry pi hot spot. I am able to successfully connect to it and send a string to the pi. However, since I have tried to implement read functionality to get data from the pi, I have had some issues.
Every time I run the while loop or just have a "response = myBufRead.readLine()", the program stalls.
private class StatusCheck extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
//debug vibrations and text
if(vibrate) {
Vibrator vib = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
vib.vibrate(100);
}
try {
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
Log.d(debugStr, "In initial connect");
mySocket = new Socket(serverAddr, SERVERPORT);
} catch (UnknownHostException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
} finally {
if (mySocket == null) {
str1 = "Socket became null";
return null;
}
str1 = "Connected";
try {
PrintWriter myPrintWriter = new PrintWriter(mySocket.getOutputStream(), true);
InputStreamReader myInputStreamRead = new InputStreamReader(mySocket.getInputStream());
BufferedReader myBufRead = new BufferedReader(myInputStreamRead);
Log.d(debugStr, "In out created");
myPrintWriter.write(recordName);
Log.d(debugStr, String.valueOf(myBufRead.ready()));
Log.d(debugStr, "About to enter while loop");
while((response = myBufRead.readLine()) != null) {
Log.d(debugStr, "in while loop");
response = myBufRead.readLine();
Log.d(debugStr, String.valueOf(myBufRead.ready()));
Log.d(debugStr, myBufRead.readLine());
Log.d(debugStr, String.valueOf(myBufRead.ready()));
}
Log.d(debugStr, "out of while loop");
myPrintWriter.close();
myInputStreamRead.close();
myBufRead.close();
} catch (IOException e1) {
e1.printStackTrace();
}
try {
mySocket.close();
} catch (IOException e1) {
e1.printStackTrace();
}
return null;
}
}
}
Anyone know why this is happening? Any help is appreciated, thanks!
BuffereadReader.readLine() is a blocking method, so it will wait and, as you say, "stall" its thread until it has something to read. Are you calling flush() after you write to the stream from your pi?
Another issue might be that readLine() will wait for a complete line, i.e. it will wait until it reads a line separator character. Are you sending a line separator character from your pi? See Socket Multithreading - Reading input stream pauses thread
You can do (from the pi end, assuming you're using a BufferedWriter):
bufferedWriter.write(text);
bufferedWriter.newLine();
bufferedWriter.flush();

android client side doesnt read after a while

It's my first question in here. I hope i can find answer. Subject is that, i have server (arduino). it send and receive data.it send data when take a data from client side(android). Android side is send data when push button. Also android has use Speech to Text (google API).So when we push button or use speechrecognation, client side send a data.But it reads socket continuously. I have two kind android device. One device work well about data receiving but it is not good about speechrecognation. One device very well about voice but after a while socket is happened useless. We must push reset button on arduino and reset android app. (My first android device version is 5.1.1 second is 6.0). Sorry for my english. I hope i can tell my problem :)
.
.
.
public void senddata(String asd){
try {
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())),
true);
out.println(asd);
out.flush();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
.
.
.
class ClientThread implements Runnable {
#Override
public void run() {
BufferedReader inStream = null;
try {
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
socket = new Socket(serverAddr, SERVERPORT);
//socket.setSoTimeout(1000);
// Get the input and output streams
inStream = new BufferedReader(new
InputStreamReader(socket.getInputStream()));
// Confirm that the socket opened
// Read messages in a loop until disconnected
while( true){
String msg= inStream.readLine();
Log.e("GELENLER::::",msg);
gelenkomut=msg;
runOnUiThread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
gelenparse(gelenkomut);
}
});
// Send it to the UI thread
}
} catch (UnknownHostException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
finally {
try {
inStream.reset();
inStream.
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

EOFException after readUTF randomly

I am developping an Android app and a java desktop app. The Android app send to the java desktop the sms received, and the desktop app provide an interface for answering to these sms.
The android app is the server, the desktop app connects to it through a socket.
Here is the code of the server (android app side)
public class Server extends AsyncTask<Void, Void, Void> {
public void stopServ(){
this.run=false;
}
public void newSMSReceived(String sms, String phone){
//SEND THE NEW SMS TO THE DESKTOP APP
try {
outputStream.writeUTF(new String(sms.getBytes(),"ISO-8859-1"));
outputStream.flush();
outputStream.writeUTF(new String(phone.getBytes(),"ISO-8859-1"));
outputStream.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
protected Void doInBackground(Void... params) {
ServerSocket ss = null;
try {
ss = new ServerSocket(TCP_SERVER_PORT);
Socket s = ss.accept();
System.out.println("connection received !");
inputStream = new ObjectInputStream(s.getInputStream());
outputStream = new ObjectOutputStream(s.getOutputStream());
outputStream.writeObject(contacts);
outputStream.flush();
while(true){
//READ THE MESSAGE SENDED FROM THE DESKTOP APP
message=inputStream.readUTF();
phone=inputStream.readUTF();
smsManager.sendTextMessage(phone.replaceFirst("0", "\\+33"), null, message, null, null);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
if (ss != null) {
try {
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
}
The desktop app side :
public class Main extends Application {
public Main(){
try {
PropertiesRetriever prop = new PropertiesRetriever();
socket = new Socket(prop.getIp(), 5657);
outputStream = new ObjectOutputStream(socket.getOutputStream());
inputStream = new ObjectInputStream(socket.getInputStream());
Thread listener = new Thread(new Runnable() {
public void run() {
while(true){
String message,phone;
Contact contact;
try {
//RECEIVED THE MESSAGE FROM THE ANDROID APP
message=inputStream.readUTF();<--- EOFException
phone=inputStream.readUTF();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
listener.start();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public void sendMessage(Contact contact, Message message){
try {
//SEND THE MESSAGE TO THE ANDROID APP
outputStream.writeUTF(message.getTextUTF());
outputStream.flush();
outputStream.writeUTF(contact.getPhoneUTF());
outputStream.flush();
System.out.println(message);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**...**/
}
The details of the method "getxxUTF":
String rtr=null;
try {
rtr = new String(text.getBytes(),"ISO-8859-1");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return rtr;
EOFException :
java.io.EOFException
at java.io.DataInputStream.readUnsignedShort(DataInputStream.java:340)
at java.io.ObjectInputStream$BlockDataInputStream.readUnsignedShort(ObjectInputStream.java:2818)
at java.io.ObjectInputStream$BlockDataInputStream.readUTF(ObjectInputStream.java:2874)
at java.io.ObjectInputStream.readUTF(ObjectInputStream.java:1073)
Thing is, at a point, I get an EOFException on the readUTF mentioned above. Everything works fine until a certain point, and I have no clue why... Someone ?
You get this not 'randomly' but when the peer has closed the connection.

Program stop working when try to read input stream

I have a Java Server and one(or more) Android Clients. For now I want them to communicate simply with strings. When i write from android I can get the data in Java Server, but when I try to get the answer from server the Android application stop working. The codes is reported below:
Java Server:
public class Server {
private static int port=12346, maxConnections=0;
// Listen for incoming connections and handle them
public static void main(String[] args) {
int i=0;
try{
ServerSocket listener = new ServerSocket(port);
Socket server;
while((i++ < maxConnections) || (maxConnections == 0)){
doComms connection;
server = listener.accept();
String end = server.getInetAddress().toString();
System.out.println("\n"+end+"\n");
doComms conn_c= new doComms(server);
Thread t = new Thread(conn_c);
t.start();
}
} catch (IOException ioe) {
System.out.println("IOException on socket listen: " + ioe);
ioe.printStackTrace();
}
}
}
class doComms implements Runnable {
private Socket server;
private String line,input;
public doComms(Socket server) {
this.server=server;
}
#SuppressWarnings("deprecation")
public void run () {
input="";
try {
// Get input from the client
DataInputStream in = new DataInputStream (server.getInputStream());
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(server.getOutputStream())),
true);
while((line = in.readLine()) != null && !line.equals(".")) {
input=input + line;
}
JOptionPane.showMessageDialog(null, input);
out.println("Enviado");
server.close();
} catch (IOException ioe) {
System.out.println("IOException on socket listen: " + ioe);
ioe.printStackTrace();
}
}
And Android client's code (it's called every time a button is pressed inside onClick method):
public String enviaMensagem(){
String resposta="";
new Thread(new ClientThread()).start();
Socket socket = null;
DataOutputStream dataOutputStream = null;
DataInputStream dataInputStream = null;
try {
socket = new Socket(ip, port);
dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataInputStream = new DataInputStream(socket.getInputStream());
dataOutputStream.writeUTF(input.getText().toString());
resposta = dataInputStream.readUTF();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
if (socket != null){
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (dataOutputStream != null){
try {
dataOutputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (dataInputStream != null){
try {
dataInputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return resposta;
}
You are using an unsorted mixture of readUTF(), writeUTF(), readLine(), etc. They're not all interoperable. Settle on one of them. If you use writeUTF() you must use readUTF() at the other end. If you use readLine() you must write lines at the other end, with a line terminator such as \r\n or \n.

multithreaded server: SwingWorker Vs Thread?

is all in the title :
I create a java client , that sends a message to server when I click a button , several client can connect in same time,here is my source code:
the client:
private void simulerMessageActionPerformed(java.awt.event.ActionEvent evt) {
try {
log.append("wait for connexion..\n");
socket=new Socket(ip.getText(),Integer.parseInt(port.getText()));
log.append("Connexion to the server ok");
BufferedReader in = new BufferedReader( new InputStreamReader(socket.getInputStream()) ); ligne.
PrintWriter out = new PrintWriter( new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())), true);
String str = "test1";
log.append("\n"+str+"\n");
out.println(str);
in.close();
out.close();
socket.close();
} catch (UnknownHostException ex) {
Logger.getLogger(Simulator.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(Simulator.class.getName()).log(Level.SEVERE, null, ex);
}
}
the server :
private void demarreActionPerformed(java.awt.event.ActionEvent evt) {
sw=new SwingWorker<String,Void> (){
protected String doInBackground() throws Exception {
try {
server = new ServerSocket(Integer.parseInt(port.getText()));
} catch (IOException ex) {
return "already in use";
}
String str1="waiting for connexion";
String str2="Connexion ok";
log.append(str1+"\n");
PrintWriter out=null;
BufferedReader in=null;
Socket socClient=null;
while(ecoute){
try{
socClient = server.accept();
}catch(java.net.SocketException e){
return "[user] Server Stoped";
}
log.append(str2+"\n");
in = new BufferedReader(
new InputStreamReader(socClient.getInputStream())
);
out = new PrintWriter(
new BufferedWriter(
new OutputStreamWriter(socClient.getOutputStream())),
true);
String str = in.readLine();
log.append(str+"\n");
}
return "fatal error";
}
protected void done(){
String m="";
try {
m=get();
} catch (InterruptedException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
} catch (ExecutionException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
log.append(m+"\n");
}
};
sw.execute();
}
Currently my server contains a small error when I send a message it works, but after that all the received messages are null...see :
I think the problem comes from ​​that I did not create a thread after socClient = server.accept(); in server ?
if it's the case what would be best ?:
use SwingWorker in a SwingWorker.
create a classic thread with the Runnable interface.
else what is the solution to overcome this problem ?
Thanks ^^.
You probably shouldn't use a SwingWorker in this case. You should have the background processing thread call SwingUtilities.invokeLater() when it's ready to update the GUI. Typically SwingWorker is for things initiated by GUI events, like clicking a button or menu item so that the GUI will not hang and you can get updates into the GUI over time. The important piece is making sure your GUI updates are done on the EDT, and SwingUtilities.invokeLater() will handle that. As alternatives to a basic Thread/Runnable, take a look at Future, Callable, and Executors too, that might give you some ideas how to structure this. SwingWorker uses them internally.
Indeed, you need to create a thread that loops, and each iteration read from the inputstream, something similar to this:
//
thread = new Thread(this);
thread.start();
public void run() {
while(true){
System.out.println("thread is running");
try {
String temp = in.readUTF();
System.out.println(temp);
chattArea.append(temp);
} catch (IOException e) {
}
}
}
If you don't do this, input will be read only once

Categories

Resources