串接上文,蓝牙扫描到设备之后存储到RecyclerView列表中,设置点击回调,点击之后开始连接蓝牙
class BlueToothScanAdapter(
private val context: Context,
private val deviceList: ArrayList<BluetoothDevice>
) :
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private lateinit var listener: DeviceClickListener
fun setListener(listener: DeviceClickListener) {
this.listener = listener
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val view =
LayoutInflater.from(context).inflate(R.layout.bluetooth_device_item, parent, false)
return BluetoothViewHolder(view)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val device = deviceList[position]
val viewHolder = holder as BluetoothViewHolder
if (device.name == null) {
val text = "蓝牙设备$position"
viewHolder.tvName.text = text
} else {
viewHolder.tvName.text = device.name
}
viewHolder.tvAddress.text = device.address
viewHolder.itemView.setOnClickListener {
listener.onCLick(device)
}
}
override fun getItemCount(): Int {
return deviceList.size
}
inner class BluetoothViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val tvName: TextView = itemView.findViewById(R.id.tv_bluetooth_name)
val tvAddress: TextView = itemView.findViewById(R.id.tv_bluetooth_address)
}
interface DeviceClickListener {
fun onCLick(device: BluetoothDevice)
}
连接蓝牙需要在异步线程中进行
class BluetoothConnectThread(
device: BluetoothDevice?,
callback: BluetoothConnectCallback?
) : Thread() {
var bluetoothSocket: BluetoothSocket? = null
var bluetoothDevice: BluetoothDevice? = null
private var connected = false
private val lock = Any()
//蓝牙连接回调接口
private var connectCallback: BluetoothConnectCallback? = null
override fun run() {
if (bluetoothSocket != null) {
if (connected) {
cancel2()
connected = false
}
}
object : Thread() {
override fun run() {
connect()
if (connected) {
if (connectCallback != null) {
connectCallback.connectSuccess(bluetoothSocket)
}
}
}
}.start()
}
fun connect() {
try {
synchronized(lock) {
bluetoothSocket!!.connect()
connected = true
}
} catch (connectException: Exception) {
connectException.printStackTrace()
cancel()
try {
val m: Method
m = bluetoothDevice!!.javaClass.getMethod(
"createRfcommSocket", *arrayOf<Class<*>?>(
Int::class.javaPrimitiveType
)
)
bluetoothSocket = m.invoke(bluetoothDevice, Integer.valueOf(1)) as BluetoothSocket
if (bluetoothSocket != null) {
bluetoothSocket!!.connect()
connected = true
}
} catch (ex: Exception) {
ex.printStackTrace()
if (connectCallback != null) {
connectCallback.connectFailed(ex.message)
}
}
}
}
fun cancel() {
try {
synchronized(lock) {
if (connected) {
bluetoothSocket!!.close()
connected = false
}
}
} catch (e: IOException) {
e.printStackTrace()
}
}
fun cancel2() {
try {
synchronized(lock) {
bluetoothSocket!!.close()
connected = false
}
} catch (e: IOException) {
e.printStackTrace()
}
}
companion object {
private val BluetoothUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")
}
init {
try {
bluetoothDevice = device
bluetoothSocket = bluetoothDevice!!.createInsecureRfcommSocketToServiceRecord(
BluetoothUUID
)
connectCallback = callback
} catch (e: Exception) {
e.printStackTrace()
}
}
}
蓝牙连接回调接口
interface BluetoothConnectCallback {
fun connectSuccess(socket: BluetoothSocket?)
fun connectFailed(errorMsg: String?)
fun connectCancel()
}
在activity中进行蓝牙连接,注意连接前要关闭蓝牙扫描
override fun onCLick(device: BluetoothDevice) {
if (bluetoothAdapter.isDiscovering) {
bluetoothAdapter.cancelDiscovery()
}
val blueThread = BluetoothConnectThread(device, object : BluetoothGattCallback(),
BluetoothConnectCallback {
override fun connectSuccess(socket: BluetoothSocket?) {
Logger.e("blueConnect: success")
}
override fun connectFailed(errorMsg: String?) {
Logger.e("blueConnectFail: $errorMsg")
}
override fun connectCancel() {
Logger.e("blueConnect: cancel")
}
});
blueThread.connect()
blueThread.start()
}
蓝牙连接成功后注册的广播同样会收到蓝牙状态改变的信息
if (StringUtil.isSameStr(BluetoothDevice.ACTION_BOND_STATE_CHANGED, action)) {
val device: BluetoothDevice? =
intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)
if (device != null) {
tvConnectName.text = device.name
tvConnectAddress.text = device.address
}
}