Bt Socket关闭异常

时间:2017-10-23 07:54:14

标签: android sockets bluetooth kotlin

我正在构建一个应该通过蓝牙套接字发送文件的应用程序但由于某种原因我不断得到相同的例外。错误消息说套接字已经关闭但我不明白在我尝试从它读取之前它是如何或为什么关闭的。向用户显示AlertDialog以及可供选择的选项。他们应该:1。配对设备。 2.将文件发送到设备(当前在对话框中标记为'connect')。选择连接选项后,设备配对后会发生异常。当接收设备尝试从套接字读取时,我得到以下异常:

Process: com.example.zemcd.toofxchange, PID: 1074
      java.io.IOException: bt socket closed, read return: -1
      at android.bluetooth.BluetoothSocket.read(BluetoothSocket.java:588)
      at android.bluetooth.BluetoothInputStream.read(BluetoothInputStream.java:96)
      at java.io.BufferedInputStream.read1(BufferedInputStream.java:273)
      at java.io.BufferedInputStream.read(BufferedInputStream.java:334)
      at java.io.FilterInputStream.read(FilterInputStream.java:107)
      at kotlin.io.ByteStreamsKt.copyTo(IOStreams.kt:101)
      at kotlin.io.ByteStreamsKt.copyTo$default(IOStreams.kt:98)
      at kotlin.io.ByteStreamsKt.readBytes(IOStreams.kt:117)
      at com.example.zemcd.toofxchange.BluetoothUtils$Companion.receiveFile(BluetoothUtils.kt:82)
      at com.example.zemcd.toofxchange.ListenThread$run$acceptThread$1.run(BluetoothUtils.kt:104)
      at java.lang.Thread.run(Thread.java:761)

下面是用于pair,unpair和connect(发送数据)以及使用的线程子类的函数:

class BluetoothUtils {

companion object {

    var listener: ListenThread? = null

    val _UUID = UUID.fromString("a0e7e4c7-0e4e-43b7-9d18-659192512164")
    val TAG = "BluetoothUtils"

    val receiver = MainBTStatusReceiver()

    fun initPairingServer(adapter: BluetoothAdapter){
        var mmServerSocket: BluetoothServerSocket?
        try {
            var tmp = adapter.listenUsingRfcommWithServiceRecord(TAG, _UUID)
            mmServerSocket = tmp
            listener = ListenThread(mmServerSocket)
            listener!!.start()
        }catch (ioe: IOException){
            Log.e(TAG, "Error initializing Bluetooth", ioe)
        }
    }

    fun cancelListener() = listener!!.cancel()

    fun connect(adapter: BluetoothAdapter, device: BluetoothDevice):Unit{
        var btSocket: BluetoothSocket?
        Log.d(TAG, "connect function called")
        if (device.bondState==BluetoothDevice.BOND_NONE)return //to prompt user to pair
        try {
            adapter.cancelDiscovery()
            btSocket = device.createRfcommSocketToServiceRecord(_UUID)
            ConnectThread(btSocket).start()
        }catch (ioe: IOException){
            Log.e(TAG, "error connecting", ioe)
        }
    }

    fun startPair(adapter: BluetoothAdapter, device: BluetoothDevice): Unit{
        adapter.cancelDiscovery()
        Log.d(TAG, device.bondState.toString())
        device.createBond()
    }

    fun unPair(device: BluetoothDevice): Any = device::class.java.getMethod("removeBond").invoke(device)

    fun sendFile(btSocket: BluetoothSocket){
        val out = btSocket.outputStream.buffered()
        out.use {
            val msg = "hello".toByteArray()
            Log.d(TAG, "sending data")
            it.write(msg, 0, msg.size)
            it.flush()
        }
        btSocket.close()
    }

    fun receiveFile(btSocket: BluetoothSocket){
        Log.d(TAG, "receiveFile called")
        val inStream = btSocket.inputStream.buffered()
        //val bytes: ByteArray = ByteArray(1024)
        val bytes: ByteArray = inStream.use { it.readBytes(1024)}
        Log.d(TAG, bytes.toString())
        btSocket.close()
    }

}
}

class ListenThread(val btServSock: BluetoothServerSocket) : Thread(){

companion object {
    val TAG = "ListenThread"
}

var btSocket: BluetoothSocket? = null

override fun run() {
    super.run()
    while (true){
        try {
            Log.d(TAG, "listening . . . ")
            btSocket = btServSock.accept()
            Log.d(TAG, btSocket.toString() + " was accepted")
            val acceptThread = Thread(Runnable { BluetoothUtils.receiveFile(btSocket!!) })
            acceptThread.start()
        }catch (ioe: IOException){
            Log.e(TAG, "Error", ioe)
            break
        }
    }
}

fun cancel() = btServSock.close()
}

class ConnectThread(val btSocket: BluetoothSocket) : Thread(){

companion object {
    val TAG = "Pairing Thread"
}

override fun run() {
    super.run()

    try {
        Log.d(TAG, "attempting to connect")
        btSocket.connect()
        BluetoothUtils.sendFile(btSocket)
    }catch (ioe: IOException){
        Log.e(TAG, "error connecting", ioe)
        btSocket.close()
    }
}
}

并且它们在OnClickListener中被调用:

ops.forEach { it.setOnClickListener {
                Toast.makeText(it.context, it.id.toString(), Toast.LENGTH_SHORT).show()
                when(it.id){
                    R.id.statOp -> {}
                    R.id.connectOp -> {
                        Log.d(TAG, "connectOp reached")
                        BluetoothUtils.connect(BluetoothAdapter.getDefaultAdapter(), btDevice)
                        dialog!!.dismiss()
                    }
                    R.id.pairOp -> {
                        Log.d(TAG, "pairOp reached")
                        mReceiver.setFocus(this@DeviceHolder)
                        BluetoothUtils.startPair(BluetoothAdapter.getDefaultAdapter(), btDevice)
                        Log.d(TAG, "start pair complete")
                        dialog!!.dismiss()
                    }
                    R.id.unPairOp -> {
                        Log.d(TAG, "unPairOp reached")
                        mReceiver.setFocus(this@DeviceHolder)
                        BluetoothUtils.unPair(btDevice)
                        Log.d(TAG, "unpair complete")
                        dialog!!.dismiss()
                    }
                    R.id.sendOp -> {}
                }
            } }

这是我的资源功能:

inline fun <T: AutoCloseable, U> withResources(resource: T, fn: (T) -> U) : U{
try {
    return fn(resource)
}finally {
    resource.close()
}
}

请帮我找到我的错误。如果需要我的代码的其他部分让我知道,我会发布它们。谢谢你的帮助。

0 个答案:

没有答案