I'm currently working on a tcp client in Android.
I want to connect my android device to a tcp server on my computer and receive the data once every 2 seconds. The problem is that I'm getting force close on my application because of the while loop that I've implemented in the tcp client.
I've tried writing in different ways the loop that will make the tcp client checking the server socket, but with no success. How can make a loop that will check the server socket without getting the force close?
Here's my code that I'm currently using:
public class Connection implements Runnable {
#Override
public void run() {
try {
sk=new Socket(server,port);
viewsurface.setText("connected");
flag = true;
} catch (UnknownHostException e) {
viewsurface.setText("failed 1 socket");
flag = false;
} catch (IOException e) {
viewsurface.setText("failed 2 socket");
flag = false;
}
while (flag == true){
try {
checkin = sk.getInputStream();
checkint = checkin.available();
if (checkint > 0){
try {
BufferedReader in = new BufferedReader(new InputStreamReader(sk.getInputStream()));
received = in.readLine();
viewsurface.setText(received);
} catch (IOException e) {
viewsurface.setText("failed to receive");
}
}
Thread.sleep(2000);
} catch (IOException e) {
viewsurface.setText("checkin failed");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
You need to paste the exception that you are getting to cause the force close, before anyone can provide decent help.
But some suggestions that might solve the problem.
Most likely to be the problem, viewText.setText can only be called from the UI thread. There's quite a few ways to handle this. You can use AsyncTask or if you have an Activity reference you can use runOnUIThread and pass in a runnable that calls setText.
Move checkin = sk.getInputStream(); to before the loop. There's no reason to get the strem every cycle through the loop.
Do not create the BufferedReader every cycle through the loop. Move it before the loop
.sleep(2000) does not guarantee exactly 2 seconds.
I'm having some code formatting issues so I apologize.
private class DownloadFilesTask extends AsyncTask<Void, String, Void> {
protected Long doInBackground(Void... nothing) {
try {
sk=new Socket(server,port);
publishProgress("connected");
flag = true;
} catch (UnknownHostException e) {
publishProgress("failed 1 socket");
flag = false;
} catch (IOException e) {
publishProgress("failed 2 socket");
flag = false;
}
while (flag == true){
try {
checkin = sk.getInputStream();
checkint = checkin.available();
if (checkint > 0){
try {
BufferedReader in = new BufferedReader(new InputStreamReader(sk.getInputStream()));
received = in.readLine();
publishProgress(received);
} catch (IOException e) {
publishProgress("failed to receive");
}
}
Thread.sleep(2000);
} catch (IOException e) {
updateProgress(
} catch (InterruptedException e) {
e.printStackTrace();
}
return;
}
protected void onProgressUpdate(String... progress) {
viewsurface.setText(progress[0]);
}
protected void onPostExecute(Void result) {
//nothing
}
}
Related
While trying to create a simple Android app that allows me to send a simple string to an IoT device, I used code which initialised a new socket everytime it would send a string. I thought it would be better to have a socket send multiple strings before it would get closed again, but this turned out to be very slow. I am not experienced enough to realise what is going on here.
public class sendString extends AsyncTask<String, String, Socket> {
int brightness;
private int oldbrightness;
void changeBrightness(int newbright){
oldbrightness = brightness;
brightness = newbright;
}
#Override
protected Socket doInBackground(String... strings) {
try {
Socket socket = new Socket(strings[0], 80);
socket.setTcpNoDelay(true);
DataOutputStream DOS = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
while (!isCancelled()) {
if (oldbrightness != brightness) {
DOS.writeUTF("\"sr1\":" + brightness + " ");
DOS.flush();
}
}
socket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
protected void onCancelled(){
return;
}
protected void onProgressUpdate(String... progress){
}
#Override
protected void onPostExecute(Socket socket){
return;
}
}
This is my code which sends multiple strings over one socket. The function is called when a seekbar is clicked, brightness is changed everytime the seekbar moves and cancel(true) is called when the seekbar is released. Is my code wrong or is there a different reason as to why this method would be so slow?
The old code:
public class sendString extends AsyncTask<String, Void, Socket> {
#Override
protected Socket doInBackground(String... strings) {
try {
Socket socket = new Socket(strings[0], 80);
DataOutputStream DOS = new DataOutputStream(socket.getOutputStream());
DOS.writeUTF(strings[1]);
socket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
This would get called everytime the seekbar moved.
The difference is that the first version executes in a CPU-smoking loop sending messages infinitely, while the second version executes exactly once per seek bar move, which should always be quicker.
You are comparing apples and oranges.
You should open the socket outside this method, prior to installing the seekbar listener, and only send one message per invocation.
I've got a problem with my code structure, it works fine but it takes 150-200 ms to process data and it will definitely increase with the size of my database. I was thinking about processing incoming data in a Thread but it could work out. Here is the asynctask:
public class IncomingData extends AsyncTask<Void, Void, String> {
public BufferedReader input;
public String read = null;
public IncomingData() {
}
#Override
public String doInBackground(Void... params) {
try {
input = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
while (input.ready()) {
read = input.readLine();
}
} catch (NullPointerException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
}
return read;
}
#Override
public void onPostExecute(final String input) {
if (input != null) {
InputStreamTokenizer(input);
}
new IncomingData().execute();
}
}
So basicly i'm saying that the function InputStreamTokenizer takes 200+ ms to finish, just after that i can read new incoming lines.
Any idea how could i make a thread or anything of it?
Thanks,
Use executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR) instead execute()
In my app i get weather info from internet in asynctask, but sometimes server is a bit laggy, and i want to make up to 10 requests (if previous was unsuccesful) with 10 second waiting between requests. But when i make my asynctask wait 10 sec.(modeling not responding server), main thread(user interface) freezes until asynctask finishes it's job(make 10 rounds of requests).
here is the code where i make and execute asynctask
WeatherGetter wg = new WeatherGetter();
wg.execute(url);
try {
weather = wg.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
and this is where i make it wait
if (cod != 200) {
synchronized (WeatherGetter.this) {
try {
WeatherGetter.this.wait(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Try this way
do not wait the thread
call same function recursively if code!=200 like this
private void loadWhetherData(final int count) {
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
WeatherGetter wg = new WeatherGetter();
wg.execute(url);
try {
weather = wg.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
if (cod != 200 && count<10) {
loadWhetherData(++count);
}
return null;
}
}.execute();
}
Call
This method will calls 10 times until not suceess
loadWhetherData(1);
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();
}
}
}