채팅 (2) 이벤트 추가하기

김가영·2020년 10월 13일
0

Node.js

목록 보기
15/34
post-thumbnail

socket io 는 JSON 파일과 binary data form으로만 통신이 가능하다.

kotlin 에서 json 만들어주기

  • gradle
dependencies {
  implementation 'com.google.code.gson:gson:2.8.5'
}

val gson.toJson(src : Any!) 를 이용한다

val gson = Gson()

// list, array, string, map 모두 가능
val gson.toJson("hello")

Emitting events

emit("event1", args) : 이벤트를 만들고
on("event1", (args) => {}) : 이벤트를 받는다. 가 기본.

클라이언트에서 이벤트를 보내기

  • 클라이언트
val message = et_message.text.toString()
mSocket.emit("chat message", gson.toJson(Student(
 et_name.text.toString(), message)) )
  • 서버
socket.on('chat message', (item) => {
        data = JSON.parse(item)
        console.log(`${data.name} : ${data.message}`);
    })

또는

  • 클라이언트
val obj = JSONObject()

val message = et_message.text.toString()
mSocket.emit("chat message", gson.toJson(Student(
 et_name.text.toString(), message)) )
  • 서버
socket.on('chat message', (data) => {
        console.log(`${data.name} : ${data.message}`);
})

서버에서 이벤트 보내기

  • 서버
socket.emit('get message', {
	name : data.name,
	message : data.message
});
  • 클라이언트
try{
	val obj = JSONObject(args[0].toString())
	val a = tv1.text.toString()
	Log.d("chat activity", args[0].toString())
}catch(e : Exception){
	e.printStackTrace()
}

example1

이름을 받는 edittext, textview, message를 받는 edittext, message 를 전송하는 button 으로 구성된 간단한 안드로이드 뷰를 만들었다.

안드로이드 코드 전체

package com

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.JsonObject
import com.gyoung.movierecord.R
import io.socket.client.IO
import io.socket.client.Socket
import io.socket.emitter.Emitter
import kotlinx.android.synthetic.main.activity_chat.*
import org.json.JSONObject
import java.lang.Exception
import java.net.URISyntaxException

class ChatActivity : AppCompatActivity() {

    lateinit var mSocket : Socket;

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_chat)

        try{
            mSocket = IO.socket("http://172.30.79.128:5000")
            Log.d("chatActivity socket", "connected")
        }catch(e : URISyntaxException){
            Log.d("chatActivity socket", "failed")
        }


        button2.setOnClickListener {

            val obj = JSONObject()
            obj.put("name", et_name.text.toString())
            obj.put("message", et_message.text.toString())
            mSocket.emit("chat message", obj)

        }

        mSocket.on("get message", setMessage)
        mSocket.connect();
    }

    var setMessage = Emitter.Listener { args ->
        val obj = JSONObject(args[0].toString())
        val a = tv1.text.toString()
        Log.d("chat activity", obj.toString())
        try{
            tv1.text = a + "\n" + obj.get("name") + ": " + obj.get("message")
        }catch(e : Exception){
            e.printStackTrace()
        }
    }
}

서버 코드 전체

const express = require('express');
const app = express();
const port = 5000;
const bodyParser = require('body-parser');
const socketIO = require('socket.io');

app.use(bodyParser.urlencoded({extended : true}));
app.use(bodyParser.json());

const server = app.listen(port, () => console.log('app listening on port ', port));
const io = socketIO.listen(server);

io.on('connection', (socket) => {
    console.log('a user connected');

    socket.on('chat message', (data) => {

        console.log(`${data.name} : ${data.message}`);
        // 다른 유저들에게 보내기
        socket.emit('get message', {
            name : data.name,
            message : data.message
        });
    })

    socket.on('disconnect', () => {
        console.log('user disconnected');
    })
});

error : CalledFromWrongThreadException

ui 는 메인스레드에서만 변경 가능한데, 새로운 스레드에서 textView 의 text를 변경시켜 에러가 발생.
textView 반영은 되는데 굉장히 느리게 반영된다.

runOnUiThread 이용

try{
	tv1.text = a + "\n" + obj.get("name") + ": " + obj.get("message")
}catch(e : Exception){
	e.printStackTrace()
}

부분을

Thread(object : Runnable{
	override fun run() {
    		runOnUiThread(Runnable {
        		kotlin.run {
            		tv1.text = a + "\n" + obj.get("name") + ": " + obj.get("message")
                	}
        	})
        }
}).start()

로 바꿔서 ui Thread 에서 해당 구문을 처리하게 바꿔줬다.

profile
개발블로그

0개의 댓글