Java Android TCP/IP和GUI与其他线程通信-Tic Tac Toe多人游戏

Java Android TCP/IP和GUI与其他线程通信-Tic Tac Toe多人游戏,java,android,multithreading,tcp,handler,Java,Android,Multithreading,Tcp,Handler,这就是交易。我想用Android实现多人游戏Tic-Tac-Toe。我使用Java部署了多线程服务器,但在客户端上遇到了麻烦。据我所知,您应该使用后台线程来处理通信,而将UI线程留给UI处理。我在开发游戏循环和线程通信时遇到了一些问题。我决定使用处理程序而不是异步任务 我认为循环应该在后台线程中实现,看起来有点像这样: 使用处理程序从UI获取信息 将数据写入服务器的输出流 从服务器的输入流中读取数据 处理数据 使用其他处理程序将数据发送到UI 我正在使用Eclipse和仿真器作为客户机进行测试。

这就是交易。我想用Android实现多人游戏Tic-Tac-Toe。我使用Java部署了多线程服务器,但在客户端上遇到了麻烦。据我所知,您应该使用后台线程来处理通信,而将UI线程留给UI处理。我在开发游戏循环和线程通信时遇到了一些问题。我决定使用处理程序而不是异步任务

我认为循环应该在后台线程中实现,看起来有点像这样: 使用处理程序从UI获取信息 将数据写入服务器的输出流 从服务器的输入流中读取数据 处理数据 使用其他处理程序将数据发送到UI

我正在使用Eclipse和仿真器作为客户机进行测试。问题是我无法设置处理程序。一个处理程序UIHandler作为参数发送给ClientThread构造函数,而Net处理程序则通过一个方法从客户端线程获取到UIThread

我读到我需要使用活套来处理传入的数据。我不能在一个无休止的循环中调用handleMessage方法吗?我真的不知道如何部署这个。我很乐意接受任何意见

主要活动客户端类:

    package com.example.tictactoecliet;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.StrictMode;
