手记

Android蓝牙开发初识篇

流程

  1. 获取蓝牙操作对象-BluetoothAdapter

  2. 开启蓝牙 

    1. 通过intent,需要用户同意

    2. mBluetoothAdapter.enable() 不用用户同意

  3. 查看自己配对信息 bondedDevices

  4. 开启可检测性-intent

  5. 搜索设备-广播监听、startDiscovery()

  6. 统一UUID

  7. 成为客户端(写出信息)- BluetoothSocket

  8. 成为服务端(读出信息)- BluetoothServerSocket

基础配置

  1. 获取蓝牙操作对象

 private val mBluetoothAdapter by lazy {
        BluetoothAdapter.getDefaultAdapter()
    }123
  1. 开启蓝牙

需要用户同意

if (!mBluetoothAdapter.isEnabled) {            startActivityForResult(Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE), START_BLUE)
        } else {            toast("蓝牙已经开启了")} override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == START_BLUE && resultCode == Activity.RESULT_OK) {            toast("蓝牙开启成功")
        }
    }1234567891011121314

不需要用户同意

    if (!mBluetoothAdapter.isEnabled) {
            mBluetoothAdapter.enable()
        } else {
            mBluetoothAdapter.disable()
        }12345
  1. 查看自己配对信息

    val bondedDevices = mBluetoothAdapter.bondedDevices
        if (bondedDevices.isEmpty()) {
            toast("当前设备没有配对成功过")
        } else {
            val names = bondedDevices.map {
                it.name + "    " + it.address
            }
            alert {
                items(items = names) { dialogInterface: DialogInterface, i: Int ->
                    dialogInterface.dismiss()
                }
            }.show()
        }12345678910111213
  1. 扫描设配(通过广播监听)

  private val mReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            val action = intent.action
            // When discovery finds a device
            if (BluetoothDevice.ACTION_FOUND == action) {
                // Get the BluetoothDevice object from the Intent
                val device = intent.getParcelableExtra<BluetoothDevice>(BluetoothDevice.EXTRA_DEVICE)
                // Add the name and address to an array adapter to show in a ListView
                mListAdapter.add(device.name + "-" + device.address)
            }
        }
    }


val filter = IntentFilter(BluetoothDevice.ACTION_FOUND)
registerReceiver(mReceiver, filter)

//开启该方法
 if (mBluetoothAdapter.isDiscovering) {
            mBluetoothAdapter.cancelDiscovery()
        }
        mBluetoothAdapter.startDiscovery()12345678910111213141516171819202122

客户端

  1. 成为客户端BluetoothSocket

不需要代码,默认就是客户端1
  1. 连接连接端(根据服务端DeviceAddress)

ConnectThread(mBluetoothAdapter.getRemoteDevice(address)).start()private inner class ConnectThread(val mmDevice: BluetoothDevice) : Thread() {        private val mmSocket: BluetoothSocket?

        init {            var tmp: BluetoothSocket? = null
            try {                // MY_UUID is the app's UUID string, also used by the server code
                tmp = mmDevice.createRfcommSocketToServiceRecord(UUID.fromString("2987f694-71d4-4a08-885a-5d07bd3ca0c4"))
            } catch (e: IOException) {
            }
            mmSocket = tmp
        }        override fun run() {            // Cancel discovery because it will slow down the connection
            mBluetoothAdapter.cancelDiscovery()            try {                // Connect the device through the socket. This will block
                // until it succeeds or throws an exception
                mmSocket?.connect()
            } catch (connectException: IOException) {                // Unable to connect; close the socket and get out
                try {
                    mmSocket?.close()
                } catch (closeException: IOException) {
                }                return
            }            // 开始写入数据
            manageWriteSocket(mmSocket)
        }        /** Will cancel an in-progress connection, and close the socket  */
        fun cancel() {            try {
                mmSocket!!.close()
            } catch (e: IOException) {
            }

        }
    }12345678910111213141516171819202122232425262728293031323334353637383940414243444546
  1. 成功后写入数据(可以先把String转成byte[])

