Screen updates only once when using multiple socket connections

Asked

Viewed 53 times

2

I’m creating an android application where I trade data with a java socket server on the pc. And in the same application I will open some threads that run servers for a direct connection with android, receiving intermittent data.

The problem is that the server to test I have on android receives only one string and then does not receive more.

This is the test server that listens to connections coming from a java socket client: When the client sends the string for the first time, it appears in the android apk, but apart from the second it updates the ui, even in the java client sends and no exception appears, in the application also does not generate an exception but does not update the ui. Maybe there is a problem in the onPostExecute class, but I am not able to analyze it. It may also be that the connection is still open, I tried close() of the various forms but all gave exception and closed the apk . Someone could analyze the code and see what’s wrong?

package com.example.palioteste;



import android.os.AsyncTask;
import android.widget.TextView;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Arrays;


    public class ServidorSocket extends AsyncTask<String, String, String> {
        private static final int portaServidor = 9879;
        private Socket conexao;
        private BufferedReader br;


        @Override
        protected String doInBackground(String... params) {
            try {
                ServerSocket socket = new ServerSocket(portaServidor);

                //dados enviados para o servidor




                while(true)
                {
                    conexao = socket.accept();

                BufferedReader br = new BufferedReader(new InputStreamReader(conexao.getInputStream()));
                //String retorno =  "Dados Recebidos " + br.readLine(); //retornar ok

                //result = br.readLine();

               return br.readLine();

                }



            }

            catch(IOException e) {
                return e.getMessage();
            }

            finally{
                try {
                    conexao.shutdownInput(); // da certo mas quando tenta denovo a ui nao atualiza
                    //conexao.close(); //da excessão informa que a conexao foi reinciada
//br.close() // da excessao e fecha a aplicacao
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }


            }





        }

        @Override
        protected void onPostExecute(String resultado) {

            MainActivity.textorecebido2.setText("texto" + resultado);  
        }


        }   

Here I have Mainactivity

package com.example.palioteste;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity {

        private Button button;
        private TextView textView1;
        static TextView textorecebido;
        static TextView textorecebido2;



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

       ServidorSocket rodarServidor = new ServidorSocket();
       rodarServidor.execute();

        button = (Button) findViewById(R.id.button);
        textView1 = (TextView)  findViewById(R.id.textView1);
        textorecebido = (TextView) findViewById(R.id.textorecebido);
        textorecebido2 = (TextView) findViewById(R.id.textorecebido2);




        button.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View arg0) {
                textView1.setText("Botao Cliquado");
                abrirSocket rodar = new abrirSocket();
                rodar.execute();
            }

        });
    }



    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }






    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }


}
  • You are using returnin the doInBackground inside an infinite loop. That doesn’t make much sense. What did you want there? Also, you are using static elements in Activity and modifying them through another thread. This is very wrong. You should be passing messages instead. Why did you do it this way?

  • There’s also the issue that you’re swallowing the exceptions. They may be the key to understanding what’s going on. Use the functions of the Log class (Log.d, Log.e etc.) instead of printStackTrace.

  • Pablo thanks for the tips, first it is not necessary to give the Return for the onPostExecute method? I didn’t mean it ("Also, you’re using static elements in Activity and modifying them through another thread. That’s quite wrong. ") the eclipse itself indicates the Static option and compiles the code without error, Is he really wrong because there’s a better way or because it wouldn’t work? I use statics from other threads in the JAVA program and it works normally

  • You are using the Return inside while without any conditional. while does not make sense, if in the first iteration it will already return. About Static, there will be no error now, but try to rotate the phone to see what happens. Android is programmed in Java, but the Android platform is completely different from Java for Desktop. Using visual elements as static variables will virtually ensure that you will have a memory leak if your screen is destroyed, and screen destruction is part of the normal lifecycle of an application-- can happen at any time.

  • What you should do is wear one service to establish this connection and receive this data. This service will warn Activity when new data arrives and Activity reacts by changing the visual element that it has to change. A class should not touch variables directly in the other class like this.

  • I intended about Static in Java Pablo, but why on Android does the eclipse tell me static methods? About while, not intendendo pq se retiro o Return, the method of InBackgroud asks me back, se coloco null, o onPostExecute me returns null, explain to me how I have to do, I’m still beginner and it’s been a few days that this research

  • First of all, drop Eclipse. No one uses Eclipse for Android anymore and it is no longer supported by Google. Download the Android Studio and migrate your project to it. Eclipse is recommending you make the variable static because it allows the Java language to compile your program, but compiling and running are two different things.

  • About while, I believe what you want is for something to run indefinitely and post the read results from the network to Activity so that it can update the screen. The doInBackground has the role of doing a long task and publishing one result in the end. This result is a String, so it asks you to return a String there. If you want something to run indefinitely, what you need is a Service, not an Asynctask.

  • Pablo thanks for the tips. I will research on the service and try to implement. About the use of Asynctask by what I saw on the internet, all the tutorials on socket connection on android said to use it. In sending data to the server works without any kind of error, so I thought the error would be in some component of the code, so Asynctask does not work for server side on android? Because Asynctask also has the onPostUpgrade method

  • The point is that the shipment is only one, so it won’t be a problem at all. But what you want is something that keeps running continuously. Asynctask serves to perform a single long operation and give a result at the end. What you want is something that runs all the time at the same time as the application and publish results multiple times at different times. This.

  • Pablo, my project is an on-board computer that receives sensor values connected to an Arduin. In my intention, to send the values of intermittent sensors I must open a server for each received value on the android side right? For example, sending the value of engine speed and temperature, I will have to have a server for each listening on separate ports not? with that I will have to have a service for each?

  • I believe you can create multiple Asynctasks within the same Service and send a different message to Activity when you finish receiving each message. Since the socket is blocking, you would need several Asynctasks anyway.

  • Let me get this straight. Is this service a thread type or should it be within a thread? If not, I can create the class extending services, and put the Asynctask for each server I open to listen to the connections, so instead of the onPostUpgrade methods responding to the main thread will be the methods of the service class that will respond?

  • The service is not a thread. It is a separate thing. It represents an activity that your application does that is not part of the graphical interface, and should continue if your application is minimized or the screen is turned off. It does not run on a separate thread by default, but it can run on a separate thread if you use an Intentservice. The idea is that you can have a while inside your Service that does Accept() and then pass a message to Activity saying what was read. Then go back to Accept() (as it is a loop).

  • Start there, preferably with one connection at a time and, if you have any questions, search more here on the site or ask a new question.

  • Pablo, I even managed to implement the service, the thread that runs the server works and I have a button that returns the received data, but I was unable to implement a loop method updating a textview with the responses received from the client. I’m programming from a notebook two in one with only 1 GB RAM, and there’s no way to open the emulator or see the log cat, so I always have to install the apk on a smartphone to try the code! If you can help me with that, I’d appreciate it!

Show 11 more comments
No answers

Browser other questions tagged

You are not signed in. Login or sign up in order to post.