-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更新します。何かのようなものUIonPostExecute()

 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のドキュメントがあります

考慮すべきもう1つのことは、変数messageを別の場所で使用しているため、問題が発生する可能性があることです。メンバー変数として定義してから、他のメソッドへのローカル変数として定義しているようです。このように同じ変数名を再利用したくはありません。String message同じで複数回定義しないでくださいActivity

于 2013-03-02T00:34:15.237 に答える