Androidチャットルーム

12214 ワード

最近ネットのプログラミングを研究していて、とても面白いと感じて、それから游んでチャットルームを作って游びたいです.このチャットルームはChatRoomと呼ばれ、TCP通信ベースのチャットルームで、いくつかのMaterial Designのコントロールを使っています.これまでプロジェクトを急いでいたので、Material Designを勉強する時間がありませんでした(実は時間がないわけではありません.面倒なことがあるので、遅れています).スタジオの昭兄は私に、あなたの基礎工はしっかりしていないと言っていました.へへ.
TCP紹介
TCPは信頼性が高く、接続しなければ通信できないプロトコルです.
接続しなければ通信できないため、TCP通信はクライアントとサーバ端を厳格に区別し、クライアントがサーバ端に接続してこそ通信を実現することができ、サーバ端はクライアントに接続できず、事前に起動し、クライアントの要求を待つ必要がある.
再送メカニズムを使用して、データ伝送の信頼性を保証します.(送信後、確認メッセージが必要です.そうでなければ再送します)
図面
ChatRoom
さあ、辛さをたくさん話して、ChatRoomがどのように実現したのか見てみましょう.まず効果を見てみましょう.
サーバ側
/**
 * Created by kn on 2016/5/24.
 *
 *         
 */
public class MyServerSocket {

    public static void main(String args[]){
        new ServerListener().start();
    }
}
/**
 * Created by kn on 2016/5/24.
 *
 *        
 */
public class ServerListener extends Thread {

