override fun onCreate() {
debug("call onCreate >>>")
val server = ServerKotlin()
thread = Thread(server)
thread.start()
}
When creating the service, need to create a thread to run the server.
internal inner class ServerKotlin : Runnable {
override fun run() {
running = true
debug("S: Connecting...")
/* Create new UDP-Socket */
socket = DatagramSocket(SERVERPORT) //50001 port로 UDP 서버를 실행 // , serverAddr
socket!!.soTimeout = 1000
socket!!.broadcast = true
// 데이터 사이즈를 넉넉하게 세팅
val buf = ByteArray(1500)
while (running) { // client 요청을 기다려야해서 while문 사용
/* Prepare a UDP-Packet that can
* contain the data we want to receive */
var packet = DatagramPacket(buf, buf.size)
debug("S: Receiving...")
/* Receive the UDP-Packet */
try {
socket!!.receive(packet)
} catch (e: java.lang.Exception) {
debug("UDP S: Error >>> $e")
continue
}
clientAddr = packet.address // client address
clientPort = packet.port // client port
debug("clientAddr: $clientAddr")
debug("clientPort: $clientPort")
packet = DatagramPacket(buf, buf.size, clientAddr, clientPort)
// 받은 패킷을 이용해서 데이터를 받는다
val received = String(packet.data, 0, packet.length).trim { it <= ' ' }
debug("UDP S: Received received >>>>>>>>>> $received")
// thread pause, interrupt() to make terminate
try {
Thread.sleep(1000)
} catch (e: Exception) {}
}
// Log.d("UDP", "S: Socket Close.")
debug("UDP clientAddr.toString() >>. ${clientAddr.toString()}")
}
}
override fun onDestroy() {
debug("call onDestroy >>>")
releaseUDPSocket() // 소켓 자원해제 함수
if (!thread.isInterrupted)
// 서비스가 종료되도 쓰레드가 계속 실행될 수 있으므로 쓰레드를 종료 시키게 한다.
thread.interrupt()
super.onDestroy()
}
Processing when the service is terminated.
/**
* UDP socket resource release function
*/
private fun releaseUDPSocket() {
running = false
socket?.broadcast = false
socket?.close()
try {
socket?.soTimeout = 1;
} catch (e: SocketException) {
}
socket?.disconnect()
socket = null
}
socket?.soTimeout = 1 to trigger a SocketException and release the resources.class UDPService : Service() {
// udp server
private var running = true
private var socket: DatagramSocket? = null
private var clientAddr: InetAddress? = null
private var clientPort: Int = 0
private var thread = Thread()
override fun onCreate() {
debug("call onCreate >>>")
val server = ServerKotlin()
thread = Thread(server)
thread.start()
}
override fun onDestroy() {
debug("call onDestroy >>>")
releaseUDPSocket()
val app = applicationContext as App
app.isPingGood = false
if (!thread.isInterrupted)
thread.interrupt()
super.onDestroy()
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
debug("onStartCommand >>>>>>>>>>")
return START_STICKY
}
override fun onBind(intent: Intent?): IBinder? {
return null
}
override fun onUnbind(intent: Intent?): Boolean {
debug("onUnbind >>>>>>>>>>")
return true
}
/**
* acheieved IP adress broadcast handling
* @param ipStr IP adress
*/
private fun sendMessage(ipStr: String) {
val intent = Intent("message")
intent.putExtra("url", ipStr)
LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
}
internal inner class ServerKotlin : Runnable {
override fun run() {
running = true
debug("S: Connecting...")
/* Create new UDP-Socket */
socket = DatagramSocket(SERVERPORT) //50001 port, UDP server execution , serverAddr
socket!!.soTimeout = 1000
socket!!.broadcast = true
/* By magic we know, how much data will be waiting for us */
val buf = ByteArray(1500)
while (running) { // waiting client request
/* Prepare a UDP-Packet that can
* contain the data we want to receive */
var packet = DatagramPacket(buf, buf.size)
debug("S: Receiving...")
/* Receive the UDP-Packet */
try {
socket!!.receive(packet)
} catch (e: java.lang.Exception) {
debug("UDP S: Error >>> $e")
continue
}
clientAddr = packet.address
clientPort = packet.port
debug("clientAddr: $clientAddr")
debug("clientPort: $clientPort")
packet = DatagramPacket(buf, buf.size, clientAddr, clientPort)
val received = String(packet.data, 0, packet.length).trim { it <= ' ' }
debug("UDP S: Received received >>>>>>>>>> $received")
val app = (applicationContext as App)
if (!app.isPingGood && received.isNotBlank()) {
// health check if device is not connected or not
val pingResult = pingFromUDP(received)
debug("UDP S: ping result >>>>>>>>>> $pingResult")
if (pingResult) {
app.setURL(received) // ip 셋팅
}
}
try {
Thread.sleep(1000)
} catch (e: Exception) {}
}
// Log.d("UDP", "S: Socket Close.")
debug("UDP clientAddr.toString() >>. ${clientAddr.toString()}")
}
}
/**
* UDP socket resource release function
*/
private fun releaseUDPSocket() {
running = false
socket?.broadcast = false
socket?.close()
try {
socket?.soTimeout = 1;
} catch (e: SocketException) {
}
socket?.disconnect()
socket = null
}
/**
* dashcam connection check function
* @param ipStr ip address
* @return result
*/
private fun pingFromUDP(ipStr: String): Boolean {
val url = "<http://$ipStr:8888/action/>"
return ClonAPIManager.instancePing(url).onErrorReturn { e ->
val result = BaseResult()
result.result = "failed"
result.msg = e.message
return@onErrorReturn BaseResult()
}.blockingGet().isSuccess()
}
companion object {
const val SERVERIP = "255.255.255.255" // 'Within' the emulator!
const val SERVERPORT = 50001
}
}