2

私はAndroidとJavaのプログラミングが初めてで、サーバークライアント接続をプログラムしようとしています。

サーバーは PC で問題なく動作し、クライアントは Android スマートフォンで動作します。

電話からサーバーにメッセージを送信できますが、サーバーからクライアントにメッセージを送信できません。

このメッセージを送信すると、クライアントがクラッシュして閉じます。

このサイトで同様のクライアントを見つけ、このクライアントの listView を textView に変更しました。この変更の後、私の問題が発生しました。誰かが私の問題を解決してくれることを心から願っています。

ここに私の活動があります:

import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v4.content.LocalBroadcastManager;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;


public class MyActivity extends Activity {

public static final String MY_LOCAL_BROADCAST = "myLocalBroadCast";
public static final String KEY_RESPONSE = "key_response";
public static final String KEY_FIRSTRUN = "first_run";

Button btn;
EditText textOut;
TextView textIn;
TextView problems;
Button send;
private TCPClient myTcpClient;

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

    editText = (EditText)findViewById(R.id.editText);
    textIn = (TextView)findViewById(R.id.textin);
    send = (Button)findViewById(R.id.send_button);

    new ConnectTask(this.getApplicationContext()).execute("");

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

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

            //sends the message to the server
            if (myTcpClient != null) {
                myTcpClient.sendMessage(message);
            }
        }
    });
    if (savedInstanceState==null) {
        new ConnectTask(this.getApplicationContext()).execute("");
    }
    }

@Override
protected void onSaveInstanceState(Bundle outState) {
    outState.putBoolean(KEY_FIRSTRUN, false);
    super.onSaveInstanceState(outState);
}

    @Override
protected void onResume() {
    super.onResume();
    LocalBroadcastManager.getInstance(this).registerReceiver(
            mMessageReceiver, new IntentFilter(MY_LOCAL_BROADCAST));
}

@Override
protected void onPause() {
    super.onPause();
    LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
}

private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String responseData = intent.getStringExtra(KEY_RESPONSE);
        Toast.makeText(MainActivity.this, responseData, Toast.LENGTH_LONG).show();
    }
};

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


    private Context context;

         public ConnectTask(Context context) {
             this.context = context;
         }

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

        //we create a TCPClient object and
        myTcpClient = new TCPClient(new TCPClient.OnMessageReceived() {

            @Override
            //here the messageReceived method is implemented
            public void messageReceived(String message) {
                //this method calls the onProgressUpdate
                publishProgress(message);
            }
        });
        myTcpClient.run();

        return null;
    }

    @Override
    protected void onProgressUpdate(String... values) {
        super.onProgressUpdate(values);
        Intent intent = new Intent(MainActivity.MY_LOCAL_BROADCAST);
        intent.putExtra(MainActivity.KEY_RESPONSE, values);
        LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
        textIn.setText(values[0]);
    }
}
}

ここに私のTCPClientクラスがあります:

package com.example.sercerclient2zweidreidrei;

import android.util.Log;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;


public class TCPClient {

private String serverMessage;
public static final String SERVERIP = "192.168.2.107"; //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. OnMessageReceived 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 send 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 must be
 * implemented in the MyActivity class at on asynckTask doInBackground
 */
public interface OnMessageReceived {
    public void messageReceived(String message);
}
}

最後に、ここで私の main.xml を見ることができます

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  tools:context=".MyActivity" >

<TextView
    android:id="@+id/textView1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:layout_alignParentTop="true"
    android:text="@string/Textausgabe" />

<EditText
    android:id="@+id/editText"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:layout_below="@+id/textView1"
    android:layout_marginTop="34dp"
    android:ems="10" >

    <requestFocus />
</EditText>

<Button
    android:id="@+id/send_button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignRight="@+id/textView1"
    android:layout_below="@+id/editText"
    android:layout_marginTop="26dp"
    android:text="@string/Senden" />

<TextView
    android:id="@+id/textin"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:layout_centerVertical="true"
    android:text="@string/EinkommenderText"
    android:textAppearance="?android:attr/textAppearanceLarge" />

 </RelativeLayout>

