12/08/2018, 13:23

Xây dựng ứng dụng ChatApp partII

Server NodeJS Đầu tiên chúng ta xây dựng server bằng cách tạo file server_chat.js như sau //server_chat.js // Setup basic express server var express = require ( 'express' ) ; var app = express ( ) ; var server = require ( 'http' ) . createServer ( app ) ; var ...

Server NodeJS

Đầu tiên chúng ta xây dựng server bằng cách tạo file server_chat.js như sau

//server_chat.js

// Setup basic express server
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io')(server);

var port = process.env.PORT || 3000;

server.listen(port, function () {
  console.log('Server listening at port %d', port);
});

// Routing
app.use(express.static(__dirname + '/public'));

// Chatroom

var numUsers = 0;

io.on('connection', function (socket) {
  var addedUser = false;

  // when the client emits 'new message', this listens and executes
  socket.on('new message', function (data) {
    // we tell the client to execute 'new message'
    socket.broadcast.emit('new message', {
      username: socket.username,
      message: data
    });
  });

  // when the client emits 'add user', this listens and executes
  socket.on('add user', function (username) {
    if (addedUser) return;

    // we store the username in the socket session for this client
    socket.username = username;
    ++numUsers;
    addedUser = true;
    socket.emit('login', {
      numUsers: numUsers
    });
    // echo globally (all clients) that a person has connected
    socket.broadcast.emit('user joined', {
      username: socket.username,
      numUsers: numUsers
    });
  });

  // when the client emits 'typing', we broadcast it to others
  socket.on('typing', function () {
    socket.broadcast.emit('typing', {
      username: socket.username
    });
  });

  // when the client emits 'stop typing', we broadcast it to others
  socket.on('stop typing', function () {
    socket.broadcast.emit('stop typing', {
      username: socket.username
    });
  });

  // when the user disconnects.. perform this
  socket.on('disconnect', function () {
    if (addedUser) {
      --numUsers;

      // echo globally that this client has left
      socket.broadcast.emit('user left', {
        username: socket.username,
        numUsers: numUsers
      });
    }
  });
});

Ở đây chúng ta có hàm nhận tin nhắn từ người dùng xong gửi cho tất cả người đang online

    socket.on('new message', function (data) {
    // we tell the client to execute 'new message'
    socket.broadcast.emit('new message', {
      username: socket.username,
      message: data
    });
    });

Một hàm để thêm người mới vào server, tính toán số người đang online, gửi cho người này số người trong server và thông báo cho tất cả người khác sự xuất hiện của người mới.

 socket.on('add user', function (username) {
    if (addedUser) return;

    // we store the username in the socket session for this client
    socket.username = username;
    ++numUsers;
    addedUser = true;
    socket.emit('login', {
      numUsers: numUsers
    });
    // echo globally (all clients) that a person has connected
    socket.broadcast.emit('user joined', {
      username: socket.username,
      numUsers: numUsers
    });
  });

Một hàm xử lí khi user thoát ra.

 socket.on('disconnect', function () {
    if (addedUser) {
      --numUsers;

      // echo globally that this client has left
      socket.broadcast.emit('user left', {
        username: socket.username,
        numUsers: numUsers
      });
    }
  });

Ok, vậy là xong phần server rồi, để chạy nó, bạn dùng

 node server_chat.js

Bây giờ chúng ta xây dựng client nhé.

Xây dựng Client Android.

  1. Đầu tiên, bạn chọn New -> Project để tạo một project mới tên là Android Chat.

  2. Bây giờ ta sẽ thêm thư viện cho ứng dụng tại build.gradle như sau.

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:23.1.1'
    compile 'com.android.support:recyclerview-v7:21.0.+'
    compile ('io.socket:socket.io-client:0.7.0') {
        exclude group: 'org.json', module: 'json'
    }
}

Ta thêm thư viện recyclerview để hiện thị list tin nhắn và socketio để liên kết với server nodejs.

  1. Chúng ta định nghĩa color và string cho ứng dụng này như sau. Thêm vào file strings.xml tại res/values như sau.