    @Override
    public void run() {
        try {
            //   port:1~65535
            ServerSocket serverSocket = new ServerSocket(30000);
            while(true){
                //          
                Socket socket = serverSocket.accept();
                //    
                System.out.println("          30000  ");
                // socket       
                ChatSocket chatSocket = new ChatSocket(socket);
                chatSocket.start();
                ChatManager.getInstance().add(chatSocket);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
/**
 * Created by kn on 2016/5/24.
 *
 *      
 */
public class ChatSocket extends Thread {

    Socket socket;

    public ChatSocket(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        try {
            BufferedReader br = new BufferedReader(
                    new InputStreamReader(socket.getInputStream(), "UTF-8"));
            String line = null;
            while ((line = br.readLine()) != null) {
                ChatManager.getInstance().publish(this, line);
            }
            br.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
    *           
    * @param message
    */
    public void showMessage(String message) {
        try {
            socket.getOutputStream().write((message + "
").getBytes("UTF-8")); } catch (IOException e) { e.printStackTrace(); } } /** * socket * @return */ public boolean isSocketClosed(){ return socket.isClosed(); } } /** * Created by kn on 2016/5/24. * * */ public class ChatManager { private static ChatManager instance = new ChatManager(); // Vector vector = new Vector<>(); private ChatManager() { } /** * * @return */ public static ChatManager getInstance() { if (instance == null) { synchronized (ChatManager.class) { if (instance == null) { instance = new ChatManager(); } } } return instance; } /** * * * @param chatSocket */ public void add(ChatSocket chatSocket) { vector.add(chatSocket); } /** * * @param chatSocket * @param message */ public void publish(ChatSocket chatSocket, String message) { // for (int i = 0; i < vector.size(); i++) { ChatSocket mChatSocket = vector.get(i); // if (!chatSocket.equals(mChatSocket)) { // if (mChatSocket.isSocketClosed()) { vector.remove(i); } else { mChatSocket.showMessage(message); } } } } }

以上のコードを書き終わると、サーバー側は基本的に完成しましたが、実は今、私たちはチャットルームを游ぶことができます.複数のcmdを開き、telnet localhost 30000を入力するとサーバーに接続でき、黒いボックスの下でチャットできます.
クライアント
メインインタフェース、サーバーのIPとチャットの中で表示する名前を入力します
インタフェースに入る
public class MainActivity extends AppCompatActivity {

    MaterialEditText metName;//     
    MaterialEditText metIP;//    IP
    ImageView ivAvatar;//     
    ButtonFlat btnEnter;//      
    ProgressBar progressBar;//   
    FrameLayout flProgressBar;

    public static Socket socket = null;

    final static int SUCCESS = 0x01;//       
    final static int FAILURE = 0x02;//       
    final static int TIMEOUT = 0x03;//    
    final static int UN_KNOWN_HOST = 0x04;//    
    private BufferedWriter writer;

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

    private void initView() {
        metName = (MaterialEditText) findViewById(R.id.met_name);
        metIP = (MaterialEditText) findViewById(R.id.met_ip);
        ivAvatar = (ImageView) findViewById(R.id.iv_avatar);
        btnEnter = (ButtonFlat) findViewById(R.id.btn_enter);
        progressBar = (ProgressBar) findViewById(R.id.progress);
        flProgressBar = (FrameLayout) findViewById(R.id.fl_progress);

        metName.setText("kntryer");
        metIP.setText("192.168.1.101");

        btnEnter.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                enterChatRoom();
            }
        });
    }

    private void enterChatRoom() {
        //  ip
        final String ipString = metIP.getText().toString().trim();

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    socket = new Socket();
                    socket.connect(new InetSocketAddress(ipString, 30000), 5000);
                    writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
                    handler.sendEmptyMessage(SUCCESS);
                } catch (SocketTimeoutException e) {
                    //      UI      
                    handler.sendEmptyMessage(TIMEOUT);
                    e.printStackTrace();
                } catch (UnknownHostException e) {
                    handler.sendEmptyMessage(UN_KNOWN_HOST);
                    e.printStackTrace();
                } catch (IOException e) {
                    handler.sendEmptyMessage(FAILURE);
                    e.printStackTrace();
                }
            }
        }).start();
    }

    Handler handler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            switch (msg.what) {
                case SUCCESS:
                    String name = metName.getText().toString();
                    try {
                        if (writer != null) {
                            writer.write("system," + name + " enter ChatRoom
"); writer.flush(); } } catch (IOException e) { e.printStackTrace(); } Intent intent = new Intent(MainActivity.this, ChatActivity.class); intent.putExtra("name", name); startActivity(intent); break; case FAILURE: showIsOpenWifi("Please check whether the network is open or not."); break; case TIMEOUT: showIsOpenWifi("SocketTimeoutException"); break; case UN_KNOWN_HOST: showIsOpenWifi("UnknownHostException"); break; } return false; } }); private void showIsOpenWifi(String message) { new SnackBar(this, message, "Yes", new View.OnClickListener() { @Override public void onClick(View v) { // WiFi, } }).show(); } }

チャットインタフェース
/**
 * Created by kn on 2016/5/24.
 */
public class ChatActivity extends AppCompatActivity {

    ButtonFlat btnSent;//    
    MaterialEditText metMsg;//  
    ListView lvMsg;//    

    ArrayList msgList = new ArrayList<>();//    
    MessageAdapter adapter;
    Socket socket;
    String name;//    
    BufferedReader reader;//          
    BufferedWriter writer;//        

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

    private void initView() {

        name = getIntent().getStringExtra("name");
        socket = MainActivity.socket;

        btnSent = (ButtonFlat) findViewById(R.id.btn_sent);
        metMsg = (MaterialEditText) findViewById(R.id.met_msg);
        lvMsg = (ListView) findViewById(R.id.lv_msg);

        adapter = new MessageAdapter(this,msgList);
        lvMsg.setAdapter(adapter);

        //             ,         
        getMessage();

        btnSent.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                ChatMessage chatMessage = new ChatMessage();
                chatMessage.setType(2);
                chatMessage.setName(name);
                chatMessage.setMessage(metMsg.getText().toString());
                msgList.add(chatMessage);
                adapter.notifyDataSetChanged();

                String message = name + "," + metMsg.getText().toString();
                metMsg.setText("");
                setMessage(message);
            }
        });
    }
    /**
     *     
     * @param message
     */
    private void setMessage(String message) {
        try {
            if (writer != null) {
                writer.write(message + "
"); writer.flush(); } else { Toast.makeText(ChatActivity.this, " YY !", Toast.LENGTH_LONG).show(); } } catch (IOException e) { e.printStackTrace(); } } /** * */ private void getMessage() { new Thread(new Runnable() { @Override public void run() { try { writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); String line = null; while ((line = reader.readLine()) != null) { ChatMessage chatMessage = new ChatMessage(); String[] temp = line.split(","); System.out.print(temp[0]); if(temp[0].equals("system")){// temp[0]=system chatMessage.setType(0); chatMessage.setMessage(temp[1]); }else{ chatMessage.setType(1); chatMessage.setName(temp[0]); chatMessage.setMessage(temp[1]); } msgList.add(chatMessage); handler.sendEmptyMessage(0x00); } reader.close(); } catch (IOException e) { e.printStackTrace(); } } }).start(); } Handler handler = new Handler(new Handler.Callback() { @Override public boolean handleMessage(Message msg) { adapter.notifyDataSetChanged(); return false; } }); }

に注意
サーバIPの表示
  cmdを開いて、ipconfigを入力すると、自機のIP設定が見えます.無線LANでwifiに適しています.ここのIPv 4アドレスはサーバーのIPです.
携帯電話がサーバーに接続できない
シミュレータはサーバーに接続できますが、携帯電話が接続できない場合はどうすればいいですか?ネット上では携帯電話は外網だと言っていますが、内網にアクセスできない問題は、携帯電話とパソコンを1つのwifiと一緒にすればいいです.