private fun manageWriteSocket(mmSocket: BluetoothSocket?) {
        WriteThread(mmSocket).start()
    }private inner class WriteThread(private val mmSocket: BluetoothSocket?) : Thread() {        private val mmInStream: InputStream?        private val mmOutStream: OutputStream?

        init {            var tmpIn: InputStream? = null
            var tmpOut: OutputStream? = null

            // Get the input and output streams, using temp objects because
            // member streams are final
            try {
                tmpIn = mmSocket?.inputStream
                tmpOut = mmSocket?.outputStream
            } catch (e: IOException) {
            }

            mmInStream = tmpIn
            mmOutStream = tmpOut
        }        override fun run() {//            val buffer = ByteArray(1024)  // buffer store for the stream
            val buffer = byteArrayOf() // buffer store for the stream
            write("用户名|132000000|")
        }        /* Call this from the main activity to send data to the remote device */
        fun write(bytes: String) {            try {
                Log.e("shen", "发送:${bytes.toByteArray()}")
                mmOutStream?.write(bytes.toByteArray())
            } catch (e: IOException) {
                Log.e("shen", "1231")
            }

        }        /* Call this from the main activity to shutdown the connection */
        fun cancel() {            try {
                mmSocket?.close()
            } catch (e: IOException) {
            }

        }
    }12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152

服务端

  1. 开启扫描设配可检测性

val discoverableIntent = Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE)
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300)
startActivity(discoverableIntent)123
  1. 成为服务端

  private inner class AcceptThread : Thread() {        private val mmServerSocket: BluetoothServerSocket?

        init {            // Use a temporary object that is later assigned to mmServerSocket,
            // because mmServerSocket is final
            var tmp: BluetoothServerSocket? = null
            try {                // MY_UUID is the app's UUID string, also used by the client code
                tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord("test", UUID.fromString("2987f694-71d4-4a08-885a-5d07bd3ca0c4"))
            } catch (e: IOException) {
            }

            mmServerSocket = tmp
        }        override fun run() {            var socket: BluetoothSocket? = null
            Log.e("shen", "startReadThread")            // Keep listening until exception occurs or a socket is returned
            //死循环进行数据接收
            while (true) {                try {
                    socket = mmServerSocket?.accept()
                } catch (e: IOException) {                    break
                }                // If a connection was accepted
                if (socket != null) {                    // Do work to manage the connection (in a separate thread)
                    manageReadSocket(socket)
                    mmServerSocket?.close()                    break
                }
            }
        }        /** Will cancel the listening socket, and cause the thread to finish  */
        fun cancel() {            try {
                mmServerSocket!!.close()
            } catch (e: IOException) {
            }

        }
    }1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. 读取数据(通过String(byteArrayOf)方式把byte[]转成String)

private fun manageReadSocket(socket: BluetoothSocket) {
        ReadThread(socket).start()
    }private inner class ReadThread(private val mmSocket: BluetoothSocket) : Thread() {        private val mmInStream: InputStream?

        //        private val mmOutStream: OutputStream?
        init {            var tmpIn: InputStream? = null
            // Get the input and output streams, using temp objects because
            // member streams are final
            try {
                tmpIn = mmSocket.inputStream
            } catch (e: IOException) {
            }

            mmInStream = tmpIn//            mmOutStream = tmpOut
        }        override fun run() {
            val byteArrayOf = ByteArray(1024)            var bytes: Int = 0 // bytes returned from read()
            Log.e("shen", "test")            // Keep listening to the InputStream until an exception occurs
            while (true) {                try {
                    bytes = mmInStream?.read(byteArrayOf) ?: 0
                    val toString = byteArrayOf.toString()
                    val string = String(byteArrayOf) //可以成功转换
                    Log.e("shen", "bytes===${byteArrayOf}")
                    Log.e("shen", "bytes===${toString}")
                    Log.e("shen", "bytes===${string}")                    break
                } catch (e: Exception) {//                    break
                }
            }
        }        /* Call this from the main activity to shutdown the connection */
        fun cancel() {            try {
                mmSocket.close()
            } catch (e: IOException) {
            }
        }
    }1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950

注意点

  1. UUID:客户端和服务端必须保持一致才能连接成功

  2. String转换:使用String(byteArrayOf)方式

  3. 数据读取一次后就需要重启一次蓝牙,这样还能重新发送数据

原文链接:http://www.apkbus.com/blog-865069-78051.html

0人推荐
随时随地看视频
慕课网APP