そして私のLogCat:

E/TCP クライアント(548): C: 接続中...

E/TCP クライアント (548): C: 送信されました。

E/TCP クライアント(548): C:完了。

D/AndroidRuntime(548): VM をシャットダウンしています

: W/dalvikvm(548): threadid=1: キャッチされない例外で終了するスレッド (group=0x409c01f8)

E/AndroidRuntime(548): 致命的な例外: メイン

E/AndroidRuntime(548): java.lang.NullPointerException

E/AndroidRuntime(548): com.example.sercerclient2zweidreidrei.MyActivity$connectTask.onProgressUpdate(MyActivity.java:72) で

E/AndroidRuntime(548): com.example.sercerclient2zweidreidrei.MyActivity$connectTask.onProgressUpdate(MyActivity.java:1) で

E/AndroidRuntime(548): android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:618) で

E/AndroidRuntime(548): android.os.Handler.dispatchMessage(Handler.java:99) で

4

2 に答える 2

1

TextViewetc が適切に初期化されていないため、null ポインターが発生しました。

それらをグローバルに宣言しますが、グローバルにリンクされていない新しいローカル変数を初期化します。したがって、グローバル値はまだ null です。

変更MyActivityされます

public class MyActivity extends Activity {

      Button btn;
      EditText textOut;
      TextView textIn;
      TextView problems;
      Button send;
      private TCPClient myTcpClient;

      @Override
      protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main);  
         editText = (EditText) findViewById(R.id.editText);
         textIn = (TextView) findViewById(R.id.textin);
         send = (Button)findViewById(R.id.send_button);

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

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

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

        //sends the message to the server
        if (myTcpClient != null) {
            myTcpClient.sendMessage(message);
        }
    }
  });
}
于 2012-12-30T17:51:04.187 に答える
0

画面の回転の問題を回避するには、アクティビティとAsyncTaskの間にレイジーバウンドを作成する必要があります。たとえば、AsyncTaskは、LocalBroadcastReceiverを介してアクティビティに応答を送信できます。さらに、AsyncTaskの代わりにサービスの使用を検討する必要があります。

LocalBroadcastReceiverのドラフトの例。

AsyncTaskを開始し、LocalBroadcastの結果を(インテントデータとして)トーストに表示するアクティビティ(この例のように、onPause(...)などでこのブロードキャストから登録を解除することを忘れないでください):

public class MainActivity extends Activity {

    public static final String MY_LOCAL_BROADCAST = "myLocalBroadCast";
    public static final String KEY_RESPONSE = "key_response";
    public static final String KEY_FIRSTRUN = "first_run";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if (savedInstanceState!=null && savedInstanceState.getBoolean(KEY_FIRSTRUN,true)) {
          new ConnectTask(this.getApplicationContext()).execute("");
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        outState.putBoolean(KEY_FIRSTRUN, false);
        super.onSaveInstanceState(outState);
    }

    @Override
    protected void onResume() {
        super.onResume();
        LocalBroadcastManager.getInstance(this).registerReceiver(
                mMessageReceiver, new IntentFilter(MY_LOCAL_BROADCAST));
    }

    @Override
    protected void onPause() {
        super.onPause();
        LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
    }

    private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String responseData = intent.getStringExtra(KEY_RESPONSE);
            Toast.makeText(MainActivity.this, responseData, Toast.LENGTH_LONG).show();
        }
    };
}

AsyncTask終了したときにLocalBroadCastを送信するAsyncTaskonProgressUpdate(...)でも同様にLocalBoradcastを送信できます。

public class ConnectTask extends AsyncTask<String, Void, String> {

    private Context context;

    public ConnectTask(Context context) {
        this.context = context;
    }

    @Override
    protected void onPreExecute() {
        //
    }

    @Override
    protected String doInBackground(String... params) {
        //
    }

    @Override
    protected void onPostExecute(String result) {
        Intent intent = new Intent(MainActivity.MY_LOCAL_BROADCAST);
        intent.putExtra(MainActivity.KEY_RESPONSE, result);
        LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
    }
}
于 2012-12-30T20:17:23.387 に答える