如何在 Kotlin 上持续监听 UDP 数据

Posted

技术标签:

【中文标题】如何在 Kotlin 上持续监听 UDP 数据【英文标题】:How to get UDP data constant listening on Kotlin 【发布时间】:2019-11-14 09:43:07 【问题描述】:

我正在寻找一种在每次收到 UDP 数据包时触发名为 receiveUDP 的函数的方法。我怎样才能在 Kotlin 上做到这一点?这是我目前正在像简单聊天一样工作的代码。

它使用 01 editText 用于用户输入,01 textView 用于显示接收到的数据包和一个按钮来发送用户输入。

package com.e.udpchat1

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.os.StrictMode
import android.view.View
import android.widget.EditText
import android.widget.TextView
import java.io.IOException
import java.net.DatagramPacket
import java.net.DatagramSocket
import java.net.InetAddress


class SoftOptions 
    var RemoteHost: String = "192.168.1.255"
    var RemotePort: Int = 6454

    constructor()
    init


// Global
val Settings = SoftOptions()

class MainActivity : AppCompatActivity() 
    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // Where should I call?
        // var Buffer = receiveUDP(1500)
        // so that it constantly listen to incoming UDP packets
    

    fun clickButtonSend(view: View) 
        // Do something in response to button
        // Send editText1 Text thru UDP.
        val editText = findViewById<EditText>(R.id.editText1)
        var message = editText.text.toString()
        sendUDP(message)
        // Add text to textView1.
        val textView = findViewById<TextView>(R.id.textView1)
        var chat = textView.text.toString()
        textView.setText(chat + message + "\n")
        // Clear editText1 after all sent.
        editText.setText("")// Clear Input text.
    

    fun sendUDP(messageStr: String) 
        // Hack Prevent crash (sending should be done using an async task)
        val policy = StrictMode.ThreadPolicy.Builder().permitAll().build()
        StrictMode.setThreadPolicy(policy)
        try 
            //Open a port to send the package
            val socket = DatagramSocket()
            socket.broadcast = true
            val sendData = messageStr.toByteArray()
            val sendPacket = DatagramPacket(sendData, sendData.size, InetAddress.getByName(Settings.RemoteHost), Settings.RemotePort)
            socket.send(sendPacket)
            println("fun sendBroadcast: packet sent to: " + InetAddress.getByName(Settings.RemoteHost) + ":" + Settings.RemotePort)
         catch (e: IOException) 
    //            Log.e(FragmentActivity.TAG, "IOException: " + e.message)
        
    

    fun receiveUDP( size: Int): ByteArray 
        val ret = ByteArray(size)
        var socket: DatagramSocket? = null
        try 
            //Keep a socket open to listen to all the UDP trafic that is destined for this port
            socket = DatagramSocket(Settings.RemotePort, InetAddress.getByName(Settings.RemoteHost))
            socket.broadcast = true
            val Buffer = ByteArray(1500)
            val packet = DatagramPacket(Buffer, Buffer.size)
            socket.receive(packet)

            // Add text to textView1.
            val textView = findViewById<TextView>(R.id.textView1)
            val chat = textView.text.toString()
            textView.setText(chat + packet + "\n")

         catch (e: Exception) 
            e.printStackTrace()
         finally 
            socket?.close()
        
        return ret
    

我希望在 textView1 中看到每个收到的数据包。

【问题讨论】:

【参考方案1】:

我找到了 Runnables 并使用它们不断检查数据到达。

package com.e.udpchat1

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.os.StrictMode
import android.view.View
import android.widget.EditText
import android.widget.TextView
import java.io.IOException
import java.net.DatagramPacket
import java.net.DatagramSocket
import java.net.InetAddress


class SoftOptions 
    var RemoteHost: String = "192.168.1.255"
    var RemotePort: Int = 6454

    constructor()
    init



// Global
val Settings = SoftOptions()


open class MainActivity : AppCompatActivity() 

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

        println("Create Runnable example.")
        val threadWithRunnable = Thread(udp_DataArrival())
        threadWithRunnable.start()

        // Add text to textView1.
            val textView = findViewById<TextView>(R.id.textView1)
            textView.setText("Hello World from main!\n")

        println("MainActivity onCreate success.")
    

    fun clickButtonSend(view: View) 
        // Do something in response to button
        // Send editText1 Text thru UDP.
        val editText = findViewById<EditText>(R.id.editText1)
        var message = editText.text.toString()
        sendUDP(message)
        // Add text to textView1.
//        val textView = findViewById<TextView>(R.id.textView1)
//        var chat = textView.text.toString()
//        textView.setText(chat + message + "\n")
        // Clear editText1 after all sent.
        editText.setText("")// Clear Input text.
    

    fun sendUDP(messageStr: String) 
        // Hack Prevent crash (sending should be done using an async task)
        val policy = StrictMode.ThreadPolicy.Builder().permitAll().build()
        StrictMode.setThreadPolicy(policy)
        try 
            //Open a port to send the package
            val socket = DatagramSocket()
            socket.broadcast = true
            val sendData = messageStr.toByteArray()
            val sendPacket = DatagramPacket(sendData, sendData.size, InetAddress.getByName(Settings.RemoteHost), Settings.RemotePort)
            socket.send(sendPacket)
            println("fun sendBroadcast: packet sent to: " + InetAddress.getByName(Settings.RemoteHost) + ":" + Settings.RemotePort)
         catch (e: IOException) 
    //            Log.e(FragmentActivity.TAG, "IOException: " + e.message)
        
    

    open fun receiveUDP() 
        val buffer = ByteArray(2048)
        var socket: DatagramSocket? = null
        try 
            //Keep a socket open to listen to all the UDP trafic that is destined for this port
            socket = DatagramSocket(Settings.RemotePort, InetAddress.getByName(Settings.RemoteHost))
            socket.broadcast = true
            val packet = DatagramPacket(buffer, buffer.size)
            socket.receive(packet)
            println("open fun receiveUDP packet received = " + packet.data)

         catch (e: Exception) 
            println("open fun receiveUDP catch exception." + e.toString())
            e.printStackTrace()
         finally 
            socket?.close()
        
    





class udp_DataArrival: Runnable, MainActivity() 
    public override fun run() 
        println("$Thread.currentThread() Runnable Thread Started.")
        while (true)
            receiveUDP()
        
    

【讨论】:

以上是关于如何在 Kotlin 上持续监听 UDP 数据的主要内容,如果未能解决你的问题,请参考以下文章

Kotlin 上的 Android:如何将数据从 Activity 传递到事件监听器?

如何在Kotlin中处理EditText drawableRight图标的点击监听器?

如何在没有 WHILE 循环锁定程序的情况下让 UDP 服务器在 Python 3 中监听?

如何忽略自己的广播 udp 数据包

如何读取从 Youtube API Kotlin/Java 返回的视频的持续时间

如何在适配器的 Kotlin 中提供长点击监听器