import android.os.StrictMode.ThreadPolicy;
import android.util.Log;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.RadioButton;
import android.widget.TextView;
import android.widget.ViewFlipper;

    public class MainActivity extends Activity implements OnClickListener,
        ClientVocabulary {

    private static final String TAG = MainActivity.class.getSimpleName();
    private Socket client;
    private PrintWriter pw;
    private EditText etIp;
    private TextView tvStatus;
    private Button bCon;
    private Socket socket;
    PrintWriter out;
    private BufferedReader in;
    private RadioButton rbVsPlayer, rbVsAI;
    private ViewFlipper vF;
    private ClientThread cT;
    private ImageButton[][] board = new ImageButton[5][5];
    private Handler h, clientHandler;
    SocketAddress sockaddr;


    /******************************************************************************************/

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);


        setContentView(R.layout.activity_main);
        init();
        setupUIHandler();
        try {

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


    }



    /*****************************************
     * initialize
     * 
     * @return nothing ffs
     ******************************************/

    private void init() {

        etIp = (EditText) findViewById(R.id.etIP);

        tvStatus = (TextView) findViewById(R.id.tvStatus);
        rbVsAI = (RadioButton) findViewById(R.id.rbAI);
        rbVsPlayer = (RadioButton) findViewById(R.id.rb2players);
        bCon = (Button) findViewById(R.id.bCon);

        //
        // // listeners
        //
        vF = (ViewFlipper) findViewById(R.id.vF);
        bCon.setOnClickListener(this);
        board[0][0] = (ImageButton) findViewById(R.id.iB_1A);
        board[0][1] = (ImageButton) findViewById(R.id.iB_2A);
        board[0][2] = (ImageButton) findViewById(R.id.iB_3A);
        board[0][3] = (ImageButton) findViewById(R.id.iB_4A);
        board[0][4] = (ImageButton) findViewById(R.id.iB_5A);

        board[1][0] = (ImageButton) findViewById(R.id.iB_1B);
        board[1][1] = (ImageButton) findViewById(R.id.iB_2B);
        board[1][2] = (ImageButton) findViewById(R.id.iB_3B);
        board[1][3] = (ImageButton) findViewById(R.id.iB_4B);
        board[1][4] = (ImageButton) findViewById(R.id.iB_5B);

        board[2][0] = (ImageButton) findViewById(R.id.iB_1C);
        board[2][1] = (ImageButton) findViewById(R.id.iB_2C);
        board[2][2] = (ImageButton) findViewById(R.id.iB_3C);
        board[2][3] = (ImageButton) findViewById(R.id.iB_4C);
        board[2][4] = (ImageButton) findViewById(R.id.iB_5C);

        board[3][0] = (ImageButton) findViewById(R.id.iB_1D);
        board[3][1] = (ImageButton) findViewById(R.id.iB_2D);
        board[3][2] = (ImageButton) findViewById(R.id.iB_3D);
        board[3][3] = (ImageButton) findViewById(R.id.iB_4D);
        board[3][4] = (ImageButton) findViewById(R.id.iB_5D);

        board[4][0] = (ImageButton) findViewById(R.id.iB_1E);
        board[4][1] = (ImageButton) findViewById(R.id.iB_2E);
        board[4][2] = (ImageButton) findViewById(R.id.iB_3E);
        board[4][3] = (ImageButton) findViewById(R.id.iB_4E);
        board[4][4] = (ImageButton) findViewById(R.id.iB_5E);

        for (int i = 0; i < 5; i++) {
            for (int j = 0; j < 5; j++) {

                board[i][j].setOnClickListener(this);
            }// end of inner for
        }// end of outer for

    }

    @Override
    public void onClick(View v) {

        switch (v.getId()) {

        case (R.id.bCon):
        vF.showNext();
        blockAllTile();
        cT = new ClientThread((short) (rbVsPlayer.isChecked() ? 2:1), clientHandler, etIp.getText().toString());
        cT.start();
            break;
        case (R.id.iB_1A):
            sendLocation(0);
            break;
        case (R.id.iB_2A):
            sendLocation(1);
            break;
        case (R.id.iB_3A):
            sendLocation(2);
            break;
        case (R.id.iB_4A):
            sendLocation(3);
            break;
        case (R.id.iB_5A):
            sendLocation(4);
            break;
        case (R.id.iB_1B):
            sendLocation(5);
            break;
        case (R.id.iB_2B):
            sendLocation(6);
            break;
        case (R.id.iB_3B):
            sendLocation(7);
            break;
        case (R.id.iB_4B):
            sendLocation(8);
            break;
        case (R.id.iB_5B):
            sendLocation(9);
            break;
        case (R.id.iB_1C):
            sendLocation(10);
            break;
        case (R.id.iB_2C):
            sendLocation(11);
            break;
        case (R.id.iB_3C):
            sendLocation(12);
            break;
        case (R.id.iB_4C):
            sendLocation(13);
            break;
        case (R.id.iB_5C):
            sendLocation(14);
            break;
        case (R.id.iB_1D):
            sendLocation(15);
            break;
        case (R.id.iB_2D):
            sendLocation(16);
            break;
        case (R.id.iB_3D):
            sendLocation(17);
            break;
        case (R.id.iB_4D):
            sendLocation(18);
            break;
        case (R.id.iB_5D):
            sendLocation(19);
            break;
        case (R.id.iB_1E):
            sendLocation(20);
            break;
        case (R.id.iB_2E):
            sendLocation(21);
            break;
        case (R.id.iB_3E):
            sendLocation(22);
            break;
        case (R.id.iB_4E):
            sendLocation(23);
            break;
        case (R.id.iB_5E):
            sendLocation(24);
            break;

        }

    }

public void unblockAllTile(){
    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 5; j++) {

            board[i][j].setEnabled(true);
        }// end of inner for
    }// 
}   

public void sendLocation(int location){

}

    public void blockAllTile(){
        for (int i = 0; i < 5; i++) {
            for (int j = 0; j < 5; j++) {

                board[i][j].setEnabled(false);
            }// end of inner for
        }// end of outer for

    }
    private void setupUIHandler(){

        h = new Handler(){

            @Override
            public void handleMessage(Message msg) {
                // TODO Auto-generated method stub
                super.handleMessage(msg);
                Bundle b = msg.getData();
                String content = b.getString("msg");
                if(content.equals(KKIP_ALL_CONNECTED)){
                    tvStatus.setText(KKIP_ALL_CONNECTED);
                }else{
                    Log.i("i no noł", "i no noł");
                }


            }
        };

    }
}

