Android:如何在TCP客户端应用程序中更改IP地址?

时间:2016-09-04 04:11:40

标签: android sockets tcp android-asynctask ip

我正在尝试在C#TCP服务器和Android TCP客户端之间进行通信。我是android的新手所以使用本教程的第二部分来创建android客户端: http://www.myandroidsolutions.com/2012/07/20/android-tcp-connection-tutorial/#.V8uZISgrKUk

一切正常,我可以在手机和计算机之间发送短信,但本教程要求客户端应用程序将服务器IP硬编码到程序中,并且由于显而易见的原因,这将导致问题,如果我其实想制作一个使用它的应用程序。

在本教程之外,我添加了第二个EditText(" @ id / ipTxt")和第二个按钮(" @ id / setIp")

由于我不想让任何人阅读整个教程,以下是总结的重要部分:

主要活动:

public class MyActivity extends Activity
{
    private ListView mList;
    private ArrayList<String> arrayList;
    private MyCustomAdapter mAdapter;
    private TCPClient mTcpClient;

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        arrayList = new ArrayList<String>();

        final EditText editText = (EditText) findViewById(R.id.editText);
        Button send = (Button)findViewById(R.id.send_button);

        //relate the listView from java to the one created in xml
        mList = (ListView)findViewById(R.id.list);
        mAdapter = new MyCustomAdapter(this, arrayList);
        mList.setAdapter(mAdapter);

        // connect to the server
        new connectTask().execute("");

        send.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                String message = editText.getText().toString();

                //add the text in the arrayList
                arrayList.add("c: " + message);

                //sends the message to the server
                if (mTcpClient != null) {
                    mTcpClient.sendMessage(message);
                }

                //refresh the list
                mAdapter.notifyDataSetChanged();
                editText.setText("");
            }
        });

    }

    public class connectTask extends AsyncTask<String,String,TCPClient> {

        @Override
        protected TCPClient doInBackground(String... message) {

            //we create a TCPClient object and
            mTcpClient = new TCPClient(new TCPClient.OnMessageReceived() {
                @Override
                //here the messageReceived method is implemented
                public void messageReceived(String message) {
                    //this method calls the onProgressUpdate
                    publishProgress(message);
                }
            });
            mTcpClient.run();

            return null;
        }

        @Override
        protected void onProgressUpdate(String... values) {
            super.onProgressUpdate(values);

            //in the arrayList we add the messaged received from server
            arrayList.add(values[0]);
            // notify the adapter that the data set has changed. This means that new message received
            // from server was added to the list
            mAdapter.notifyDataSetChanged();
        }
    }
}

TCPClient类:

public class TCPClient {

    private String serverMessage;
    public static final String SERVERIP = "192.168.0.102"; //your computer IP address
    public static final int SERVERPORT = 4444;
    private OnMessageReceived mMessageListener = null;
    private boolean mRun = false;

    PrintWriter out;
    BufferedReader in;

    /**
     *  Constructor of the class. OnMessagedReceived listens for the messages received from server
     */
    public TCPClient(OnMessageReceived listener) {
        mMessageListener = listener;
    }

    /**
     * Sends the message entered by client to the server
     * @param message text entered by client
     */
    public void sendMessage(String message){
        if (out != null && !out.checkError()) {
            out.println(message);
            out.flush();
        }
    }

    public void stopClient(){
        mRun = false;
    }

    public void run() {

        mRun = true;

        try {
            //here you must put your computer's IP address.
            InetAddress serverAddr = InetAddress.getByName(SERVERIP);

            Log.e("TCP Client", "C: Connecting...");

            //create a socket to make the connection with the server
            Socket socket = new Socket(serverAddr, SERVERPORT);

            try {

                //send the message to the server
                out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);

                Log.e("TCP Client", "C: Sent.");

                Log.e("TCP Client", "C: Done.");

                //receive the message which the server sends back
                in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

                //in this while the client listens for the messages sent by the server
                while (mRun) {
                    serverMessage = in.readLine();

                    if (serverMessage != null && mMessageListener != null) {
                        //call the method messageReceived from MyActivity class
                        mMessageListener.messageReceived(serverMessage);
                    }
                    serverMessage = null;

                }

                Log.e("RESPONSE FROM SERVER", "S: Received Message: '" + serverMessage + "'");

            } catch (Exception e) {

                Log.e("TCP", "S: Error", e);

            } finally {
                //the socket must be closed. It is not possible to reconnect to this socket
                // after it is closed, which means a new socket instance has to be created.
                socket.close();
            }

        } catch (Exception e) {

            Log.e("TCP", "C: Error", e);

        }

    }

    //Declare the interface. The method messageReceived(String message) will must be implemented in the MyActivity
    //class at on asynckTask doInBackground
    public interface OnMessageReceived {
        public void messageReceived(String message);
    }
}

我的理论是每次&#34; setIp&#34;停止connectTask进程。单击按钮并创建一个新按钮,但这似乎是一种非常低效的方式,而且我不知道如何做到这一点:(

任何想法?

1 个答案:

答案 0 :(得分:0)

将您的SERVERIPSERVERPORT常量改为非静态变量,然后使用其他输入值将其初始化为TCPClient构造函数,或作为{{1}的输入参数}(然后将其作为输入参数传递给您的AsyncTask.execute()方法)。

在您首次从应用程序的存储配置或UI中的用户确定这些值之前,请不要致电doInBackground()

当您开始新任务时,将对象保存到主代码中的变量(您当前没有这样做)。要取消连接,您可以在该变量上调用execute()方法。请确保您的AsyncTask.cancel()connectTask.doInBackground()代码定期检查TCPClient.run()方法,以便在返回true时尽快退出。 AsyncTask documentation中提到了这种技术。

AsyncTask.isCancelled()对象运行完毕后,您可以创建一个具有不同输入值的新对象。