Страницы

Поиск по вопросам

суббота, 30 ноября 2019 г.

И снова сокеты в java android

#java #android #сокет


Я хотел бы спросить про сокеты в Android. Я перерыл половину интернета и не нашел
того, что мне нужно.

Задача написать клиент под Android на Java, который бы отправлял и получал сообщения.
Когда писал на компьютер, все было чудесно, тут же столкнулся с проблемой многопоточности
(нельзя вызывать сетевые задачи из главного потока). Я более менее разобрался, заставил
отправлять сообщения на сервер, но никак не получается сделать, чтобы TextView сам
принимал и обновлял историю диалога.

Вот код клиента, сервер даже переписал как простой эхо сервер, отсылает обратно то,
что отправил клиент. Ниже код клиента, помогите с реализацией приема сообщений от сервера.  

import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

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

public class MainActivity extends AppCompatActivity {

    private Socket socket;
    private Button SendBut;
    private EditText editText;
    private TextView textView;
    private PrintWriter os;
    private BufferedReader is;
    networking net;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        SendBut = (Button) findViewById(R.id.SendBut);
        editText = (EditText) findViewById(R.id.editText);
        textView = (TextView) findViewById(R.id.TxtFrSrv);
        net = new networking();
        net.execute();
    }

    public void onClck(View view) {
        String txt = null;
        txt = editText.getText().toString();
        os.println(txt);
    }


    public class networking extends AsyncTask < String, Void, Void > {
        @Override
        protected Void doInBackground(String...params) {
            try {
                socket = new Socket("10.0.2.2", 4444);
                os = new PrintWriter(new PrintWriter(new OutputStreamWriter(socket.getOutputStream())),
true);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
    }
}


Пытался изобразить что то похожее на это, но с нулевым значение запустить не получается...

public class getMsg extends Thread{
    public void run(){
        try {
            is=new BufferedReader(new InputStreamReader(socket.getInputStream()));
            final String finc;
            finc=is.readLine();
            while (!finc.equals("break")){
                MainActivity.this.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        textView.setText(finc);
                    }
                });
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

    


Ответы

Ответ 1



Use retrofit Luke! Retrofit+rxJava+retrolambda Допустим ответ от сервера такой {"text":"текст сообщения"} Как обрабатываем public class Message{ @SerializedName("text") public String message; } public interface RequestApi { String BASE_URL = "http://server/"; RequestApi api = new Retrofit.Builder() .baseUrl(RequestApi.BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .subscribeOn(AndroidSchedulers.mainThread() .build() .create(RequestApi.class); @GET("?method=getMsg") Observable getMessage(); } public class MainActivity extends Activity{ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); SendBut = (Button) findViewById(R.id.SendBut); editText = (EditText) findViewById(R.id.editText); textView = (TextView) findViewById(R.id.TxtFrSrv); RequestApi.api.getMessage().subscribe(m->textView.setText(m.message)); } }

Ответ 2



Вот решение вашей задачи private class Networking extends AsyncTask { @Override protected String doInBackground(String... params) { try { Socket socket = new Socket("10.0.2.2", 4444); PrintWriter writer = new PrintWriter(new PrintWriter(new OutputStreamWriter(socket.getOutputStream())), true); writer.write(params[0]); writer.flush(); BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); StringBuilder result = new StringBuilder(); String line; while ( (line = reader.readLine()) != null) { result.append(line); } return result.toString(); } catch (IOException e) { e.printStackTrace(); } return null; } @Override protected void onPostExecute(String s) { textView.setText(s); } } И вызывать AsyncTask необходимо из метода onClick() new Networking().execute(text);

Ответ 3



public void GetMsg(){ new Thread(new Runnable() { @Override public void run() { try { socket=new Socket(Host,4444); } catch (IOException e) { e.printStackTrace(); } try{ is = new BufferedReader(new InputStreamReader(socket.getInputStream())); } catch (IOException e) { e.printStackTrace(); } while (true){ String msg = null; try { msg=is.readLine(); } catch (IOException e) { e.printStackTrace(); } if (msg==null){ break; } else { displayMsg(msg); } } } }).start(); } public void displayMsg(String msg){ final String msg1 = msg; handler.post(new Runnable() { @Override public void run() { appendTextAndScroll(msg1); } }); } Всем большое спасибо за помощь, я немного переделал клиент и решил данную проблему вот таким кодом, надеюсь кому-нибудь это будет полезно. Метод GetMsg вызываю в onCreate().

Ответ 4



А почему ты хочешь, чтобы это делал TextView? Как ты себе это представляешь? TextView - это всего лишь объект лейаута. Если ты создаешь какой-то writer, os = new PrintWriter(new PrintWriter(new OutputStreamWriter(socket.getOutputStream())), true); то очевидно ты хочешь чтобы он тебе писал в исходящий поток- getOutputStream(). Если тебе нужно получать информацию, то скорее всего тебе нужен reader, который тебе ее читать будет из входящего потока - getInputStream().

Ответ 5



Я бы сделал цикл с ожиданием Thread.sleep(400) и проверял, пришло ли сообщение, если сообщение !=null, то publishProgress(message) и в onProgressUpdate (! Точно не помню как называется метод, его нужно переопределить в AsyncTask) в ссылку на TextView, которую нужно заранее инициализировать, забивал текст. Если я правильно понял суть задачи

Комментариев нет:

Отправить комментарий