代码尚未完成,因此某些方法可能看起来很奇怪。我对解决UIThread到BackGroundThread到服务器的通信很感兴趣。没有其他内容。

处理程序
对象隐式绑定到创建它们的
线程内运行的
循环器
。您的后台线程需要创建自己的
活套
(或者使用
HandlerThread
为您处理
活套
),然后您的后台线程需要将其
处理程序
传回主UI线程

package com.example.tictactoecliet;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.UnknownHostException;

import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;

public class ClientThread extends Thread implements ClientVocabulary {

    private Socket socket;
    private short game_mode;

    private Handler uiHandler;
    private Handler netHandler;
    private Bundle inMsgBundle, outMsgBundle;
    private final static String TAG = ClientThread.class.getSimpleName();
    private BufferedReader in;
    private String ip, serverResponse;
    PrintWriter out;

    public ClientThread(Short game_mode, Handler h, String ip) {
        this.game_mode = game_mode;
        this.uiHandler = h;
        this.ip = ip;
        inMsgBundle = new Bundle();
        outMsgBundle = new Bundle();

    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        Log.i("Thread started",TAG);
        connectionSetup();
        Log.i("Setup connection",TAG);
        Looper.prepare();
        setupHandler();
        Log.i("Handler set",TAG);
        try {

            play();




        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        Looper.loop();
    }// end of run

    public  Handler getHandlerToMsgQueue() {
        while (netHandler == null) {
            try {
                wait();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return netHandler;
    }

    // //////////////////////////////////////////
    public void connectionSetup() {
        try {
            Log.i("Setup start",TAG);
            InetAddress serverAddress = InetAddress.getByName(ip);
            SocketAddress sockaddr = new InetSocketAddress(serverAddress, 4321);
            // socket = new Socket("192.168.0.102",4321);
            socket = new Socket();
            socket.connect(sockaddr);
            out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
                    socket.getOutputStream())), true);
            out.println(game_mode);

            in = new BufferedReader(new InputStreamReader(
                    socket.getInputStream()));
            Log.i("Setup finish",TAG);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
////////////////
    public void setupHandler(){

        Log.i("Handler ready",TAG);
        netHandler = new Handler(){



            @Override
            public void handleMessage(Message msg) {
                // TODO Auto-generated method stub
                super.handleMessage(msg);
                notifyAll();

            }
        };

        Log.i("Handler done",TAG);
    }
///////////////////////////play//////////////////////////
    public void play() throws Exception{
        String response;
        Log.v("Play start", "Play start");



        try {
            response =null;
            if(in.readLine()!=null){
            response=in.readLine();
            Log.v(response, response);
            }else{
                Log.v(TAG, "Resposne is empty");
            }

            if( response.startsWith(KKIP_WELCOME)){
                Log.i("wow welcome so much", "so much welcome");
                char mark = response.charAt(8);
            }else if (response.startsWith(KKIP_WAITING_FOR_OPPONENT)){


                while (true){


                //updatuj status zegarem, może wait i notify?
             if(response.startsWith(KKIP_ALL_CONNECTED)){



                    Log.v("now we play","play");
                    sendMessageToUI(KKIP_ALL_CONNECTED);
                    response=in.readLine();
                    if(response.startsWith(KKIP_VALID_MOVE)){

                        //update board
                    }else if (response.startsWith(KKIP_MOVED)){
                        int loc = Integer.parseInt(response.substring(15));
                        //update board
                    }else if (response.startsWith(KKIP_VICTORY)){

                    }else if(response.startsWith(KKIP_DEFEAT)){

                    }else if (response.startsWith(KKIP_TIE)){

                    }
                }   

            }//end of while (true)


            //end of if connected 


            }
            out.print(KKIP_QUIT);
            }




         catch (Exception e) {
            // TODO: handle exception
             e.printStackTrace();
        }
        finally{
            socket.close();
        }       

    }
    private void sendMessageToUI(String msg){
        Bundle data = new Bundle();
        data.putString("msg", msg);
        Message m = new Message();
        m.setData(data);
        uiHandler.sendMessage(m);
    }
}