如何在我的Android应用程序中创建全局客户端套接字?

时间:2014-09-15 03:52:50

标签: java android sockets service android-asynctask

亲爱的程序员,您好

我正在尝试使用android制作一个tic tac toe游戏,我的android应用程序包含几个活动,其中一个活动可以允许客户端向服务器发送消息,询问X用户是否想要挑战,如果用户接受服务器给我发出的挑战,我们都前进到另一项活动。

我的服务器在我的电脑上作为常规Java代码运行,这是我的服务器代码:

public class Server {

    ServerSocket serverSocket;
    ArrayList<ServerThread> allClients = new ArrayList<ServerThread>();

    public static void main(String[] args) {
        new Server();

    }

    public Server() {
        // ServerSocket is only opened once !!!

        try {
            serverSocket = new ServerSocket(6000);

            System.out.println("Waiting on port 6000...");
            boolean connected = true;

            // this method will block until a client will call me
            while (connected) {
                Socket singleClient = serverSocket.accept();
                // add to the list
                ServerThread myThread = new ServerThread(singleClient);
                allClients.add(myThread);
                myThread.start();
            }

            // here we also close the main server socket
            serverSocket.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    class ServerThread extends Thread {
        Socket threadSocket;
        String userName;
        boolean isClientConnected;
        InputStream input;
        ObjectInputStream ois;
        OutputStream output;
        ObjectOutputStream oos; // ObjectOutputStream

        public ServerThread(Socket s) {
            threadSocket = s;
        }

        public void sendText(String text) {
            try {
                oos.writeObject(text);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        public void run() {

            try {
                input = threadSocket.getInputStream();
                ois = new ObjectInputStream(input);
                output = threadSocket.getOutputStream();
                oos = new ObjectOutputStream(output);

                userName = (String) ois.readObject();
                isClientConnected = true;
                System.out.println("User " + userName + " has connected");

                while (isClientConnected) {
                    String singleText = (String) ois.readObject();
                    System.out.println(singleText);

                    for (ServerThread t : allClients)
                        t.sendText(singleText);
                    // oos.writeObject(singleText);
                }
                // close all resources (streams and sockets)
                ois.close();
                oos.close();
                threadSocket.close();

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

}    

我只在两个活动中使用客户端之间的通信,两个活动都包含相同的connectUser()代码:

public class MenuActivity extends Activity {

    public static final String HOST = "10.0.2.2";
    public static final int PORT = 6000;

    static ConnectThread clientThread;
    boolean isConnected;

    static boolean isOnline = false;


    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_menu);

        runOnUiThread(new Runnable() {
            public void run() {
                connectUser();

            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
    public void connectUser() {
        clientThread = new ConnectThread();
        clientThread.start();


    }

    class ConnectThread extends Thread {
        InputStream input;
        OutputStream output;
        ObjectOutputStream oos;
        Socket s;

        public void sendText(String text) {
            try {
                oos.writeObject(text);
                System.out.println(text);

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

        public void run() {
            try {
                s = new Socket(HOST, PORT);
                output = s.getOutputStream();
                oos = new ObjectOutputStream(output);
                oos.writeObject(un);

                isOnline = true;
                isConnected = true;

                new ListenThread(s).start();

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

    class ListenThread extends Thread {

        Socket s;
        InputStream input;
        ObjectInputStream ois;

        public ListenThread(Socket s) {
            this.s = s;
            try {
                input = s.getInputStream();
                ois = new ObjectInputStream(input);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }

        public void run() {
            while (isConnected) {
                try {
                    final String inputMessage = (String) ois.readObject();
                //do something with the message                 }
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            }
        }
    }

}

我使用此代码将此代码发送到服务器:

                clientThread.sendText(user + " " + opponent + " play");

问题 是当我在第一个活动创建连接时,然后转到第二个活动我创建另一个连接,这意味着到目前为止我有两个连接,与其他客户端相同,然后服务器似乎返回超时错误。

我的问题 是如何创建一次创建的全局客户端变量,并且可以在每个活动中使用。我看到很多建议,比如套接字服务或asyntask,但我需要更多指导和帮助

提前致谢。

1 个答案:

答案 0 :(得分:0)

在项目中添加一个Application子类并更新应用程序标记,并将此类添加为android:name:

<application
    android:name="com.your.app.MyApplication"
...

然后在MyApplication类中创建对Socket连接的静态引用:

private static Socket connection;

然后添加一个静态方法来访问此对象:

public static Socket getConnection() {
    if( connection == null) {
        // initialize connection object here
    }
    return connection;
}

现在你有了一个全球对象!