//strings.xml

    <resources>
        <string name="app_name">Android Chat</string>
        <string name="action_settings">Settings</string>
        <string name="action_leave">Leave</string>
        <string name="action_send">Send</string>
        <string name="prompt_message">Message</string>

        <string name="error_connect">Failed to connect</string>

        <!-- messages -->
        <string name="message_welcome">Welcome to Socket.IO Chat –</string>
        <plurals name="message_participants">
            <item quantity="one">there's %d participant</item>
            <item quantity="other">there are %d participants</item>
        </plurals>
        <string name="message_user_joined">%s joined</string>
        <string name="message_user_left">%s left</string>
        <string name="user_action_typing">is typing</string>
        <string name="title_activity_login">Join</string>

        <!-- Strings related to login -->
        <string name="prompt_username">What's your nickname?</string>
        <string name="action_sign_in">Join</string>
        <string name="action_sign_in_short">Join</string>

        <string name="error_field_required">This field is required</string>

        <dimen name="spacing">8dp</dimen>

    </resources>

Thêm file colors.xml tại res/values.

   //colors.xml

    <?xml version="1.0" encoding="utf-8"?>
    <resources>

        <color name="username0">#e21400</color>
        <color name="username1">#91580f</color>
        <color name="username2">#f8a700</color>
        <color name="username3">#f78b00</color>
        <color name="username4">#58dc00</color>
        <color name="username5">#287b00</color>
        <color name="username6">#a8f07a</color>
        <color name="username7">#4ae8c4</color>
        <color name="username8">#3b88eb</color>
        <color name="username9">#3824aa</color>
        <color name="username10">#a700ff</color>
        <color name="username11">#d300e7</color>

    </resources>

Thêm file arrays.xml tại res/values.

    //arrays.xml

    <?xml version="1.0" encoding="utf-8"?>
    <resources>

        <array name="username_colors">
            <item>@color/username0</item>
            <item>@color/username1</item>
            <item>@color/username2</item>
            <item>@color/username3</item>
            <item>@color/username4</item>
            <item>@color/username5</item>
            <item>@color/username6</item>
            <item>@color/username7</item>
            <item>@color/username8</item>
            <item>@color/username9</item>
            <item>@color/username10</item>
            <item>@color/username11</item>
        </array>

    </resources>

Sửa file menu_main.xml tại res/values như sau.

    // menu_main.xml

    <menu xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        tools:context=".MainActivity">
        <item android:id="@+id/action_leave"
            android:title="@string/action_leave"
            android:orderInCategory="100"
            app:showAsAction="never"/>
    </menu>
  1. Tạo file Constants.java như sau.
    //Constants.java

    package com.ln.androidchat;

    public class Constants {
        public static final String CHAT_SERVER_URL = "http://192.168.1.6:3000";
    }

Đây là đường dẫn để truy cập vào server nodejs, bạn phải thay bằng địa chỉ ip của máy bạn nhé.

  1. Tạo file ChatApplication.java như sau.
    // ChatApplication.java

    package com.ln.androidchat;

    import android.app.Application;

    import java.net.URISyntaxException;

    import io.socket.client.IO;
    import io.socket.client.Socket;

    public class ChatApplication extends Application {

        private Socket mSocket;
        {
            try {
                mSocket = IO.socket(Constants.CHAT_SERVER_URL);
            } catch (URISyntaxException e) {
                throw new RuntimeException(e);
            }
        }

        public Socket getSocket() {
            return mSocket;
        }
    }

File này có chức năng đăng kí socket với server, ta dùng application để có thể sử dụng chức năng này trong toàn ứng dụng

  1. OK, bây giờ ta sẽ tạo hết các file xml layout một lượt nhé, vào res/layout tạo file item_action.xml như sau.
    // item_action.xml

    <LinearLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_awidth="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:gravity="center_vertical"
            android:paddingTop="@dimen/spacing">

        <TextView
                android:id="@+id/username"
                style="?android:textAppearanceMedium"
                android:textColor="?android:textColorPrimary"
                android:layout_awidth="wrap_content"
                android:layout_height="wrap_content"
                android:singleLine="true"
                android:textStyle="bold"/>
        <TextView
                android:id="@+id/action"
                style="?android:textAppearanceMedium"
                android:textColor="?android:textColorSecondary"
                android:text="@string/user_action_typing"
                android:layout_awidth="wrap_content"
                android:layout_height="wrap_content"
                android:paddingLeft="@dimen/spacing"
                android:paddingRight="@dimen/spacing"
                android:singleLine="true"/>

    </LinearLayout>

