Android - 打开数据套接字,连续写入文本视图(读取数据)

时间:2014-09-22 22:40:25

标签: android sockets tcp client-server

我目前正在处理两个很棒的TCP / IP客户端示例。我的目标是创建一个连接到服务器的简单TCP / IP客户端,并在建立连接后,使用从服务器传递的字符串不断更新TextView。如果用户按下按钮,客户端会向服务器发送停止命令,我最终希望将TextView扩展为包含转换后的字符串值的图形。我能够建立与服务器的连接并从客户端发送停止命令,但到目前为止,我尝试添加读取功能的应用程序一旦启动就崩溃了。

以下是我一直用于指导的示例的链接:

http://android-er.blogspot.com/2014/02/android-sercerclient-example-client.html

http://android-er.blogspot.com/2014/08/bi-directional-communication-between.html

以下是我的MainActivity中的代码:

package com.example.androidclient;

import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.net.UnknownHostException;

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

public class MainActivity extends ActionBarActivity {
    TextView            textResponse;
    TextView            textIn;
    EditText            editTextAddress, editTextPort; 
    Button              buttonConnect, buttonStopTest, buttonDisconnect;
    Socket              socket              = null;
    DataInputStream     incomingString      = null;
    DataOutputStream    terminalLetter      = null;


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

        editTextAddress     = (EditText)findViewById(R.id.address);
        editTextPort        = (EditText)findViewById(R.id.port);
        buttonConnect       = (Button)findViewById(R.id.connect);
        buttonDisconnect    = (Button)findViewById(R.id.disconnect);
        buttonStopTest      = (Button)findViewById(R.id.stop_test);
        textResponse        = (TextView)findViewById(R.id.response);
        textIn              = (TextView)findViewById(R.id.text_in);

        buttonConnect.setOnClickListener(buttonConnectOnClickListener);

        buttonStopTest.setOnClickListener(buttonStopTestOnClickListener);

        buttonDisconnect.setOnClickListener(buttonDisconnectOnClickListener);
    }

    OnClickListener buttonConnectOnClickListener = new OnClickListener(){
        //setOnClickListener sets a callback to be invoked when the button is clicked
        @Override
        public void onClick(View arg0) {
            //Clicking button (Connect) calls a MyClientTask defined below. 
            MyClientTask myClientTask = new     
            MyClientTask(editTextAddress.getText().toString(),   
            Integer.parseInt(editTextPort.getText().toString()));
            myClientTask.execute();
        }
    };

    OnClickListener buttonStopTestOnClickListener = new OnClickListener(){
        //setOnClickListener sets a callback to be invoked when the button is clicked
        @Override
            public void onClick(View arg0) {
                try {
                    terminalLetter = new DataOutputStream(socket.getOutputStream());
                    terminalLetter.writeByte('b');
                    terminalLetter.writeByte('\n');
                    terminalLetter.close();
                    socket.close();
                } 
                catch (IOException e) {
                    System.err.println("Couldn't get I/O for the connection.");
                }
            }
    };

    OnClickListener buttonDisconnectOnClickListener = new OnClickListener(){
        //setOnClickListener sets a callback to be invoked when the button is clicked
        @Override
        public void onClick(View arg0) {
            try {
                socket.close();
            } 
            catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    };


    public class MyClientTask extends AsyncTask<Void, Void, Void> {

        String IPaddress;
        int Port;
        String response = "";

        MyClientTask(String addr, int port){
        IPaddress = addr;
        Port = port;
        }

        @Override
        protected Void doInBackground(Void... arg0) {
        //Took socket declaration from here. 

        try {
            //Taking relevant parameters and applying them to socket
            socket = new Socket(IPaddress, Port);                
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(1024);
            byte[] buffer = new byte[1024];
            int bytesRead;

            InputStream inputStream = socket.getInputStream();

            incomingString = new DataInputStream(socket.getInputStream());
            textIn.setText(incomingString.readUTF());

            /*
             * notice:
             * inputStream.read() will block if no data return
             */
            while ((bytesRead = inputStream.read(buffer)) != -1){
                byteArrayOutputStream.write(buffer, 0, bytesRead);
                response += byteArrayOutputStream.toString("UTF-8");
            }
        } 
        catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            response = "UnknownHostException: " + e.toString();
        } 
        catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            response = "IOException: " + e.toString();
        }
        finally{
            if(socket != null){
                try {
                    socket.close();
                } 
                catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        textResponse.setText(response);
        super.onPostExecute(result);
    }

}

}

我将命令用于从服务器读取数据,并使用设置与套接字连接的代码将其写入TextView。这个想法是在连接建立后它将是下一步但我意识到它看起来我只读了一次。我尝试添加一个while循环并将其从doInBackground中删除。在每种情况下,我得到的只是整个应用程序崩溃在我身上。它在示例中看起来相当直接但是连接是自动的,没有触发,我无法成功修改代码。

我还是Android的新手,这感觉它是应用程序开发的一个重要部分所以我希望社区中的某个人可以帮助我理解与读取数据相关的代码部分(连续)应该放在哪里其余的。

最佳, Yusif Nurizade

P.S。我打算包括片段,但之前的帖子有些人认为没有必要。由于帖子足够长,我选择省略它但可以根据要求分享。

0 个答案:

没有答案