-2

我正在尝试在服务器和客户端之间建立一个聊天应用程序,但是由于这行代码,该应用程序无法运行: message = (String) input.readObject(); 因为起初, inputStream 是 null !任何人都可以帮忙吗?这是我的代码

package com.example.test;

import java.io.BufferedReader;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OptionalDataException;
import java.net.Socket;


import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.os.StrictMode;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends Activity {

    private Button send;
    private Button connect;
    private EditText userText;
    private TextView chatWindow;

    private String serverIP;
    private ObjectOutputStream output;
    private ObjectInputStream input;
    private String message = "";
    private Socket connection;

    @SuppressLint({ "NewApi", "NewApi", "NewApi" })
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (android.os.Build.VERSION.SDK_INT > 9) {
            StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
            StrictMode.setThreadPolicy(policy);
          }

        serverIP = "192.168.1.4";
        //userText.setEnabled(false);
        send = (Button)findViewById(R.id.button1);
        connect = (Button)findViewById(R.id.button2);
        chatWindow =(TextView)findViewById(R.id.textView1); 
        userText = (EditText)findViewById(R.id.editText1); 
        userText.setHint("Enter your message here");

        connect.setOnClickListener(new View.OnClickListener() {

            public void onClick(View v) {


                //connect to the server
                try{
                    connectToServer();
                    setupStreams();

                }catch(EOFException eofException){
                    showMessage("\n client terminated the connection");
                }catch(IOException ioException){
                    ioException.printStackTrace();
                }
            }
        });

        send.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                String message = userText.getText().toString();
                sendMessage(message);
                userText.setText("");   

            }
        });

        while(true){
            try{
                message = (String) input.readObject(); 
                showMessage("\n" + message + " NULL ");
                chatWindow.refreshDrawableState(); 
            }catch(ClassNotFoundException classNotFoundException){
                showMessage("\n I don't know that object type");
            }
            catch(NullPointerException e){
                e.printStackTrace();
            }
            catch (OptionalDataException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

    } // end of onCreate


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }


    //connect to the server
        private void connectToServer() throws IOException {
            showMessage("Attempting connection... \n");
            connection = new Socket( "192.168.1.4", 6789);
            showMessage("Connected to " + connection.getInetAddress().getHostName() );
        }

        //setup streams to send and receive messages
        private void setupStreams() throws IOException{
            output = new ObjectOutputStream(connection.getOutputStream());
            output.flush();
            input = new ObjectInputStream(connection.getInputStream());
            showMessage("\n Your streams are now good to go! \n ");
        }

        //whileChatting with server
        private void whileChatting() throws IOException{

                try{
                    message = (String) input.readObject(); 
                    showMessage("\n" + message + " NULL ");
                    chatWindow.refreshDrawableState(); 
                }catch(ClassNotFoundException classNotFoundException){
                    showMessage("\n I don't know that object type");
                }

        }

        //close the streams and sockets
        private void closeCrap(){
            showMessage("\n closing crap down");
            ableToType(false);
            try{
                output.close();
                input.close();
                connection.close();
            }catch(IOException ioException){
                ioException.printStackTrace();
            }
        }

        // gives user permission to type into the text box
        private void ableToType(final boolean tof){
            userText.setEnabled(tof);
        }

        // send messages to server
        private void sendMessage(String message){
            try{
                output.writeObject("CLIENT - " + message);
                output.flush();
                showMessage("\nCLIENT - " + message);
            }catch(IOException ioException){
                chatWindow.append("\n somethine messed up sending message!");
            }
        }

        //change/update chatWindow
        private void showMessage(final String m){
            chatWindow.append(m);
            chatWindow.refreshDrawableState();
        }

} // end of class MainActivity
4

2 回答 2

2

您的代码绝对没有遵循任何好的 UI 准则:您正在主 (UI) 线程上进行网络操作,并且onCreate(). 如果没有任何崩溃,Android 实际上应该提供强制关闭您的应用程序。现在,您面临的问题的可能原因是:null

setupStreams()仅在单击按钮时调用。但是,您的while (true)循环位于onCreate(). 这意味着一旦创建并设置了点击侦听器,循环就会运行,尝试从中读取input并失败,因为setupStreams()尚未调用。

所以请不要取消 StrictMode - 它可以帮助您,从事件驱动的角度来看您的代码(“一旦 X 发生,然后执行 Y”)。并且还摆脱了主(UI)线程中的循环。循环对于控制台窗口来说很好,但是对于 UI(它们有自己复杂的生命周期),你不能在不冻结很多东西的情况下做到这一点。

于 2013-03-02T00:45:53.437 回答
1

在 中执行所有网络任务doInBackground()AsyncTask然后在 中更新您的UI变量onPostExecute()。就像是

 public class TalkToServer extends AsyncTask<String, String, String> {
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

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

    }

    @Override
    protected String doInBackground(String... params) {
    //do your work here
        return something;
    }

    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);
           // do something with data here-display it or send to mainactivity
}

这是关于AsyncTask的文档

要考虑的另一件事是您message在不同的地方使用该变量,这可能会给您带来问题。看起来您已将其定义为成员变量,然后将其定义为其他方法的局部变量。您不想以这种方式重复使用相同的变量名。不要String message在同一个中定义多次Activity

于 2013-03-02T00:34:15.237 回答