Layout này để hiển thị user đang gõ tin nhắn.

Tạo file item_log.xml như sau

    // item_log.xml

    <LinearLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_awidth="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:paddingTop="@dimen/spacing">

        <TextView
                android:id="@+id/message"
                style="?android:textAppearanceSmall"
                android:textColor="?android:textColorSecondary"
                android:layout_awidth="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center"/>

    </LinearLayout>

Layout này hiển thị số người đang online và 1 số tin nhắn khác.

Tạo file item_message.xml như sau.

     // item_message.xml
    <LinearLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_awidth="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:paddingTop="@dimen/spacing">

        <TextView
                android:id="@+id/username"
                style="?android:textAppearanceMedium"
                android:textColor="?android:textColorPrimary"
                android:layout_awidth="wrap_content"
                android:layout_height="wrap_content"
                android:singleLine="true"
                android:textStyle="bold"/>
        <TextView
                android:id="@+id/message"
                style="?android:textAppearanceMedium"
                android:textColor="?android:textColorPrimary"
                android:layout_awidth="wrap_content"
                android:layout_height="wrap_content"
                android:paddingLeft="@dimen/spacing"
                android:paddingRight="@dimen/spacing"
                android:singleLine="true"/>

    </LinearLayout>

Layout này hiển thị user và tin nhắn của họ.

Tạo file fragment_main.xml như sau.

    // fragment_main.xml

    <LinearLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            android:layout_awidth="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            tools:context=".MainFragment">

        <android.support.v7.widget.RecyclerView
                android:id="@+id/messages"
                android:layout_awidth="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1"
                android:paddingLeft="@dimen/activity_horizontal_margin"
                android:paddingRight="@dimen/activity_horizontal_margin"
                android:scrollbars="vertical"
                android:scrollbarStyle="outsideOverlay"/>
        <LinearLayout
                android:layout_awidth="match_parent"
                android:layout_height="wrap_content"
                android:paddingLeft="@dimen/activity_horizontal_margin"
                android:paddingRight="@dimen/activity_horizontal_margin"
                android:orientation="horizontal"
                android:gravity="center_vertical">

            <EditText
                    android:id="@+id/message_input"
                    android:layout_awidth="0dp"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:hint="@string/prompt_message"
                    android:imeActionId="@+id/send"
                    android:imeActionLabel="@string/action_send"
                    android:imeOptions="actionSend"
                    android:inputType="text"
                    android:maxLines="1"
                    android:singleLine="true"/>
            <ImageButton
                    android:id="@+id/send_button"
                    android:layout_awidth="wrap_content"
                    android:layout_height="wrap_content"
                    android:src="@android:drawable/ic_menu_send"
                    android:contentDescription="@string/action_send"/>

        </LinearLayout>

    </LinearLayout>

Layout này hiển thị list tin nhắn và ô tin nhắn để user nhập và gửi.

Tạo file activity_login.xml như sau

    // activity_login.xml

    <ScrollView
            xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            android:layout_awidth="match_parent"
            android:layout_height="match_parent"
            android:paddingBottom="@dimen/activity_vertical_margin"
            android:paddingLeft="@dimen/activity_horizontal_margin"
            android:paddingRight="@dimen/activity_horizontal_margin"
            android:paddingTop="@dimen/activity_vertical_margin"
           >

        <LinearLayout
                android:layout_awidth="match_parent"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:orientation="vertical">

            <EditText
                    android:id="@+id/username_input"
                    android:layout_awidth="match_parent"
                    android:layout_height="wrap_content"
                    android:hint="@string/prompt_username"
                    android:imeActionId="@+id/login"
                    android:imeActionLabel="@string/action_sign_in_short"
                    android:imeOptions="actionUnspecified"
                    android:inputType="textPersonName"
                    android:maxLength="14"
                    android:maxLines="1"
                    android:singleLine="true"/>
            <Button
                    android:id="@+id/sign_in_button"
                    style="?android:textAppearanceSmall"
                    android:layout_awidth="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="16dp"
                    android:text="@string/action_sign_in"
                    android:textStyle="bold"/>

        </LinearLayout>
    </ScrollView>

Layout này để user đăng nhập tên vào server

  1. Hơi nhiều thứ cần làm nhỉ             </div>
            
            <div class=
0