Basically as stated above. I have 2 AsyncTasks, and Thread.sleep() crashes in one but works in the other when I add it.
here is the task that it works in
public class createConnection extends AsyncTask<Void,Void,Void>{
#Override
protected Void doInBackground(Void... params){
try{
socket = new Socket(ip, port);
PrintWriter out = new PrintWriter(socket.getOutputStream());
InputStream is = socket.getInputStream();
}
catch (UnknownHostException e){
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
The task that makes it crash:
public class SR extends AsyncTask<Void,Void,Void> {
#Override
protected Void doInBackground(Void... params) {
out.write(messageToSend);
out.flush();
msg.setText("message sent!");
try{
Thread.sleep(1000);
msg.setText("before attempt:");
byte[] buffer = new byte[4096];
baos = new ByteArrayOutputStream(4096);
int bytesRead;
while ((bytesRead = is.read(buffer)) != -1){
baos.write(buffer, 0, bytesRead);
}
String response = baos.toString("UTF-8");
msg.setText(response);
}
catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
}
My code consists of one button that creates a TCP connection with a Python server (on a Pi), and a second button which sends and receives text between the two. In the msg textbox, the app displays "message sent!" before it crashes, but does not reach "before attempt", which leads me to think that it is Thread.sleep() crashing the application. Does anyone have any idea why it's crashing or why it's working in one function but not the other?
You can't call msg.setText(...) from inside doInBackground(). That will definitely cause an exception. You can use the progress mechanism of AsyncTask to post progress updates:
public class SR extends AsyncTask<Void,String,Void> { // <- NOTE TYPE CHANGE
#Override
protected Void doInBackground(Void... params) {
out.write(messageToSend);
out.flush();
publishProgress("message sent!");
try{
Thread.sleep(1000);
publishProgress("before attempt:");
byte[] buffer = new byte[4096];
baos = new ByteArrayOutputStream(4096);
int bytesRead;
while ((bytesRead = is.read(buffer)) != -1){
baos.write(buffer, 0, bytesRead);
}
String response = baos.toString("UTF-8");
publishProgress(response);
}
catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
public void onProgressUpdate(String... progress) {
msg.setText(progress[0]);
}
}
Related
I have an AsyncTask which acts as a client and get a string from a server and puts it in a String. After the task I use the response from the server but the data haven't changed yet - it's null.
connectBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
...
Client myClient = new Client(responseTV);
myClient.execute();
if (responseStr.charAt(0) == '1') { <----- responseStr is null
changeBrightness(Integer.parseInt(responseStr.substring(1)));
}
}
});
I assume the code keeps going after .execute() which is not very good in my situation.
Update: Added code for Client class.
public class Client extends AsyncTask<Void, Void, Void> {
String response = "";
TextView responseTV;
public Client(TextView responseTV) {
this.responseTV = responseTV;
}
#Override
protected Void doInBackground(Void... params) {
Socket socket = null;
try {
socket = new Socket(IP, PORT);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(BUFFER_SIZE);
byte[] buffer = new byte[BUFFER_SIZE];
int bytesRead;
InputStream inputStream = socket.getInputStream();
while ((bytesRead = inputStream.read(buffer)) != -1) {
byteArrayOutputStream.write(buffer, 0, bytesRead);
response += byteArrayOutputStream.toString("UTF-8");
}
} catch (UnknownHostException e) {
e.printStackTrace();
response = "UnknownHostException: " + e.toString();
} catch (IOException e) {
e.printStackTrace();
response = "IOException: " + e.toString();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
//Toast.makeText(MainActivity.this, response, Toast.LENGTH_LONG).show();
responseTV.setText(response);
responseStr = response;
super.onPostExecute(aVoid);
}
}
if (responseStr.charAt(0) == '1') { <----- responseStr is null
changeBrightness(Integer.parseInt(responseStr.substring(1)));
}
Use this code in onPostExecute() method of AsyncTask. It runs on the UI thread and is exactly the method you need after finishing work in doInBackground().
I need to update data from server every second. I create handle with AsyncTask, that repeats every second. This works, but about a minute it crushes with EOFException by reading from DataInputStream.
Handler
handler.postDelayed( new Runnable() {
#Override
public void run() {
tickListAdapter = new TickListAdapter(TickActivity.this,tickList);
tickListView.setAdapter(tickListAdapter);
AsyncTCPSend tcpSend= new AsyncTCPSend(address,serverPort, line);
tcpSend.execute();
Log.e(TAG,"update");
handler.postDelayed( this, 1000 );
}
},1000 );
AsyncTask
public class AsyncTCPSend extends AsyncTask<Void, Void, Void> {
String address;
int port;
String message;
String response=null;String lineRead = null;
Socket socket;
int count=1;
OutputStream os;
DataInputStream dis;
AsyncTCPSend(String addr, int p, String mes) {
address = addr;
port = p;
message = mes;
}
#Override
protected Void doInBackground(Void... params) {
socket = null;
try {
socket = new Socket(address, port);
os = socket.getOutputStream();
dis = new DataInputStream(socket.getInputStream());
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
if (!isConnect){
if (connect()){
isConnect = true;
Log.e("CLIENT","now is connected");
getTick();
}
}
return null;
}
public boolean connect(){
try {
Log.e("CLIENT","CONNECTED");
String command = "AUTH_START";
byte[] queryBody = null;
queryBody = command.getBytes("UTF-16LE");
byte[] message = new byte[queryBody.length];
for (int i = 0; i < message.length; ++i)
os.write(message,0,message.length);
Log.e(TAG,"AUTH_START");
String srv = null;
srv = function();
if (srv != null){
if (srv.equals("Error")){
Log.e("CLIENT","Error");
return false;
} else {
String auth_answer = "AUTH_ANSWER";
byte[] authBody = auth_answer.getBytes("UTF-16LE");
Log.e(TAG,"AUTH_ANSWER");
os.write(authBody,0,authBody.length);
srv = function();
if (srv.equals("Error")){
Log.e("CLIENT","Error");
return false;
} else {
Log.e(TAG,"AUTH SUCCESS!!!");
return true;
}
}
} else {
return false;
}
}
catch (UnknownHostException e) {
e.printStackTrace();
return false;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
public String getTick(){
String tick = "TICK";
try {
tickBody = tick.getBytes("UTF-16LE");
os.write(tickBody,0,tickBody.length);
String srv = function();
return srv;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
String function(){
String srv = null;
int len = 0;
try {
len = dis.readInt(); //EOFException is here!!!!
byte[] data = new byte[1024];
if (len > 0) {
dis.read(data, 0, data.length);
}
String out = new String(data,"UTF-16");
if (out.indexOf("Done")>0){
if (out.indexOf("STAT")>0 ||out.indexOf("AST")>0){
srv = out;
}
else {
srv = out.substring(out.indexOf("SRV")+9,out.indexOf("SRV")+41);
}
} else {
srv = "Error";
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return srv;
}
#Override
protected void onPostExecute(Void result) {
Log.e("CLIENT","onPostExecute");
super.onPostExecute(result);
}
}
}
Anybody know why appear EOFException about a minute? How to avoid?
P.S. To obtain the necessary information from the server, I must first pass authentication
Why this exception occurs?
According to Docs
Signals that an end of file or end of stream has been reached unexpectedly during input.
This exception is mainly used by data input streams to signal end of stream. Note that many other input operations return a special value on end of stream rather than throwing an exception.
look upon this answer
The problem was solved by changing the method. I added two threads for output and input inside AsyncTask
The code is supposed to connect as a client to a TCP server, send a command and receive a response.
The code connects and sends the command but time-out-s at "socket.getInputStream()", even though the connected server receives the command and is supposed to respond (was checked using a TCP client program on the PC).
Here Is the Code for the task:
public class MyClientTask extends AsyncTask<Void, Void, Void> {
String dstAddress;
int dstPort;
String command;
String response = "";
MyClientTask(String addr, int port, String cmd){
dstAddress = addr;
dstPort = port;
command = cmd;
}
#Override
protected Void doInBackground(Void... arg0) {
Socket socket = null;
InputStream inputStream;
try {
socket = new Socket();
socket.connect(new InetSocketAddress(dstAddress, dstPort),2000);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(1024);
byte[] buffer = new byte[1024];
int bytesRead;
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);
out.println(command);
inputStream = socket.getInputStream();
socket.setSoTimeout(20000);
while ((bytesRead = inputStream.read(buffer)) != -1){
byteArrayOutputStream.write(buffer, 0, bytesRead);
response += byteArrayOutputStream.toString("UTF-8");
}
}catch (UnknownHostException e){
e.printStackTrace();
response = "UnknownHostException: " + e.toString();
} catch (IOException e) {
e.printStackTrace();
response = "IOException: " + e.toString();
} catch (Throwable e) {
e.printStackTrace();
response = "Throwable: " + e.toString();
}finally{
if(socket != null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
#Override
protected void onPostExecute(Void result) {
textResponse.setText(response);
super.onPostExecute(result);
}
}//MyClientTask
You're reading the response until end of stream. End of stream won't occur until the peer closes the connection. You got a read timeout: ergo, probably, he didn't close the connection. Or else your timeout is too short. Two seconds isn't much.
You need a proper way of reading the response, or of dealing with the parts as they arrive.
I'm making an app that sends a string to a server over a socket and then reads the output after the server has processed that data. It worked perfectly when it was my foreground task, but I have since used AsyncTask to show a process dialog while the socket communication runs in the background, and things start breaking after I read the output from the server and then try to close the socket.
private class Progressor extends AsyncTask<String, Void, Void> {
ProgressDialog dialog;
protected void onPreExecute() {
dialog = ProgressDialog.show(ClearTalkInputActivity.this, "Loading..", "Analyzing Text", true, false);
}
protected Void doInBackground(String... strings) {
String language = strings[0].toLowerCase();
String the_text = strings[1];
Socket socket = null;
DataOutputStream dos = null;
DataInputStream dis = null;
try {
socket = new Socket(my_ip, port);
dos = new DataOutputStream(socket.getOutputStream());
dis = new DataInputStream(socket.getInputStream());
dos.writeUTF(language+"****"+the_text);
String in = "";
while (in.indexOf("</content>") < 0) {
in += dis.readUTF();
}
socket.close();
save_str(OUTPUT_KEY, in);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
if (dos != null) {
try {
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (dis != null) {
try {
dis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
protected void onPostExecute() {
if (dialog.isShowing())
dialog.dismiss();
startActivity(new Intent (output_intent));
}
}
The recommended way in Android is to use one of the two included HttpClients:
Apache HTTP Client
HttpURLConnection
There is no need to use sockets directly. These clients do a lot to improve your experience.
Here is a blog article by the Android developers, that explain the basics: http://android-developers.blogspot.de/2011/09/androids-http-clients.html
I have a BufferedReader, when I try to read it, it just hangs and doesn't do anything, am I doing this right? I am using this in an AsyncTask.
Edit: I have a tablet connected to the Wi-Fi, this connects to my computer which is broadcasting on 172.20.104.203 on port 5334, I can see when the thread starts, but nothing after that.
Here my code:
try {
final BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
final String msg;
msg = (line);
Log.d("DeviceActivity", msg);
}
} catch (Exception e) {
e.printStackTrace();
Log.e("ClientAcivtity: Exception",
String.valueOf(e));
}
EDIT
I have all the right permissions or anything, I was doing this outside a AsyncTask and it worked perfectly, moved it because I didn't want it in the main thread.
-Edit , here is the full code.
public class NetworkTask extends AsyncTask<Void, byte[], Boolean> {
Socket nsocket; // Network Socket
InputStream nis; // Network Input Stream
OutputStream nos; // Network Output Stream
private Handler handler = new Handler();
Boolean connected = false;
public static final int PORT = 5334;
public String SERVERIP = "172.20.104.203";
Socket socket;
#Override
protected void onPreExecute() {
Log.i("AsyncTask", "onPreExecute");
InetAddress serverAddr;
try {
serverAddr = InetAddress.getByName(SERVERIP);
socket = new Socket(serverAddr, PORT);
connected = true;
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.e("ClientAcivtity: Exception", String.valueOf(e));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.e("ClientAcivtity: Exception", String.valueOf(e));
}
}
#Override
protected Boolean doInBackground(Void... params) { // This runs on a
// different thread
boolean result = false;
try {
Log.d("ClientActivity", "C: Connecting...");
if (socket != null) {
int cont = 1;
while (cont == 1) {
try {
Log.d("ClientActivity", "C: Sending command.");
PrintWriter out = new PrintWriter(
new BufferedWriter(new OutputStreamWriter(
socket.getOutputStream())), true);
// where you issue the commands
out.println("getPos");
Log.d("ClientActivity", "C: Sent " + "getPos");
} catch (Exception e) {
Log.e("ClientAcivtity: Exception",
String.valueOf(e));
}
try {
final BufferedReader in = new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
final String msg;
msg = (line);
Log.d("DeviceActivity", msg);
}
} catch (Exception e) {
e.printStackTrace();
Log.e("ClientAcivtity: Exception",
String.valueOf(e));
}
cont--;
}
Log.d("ClientActivity", "C: Closed.");
}
} catch (Exception e) {
Log.e("ClientAcivtity: Exception", String.valueOf(e));
}
return result;
}
#Override
protected void onProgressUpdate(byte[]... values) {
if (values.length > 0) {
Log.i("AsyncTask", "onProgressUpdate: " + values[0].length
+ " bytes received.");
}
}
#Override
protected void onCancelled() {
Log.i("AsyncTask", "Cancelled.");
}
#Override
protected void onPostExecute(Boolean result) {
if (socket != null) {
if (connected) {
if (result) {
Log.i("AsyncTask",
"onPostExecute: Completed with an Error.");
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
Log.i("AsyncTask", "onPostExecute: Completed.");
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}
My guess is that when you write out the command "getPos" the underlying BufferedWriter is not actually sending the data out on the line (you should verify this with tcpdump/wireshark). If this is the case, the server doesn't responsed to the readLine(), since it never got a command. To verify this claim, add out.flush(); after out.println("getPos");
Really, tcpdump will probably give you a better answer then anyone on the forums.
Also see http://developer.android.com/reference/java/io/BufferedWriter.html
Try doing it like this:
final BufferedReader in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
StringBuffer buf = new StringBuffer();
int i;
while((i = in.read()) != -1){
buf.append((char) i);
}
String data = buf.toString();
Reading from sockets is a quite difficult issue depending where the socket is actually connected to and how the other side responds.
If the other side is extremely fast than it can provide the socket with enough data so that the read routines actually work fine. However if there is a delay in the other side of any kind (just needs to be slower than your read routine incl the small default timeout) then your read fails even though there might be data on the other side - just arriving a little too slow at the socket.
Depending on your needs you may wrap your own minimum and maximum timer around the read routine.
Please provide more information and we can better understand the issue.
In many cases it is necessary to have a minimum timeout large enough for the other side to push data to the socket - but you might also need a maximum time for how long you actually want to wait for data to arrive.
UPDATE:
first the runnable to start the monitoring thread. You may use monitoringCanRun in your loop to interrupt the thread if required. And monitoringThreadIsAlive can be used to know if the thread is still running.
monitoringCanRun = true;
new Thread(new Runnable() {
public void run() {
monitoringThreadIsAlive = true;
performMonitoring();
monitoringThreadIsAlive = false;
}
}).start();
}
and performMonitoring looks like:
public void performMonitoring() {
while (monitoringCanRun) {
... do your read in the while loop
...you might like to insert some delay before trying again...
try { //we delay every partial read so we are not too fast for the other side
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}