이전 회에 알아본 내용을 실제로 코드로 구현 해 보자
1. ViewModel에 observer 추가
1) ViewModel의 observer에 publishDiscoverSession, subscribeSession에 대한 observer 를 추가하고
2) btnSendViaSession 을 disable 및 enable 시키는 부분 구현
private fun initViewModel(){
viewModel = ViewModelProvider(this)[MainViewModel::class.java]
.................
viewModel.publishDiscoverySession.observe(this){
var strDisplay = "publishDiscoverySession : "
strDisplay += it?.toString() ?: "null"
bindMain.tvPublishDiscoverySession.text = strDisplay
bindMain.btnConnect.isEnabled = (
viewModel.publishDiscoverySession.value == null
&& viewModel.subscribeDiscoverySession.value == null)
bindMain.btnSendViaSession.isEnabled = (
viewModel.publishDiscoverySession.value != null
|| viewModel.subscribeDiscoverySession.value != null)
}
viewModel.subscribeDiscoverySession.observe(this){
var strDisplay = "subscribeDiscoverySession : "
strDisplay += it?.toString() ?: "null"
bindMain.tvSubscribeDiscoverySession.text = strDisplay
bindMain.btnConnect.isEnabled = (
viewModel.publishDiscoverySession.value == null
&& viewModel.subscribeDiscoverySession.value == null)
bindMain.btnSendViaSession.isEnabled = (
viewModel.publishDiscoverySession.value != null
|| viewModel.subscribeDiscoverySession.value != null)
}
}
2. setWifiAwareSession 구현
이전 회의 내용 그대로 순서대로 구현 하였다
fun setWifiAwareSession(wifiAwareSession: WifiAwareSession?){
Log.i(">>>>", "setting wifiAwareSession")
if(wifiAwareSession == null) Log.i(">>>>", "wifiAwareSession null")
removeCurrentWifiAwareSession()
viewModel.setWifiAwareSession(wifiAwareSession)
if(asServer == null || bindMain.editServiceName.text.isEmpty()) return
if(asServer!!) {
val config: PublishConfig = PublishConfig.Builder()
.setServiceName(bindMain.editServiceName.text!!.toString())
.setTtlSec(0)
.build()
viewModel.wifiAwareSession.value?.publish(config, object : DiscoverySessionCallback() {
override fun onPublishStarted(session: PublishDiscoverySession) {
Log.i(">>>>", "onPublishStarted... $session")
viewModel.setPublishDiscoverySession(session)
}
@RequiresApi(Build.VERSION_CODES.Q)
override fun onMessageReceived(peerHandle: PeerHandle, message: ByteArray) {
viewModel.setPeerHandle(peerHandle)
val receivedMessage = String(message, Charsets.UTF_8)
Log.i(">>>>", "onMessageReceived...$peerHandle, $receivedMessage")
val strDispay = bindMain.tvChattingArea.text.toString() + "\n" + receivedMessage
bindMain.tvChattingArea.text = strDispay
//initServerSocket()
}
override fun onSessionTerminated() {
Log.i(">>>>", "onSessionTerminated")
removeCurrentWifiAwareSession()
Toast.makeText(this@MainActivity, "fail to connect to server", Toast.LENGTH_SHORT).show()
super.onSessionTerminated()
}
override fun onServiceLost(peerHandle: PeerHandle, reason: Int) {
super.onServiceLost(peerHandle, reason)
Log.i(">>>>", "onServiceLost $peerHandle, $reason")
}
}, null)
} else {
val config: SubscribeConfig = SubscribeConfig.Builder()
.setServiceName(bindMain.editServiceName.text!!.toString())
.setTtlSec(0)
.build()
viewModel.wifiAwareSession.value?.subscribe(config, object : DiscoverySessionCallback() {
override fun onSubscribeStarted(session: SubscribeDiscoverySession) {
Log.i(">>>>", "onSubscribeStarted... $session")
viewModel.setSubscribeDiscoverySession(session)
}
override fun onServiceDiscovered(
peerHandle: PeerHandle,
serviceSpecificInfo: ByteArray,
matchFilter: List<ByteArray>
) {
Log.i(">>>>", "onServiceDiscovered... $peerHandle, $serviceSpecificInfo")
val messageToSend = "hello...connected"
viewModel.setPeerHandle(peerHandle)
sendMessageViaSession(messageToSend)
Toast.makeText(this@MainActivity, "Connected to server", Toast.LENGTH_SHORT).show()
}
@RequiresApi(Build.VERSION_CODES.Q)
override fun onMessageReceived(peerHandle: PeerHandle, message: ByteArray) {
viewModel.setPeerHandle(peerHandle)
val receivedMessage = String(message, Charsets.UTF_8)
Log.i(">>>>", "onMessageReceived...$peerHandle, $receivedMessage")
val strDisplay = bindMain.tvChattingArea.text.toString() + "\n" + receivedMessage
bindMain.tvChattingArea.text = strDisplay
//connectToServerSocket()
}
override fun onSessionTerminated() {
removeCurrentWifiAwareSession()
Toast.makeText(this@MainActivity, "fail to connect to server", Toast.LENGTH_SHORT).show()
super.onSessionTerminated()
}
override fun onServiceLost(peerHandle: PeerHandle, reason: Int) {
super.onServiceLost(peerHandle, reason)
Log.i(">>>>", "onServiceLost $peerHandle, $reason")
}
}, null)
}
fun sendMessageViaSession(message : String){
if(asServer!!) {
val strToSend = "server : $message"
viewModel.publishDiscoverySession.value?.sendMessage(
viewModel.peerHandle.value!!,101, strToSend.toByteArray(Charsets.UTF_8))
} else {
val strToSend = "client : $message"
viewModel.subscribeDiscoverySession.value?.sendMessage(
viewModel.peerHandle.value!!,101, strToSend.toByteArray(Charsets.UTF_8))
}
val strDisplay = bindMain.tvChattingArea.text.toString() + "\n" + message
bindMain.tvChattingArea.text = strDisplay
}
3. 실행 결과
두개의 device로 실행 시켜 보았다.
하나는 Galaxy S9으로 이전 글에서 살펴 본 최소한의 사양은 만족하지만, 권장 사양은 만족하지 못하지만 일단 정상적인 작동은 하는 것으로 확인 되었다
4. 전송 버튼 작동 시키기
전송 버튼에 리스너를 달고 message를 서로 보내 보았다
@RequiresApi(Build.VERSION_CODES.S)
fun initUIListener() {
..........
bindMain.btnSendViaSession.setOnClickListener{
if(bindMain.editMessage.text.isEmpty()) return@setOnClickListener
sendMessageViaSession(bindMain.editMessage.text.toString())
bindMain.editMessage.text.clear()
}
}
이제 서로 서로 메시지를 주고 받을 수 있게 되었다
정상 작동 한다
5. Socket을 통한 연결
앞에 살펴 보았던 개발자 페이지 내용을 보면 이 방법은 안정적이지 못하고(데이터의 전달이 안 되는 경우도 있다라고 했다), 256 byte까지의 데이터만 전달 가능하다
따라서 만들어진 Session을 이용한 Socket 연결 방법이 있다고 하여 다음 회에는 그 것을 구현 해 보겠다
'AndroidStudio' 카테고리의 다른 글
Wi-fi Aware를 이용한 채팅 앱 제작 (7) (0) | 2024.03.25 |
---|---|
Wi-fi Aware를 이용한 채팅 앱 제작 (6) (0) | 2024.03.24 |
Wi-fi Aware를 이용한 채팅 앱 제작 (4) (0) | 2024.03.24 |
Wi-fi Aware를 이용한 채팅 앱 제작 (3) (0) | 2024.03.24 |
Wi-fi Aware를 이용한 채팅 앱 제작 (2) (0) | 2024.03.24 |