ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 需要传入一个关键参数,BluetoothGattCallback是一个抽象类

需要传入一个关键参数,BluetoothGattCallback是一个抽象类

投稿 Linux操作系统 作者:ecclw459 时间:2026-01-26 17:05:13 0 删除 编辑

注意,每个设备和Gatt只能持有自己的gattCallBack


BluetoothGattCallback包含如下重要的回调方法:


onConnectionStateChange 连接状态回调

onServicesDiscovered 服务发现回调

onCharacteristicRead 特征值读回调

onCharacteristicWrite 特征值写入回调

onCharacteristicChanged 特征值变化通知回调(对应设置了CCCD的通知)

onDescriptorWrite 特征值描述写入回调





 BLE 设备封装类 —— 实现连接、通信与事件分发

 */class BleDevice(    private val deviceName: String,    private val deviceAddress: String,    private var nativeDevice: BluetoothDevice? = null) {    companion object {        private const val TAG = "BleDevice"


        // 服务与特征值 UUID(请根据实际设备修改)

        private val SERVICE_UUID = UUID.fromString("0000fff0-0000-1000-8000-00805f9b34fb")        private val NOTIFY_CHARACTERISTIC_UUID = UUID.fromString("0000fff1-0000-1000-8000-00805f9b34fb")        private val WRITE_CHARACTERISTIC_UUID = UUID.fromString("0000fff2-0000-1000-8000-00805f9b34fb")        // CCCD UUID(标准定义)

        private val CLIENT_CHARACTERISTIC_CONFIG = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")

    }    // 当前连接状态

    @Volatile

    var isConnected: Boolean = false

        private set


    // 回调接口

    var stateListener: ((device: BleDevice, state: ConnectionState) -> Unit)? = null

    var dataListener: ((device: BleDevice, data: ByteArray) -> Unit)? = null


    private var bluetoothGatt: BluetoothGatt? = null

    private var writeCharacteristic: BluetoothGattCharacteristic? = null

    private var notifyCharacteristicUuid: livesoccerzb.com UUID? = null


    // 主线程 Handler,用于回调 UI

    private val mainHandler = Handler(Looper.getMainLooper())    /**

     * 连接设备

     */

    fun connect(context: Context) {        if (isConnected) {

            Log.w(TAG, "Already connected to $deviceName")            return

        }        // 清理旧连接

        closeOldConnection()


        realConnect(context.applicationContext)

    }    private fun closeOldConnection() {        if (bluetoothGatt != null) {

            Log.d(TAG, "Closing previous GATT instance to avoid errors...")            try {

                bluetoothGatt?.close()

            } catch (e: Exception) {

                Log.e(TAG, "Error closing old GATT", e)

            }

            bluetoothGatt = null


            // 延迟重连,避免频繁操作导致 Status 133

            mainHandler.postDelayed(this::realConnectWithAppContext, 200)

        }

    }    private val realConnectWithAppContext: () -> Unit = {        // 在延时任务中重新获取 context(需外部传入)

    }    private fun realConnect(context: Context) {        val adapter = (context.getSystemService(Context.BLUETOOTH_SERVICE) as? BluetoothManager)?.adapter

            ?: run {:gzbeimu.com

                stateListener?.invoke(this, ConnectionState.Error("Bluetooth not available"))                return

            }        if (!adapter.isEnabled) {

            stateListener?.invoke(this, ConnectionState.Error("Bluetooth is disabled"))            return

        }        val device = nativeDevice ?: run {            val d = adapter.getRemoteDevice(deviceAddress)

            nativeDevice = d

            d

        }        try {

            bluetoothGatt = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

                device.connectGatt(context, false, gattCallback, BluetoothDevice.TRANSPORT_LE)

            } else {

                device.connectGatt(context, false, gattCallback)

            }

        } catch (e: IllegalArgumentException) {

            Log.e(TAG, "Invalid device address: $deviceAddress", e)

            stateListener?.invoke(this, ConnectionState.Error("Invalid address"))

        }

    }    /**

     * 断开连接

     */

    fun disconnect() {

        bluetoothGatt?.disconnect()

    }    /**

     * 发送数据

     */

    fun sendData(data: ByteArray): Boolean {        val char = writeCharacteristic ?: return false


        return try {

            char.value = data

            char.writeType = BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT

            bluetoothGatt?.writeCharacteristic(char) == true

        } catch (e: Exception) {

            Log.e(TAG, "Failed to write characteristic", e)            false

        }

    }    /**

     * 主动读取特征值(可选)

     */

    fun readData() {        val char = bluetoothGatt?.getService(SERVICE_UUID)

            ?.getCharacteristic(NOTIFY_CHARACTERISTIC_UUID)

            ?: return


        bluetoothGatt?.readCharacteristic(char)

    }    // MARK: - GATT Callback


    private val gattCallback = object : BluetoothGattCallback() {        override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {            when (newState) {

                BluetoothProfile.STATE_CONNECTED -> {

                    Log.i(TAG, "Connected to $deviceName")

                    isConnected = true

                    mainHandler.post { stateListener?.invoke(this@BleDevice, ConnectionState.Connected) }                    // 请求高优先级连接参数

                    gatt.requestConnectionPriority(BluetoothGatt.CONNECTION_PRIORITY_HIGH)                    // 开始服务发现

                    gatt.discoverServices()

                }

                BluetoothProfile.STATE_DISCONNECTED -> {

                    Log.i(TAG, "Disconnected from $deviceName")

                    isConnected = false

                    writeCharacteristic = null

                    notifyCharacteristicUuid = null


                    gatt.close()

                    bluetoothGatt = null


                    mainHandler.post { stateListener?.invoke(this@BleDevice, ConnectionState.Disconnected) }

                }

            }

        }        override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) {            if (status != BluetoothGatt.GATT_SUCCESS) {

                Log.e(TAG, "Service discovery failed: $status")

                mainHandler.post {

                    stateListener?.invoke(this@BleDevice, ConnectionState.Error("Service discovery failed"))

                }                return

            }            val targetService = gatt.getService(SERVICE_UUID)            if (targetService == null) {

                Log.e(TAG, "Target service not found")

                printAllServices(gatt.services)                return

            }            for (char in targetService.characteristics) {                when (char.uuid) {

                    WRITE_CHARACTERISTIC_UUID -> {

                        writeCharacteristic = char.apply {

                            writeType = BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT

                        }

                        Log.d(TAG, "Write characteristic found: ${char.uuid}")

                    }

                    NOTIFY_CHARACTERISTIC_UUID -> {

                        Log.d(TAG, "Notify characteristic found: ${char.uuid}")

                        notifyCharacteristicUuid = char.uuid

                        enableNotification(gatt, char)

                    }

                }

            }

        }        // 接收被动通知的数据(服务器主动推送)

        override fun onCharacteristicChanged(

            gatt: BluetoothGatt,

            characteristic: BluetoothGattCharacteristic

        ) {

            handleReceivedData(characteristic.value ?: byteArrayOf())

        }        // 主动读取返回的数据

        override fun onCharacteristicRead(

            gatt: BluetoothGatt,

            characteristic: BluetoothGattCharacteristic,

            status: Int

        ) {            if (status == BluetoothGatt.GATT_SUCCESS) {

                Log.d(TAG, "Read success: ${characteristic.uuid}")

                handleReceivedData(characteristic.value ?: byteArrayOf())

            }

        }        override fun onDescriptorWrite(

            gatt: BluetoothGatt,

            descriptor: BluetoothGattDescriptor,

            status: Int

        ) {            if (status == BluetoothGatt.GATT_SUCCESS) {

                Log.d(TAG, "CCCD enabled: ${descriptor.characteristic.uuid}")

            } else {

                Log.e(TAG, "Failed to write descriptor: $status")

            }

        }

    }    private fun enableNotification(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) {        if (!gatt.setCharacteristicNotification(characteristic, true)) {

            Log.e(TAG, "Failed to set characteristic notification")            return

        }        val cccd = characteristic.getDescriptor(CLIENT_CHARACTERISTIC_CONFIG)        if (cccd != null) {

            cccd.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE

            gatt.writeDescriptor(cccd)

        } else {

            Log.w(TAG, "CCCD not found for characteristic ${characteristic.uuid}. Trying fallback...")            // 尝试写入第一个可用描述符(部分设备非标准实现)

            characteristic.descriptors.firstOrNull()?.let { desc ->

                desc.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE

                gatt.writeDescriptor(desc)

            }

        }

    }    private fun handleReceivedData(value: ByteArray) {

        Log.d(TAG, "Received data: ${value.toHexString()}")

        mainHandler.post { dataListener?.invoke(this, value) }

    }    private fun printAllServices(services: List<BluetoothGattService>) {

        Log.d(TAG, "Discovered services:")

        services.forEach ttkq-163.cn { service ->

            Log.d(TAG, "  Service: ${service.uuid}")

            service.characteristics.forEach { char ->

                Log.d(TAG, "    Char: ${char.uuid} | Props: ${char.properties}")

            }

        }

    }

}// MARK: - 状态枚举sealed class ConnectionState {    object Connected : ConnectionState()    object Disconnected : ConnectionState()    data class Error(val message: String) : ConnectionState()

}




create table account (

  id          bigint not null auto_increment,

  username    varchar(32)     default '',chengyiwl.com

  password    varchar(32)     default '',

  balance     decimal(10,2)   default '0.00',

  create_time datetime        default null,

  update_time datetime        default null,  primary key (`id`)

);insert into account (username, password, create_time, balance) values('admin', 'admin123', '2020-01-01 12:00:00', 1000.10),

('user', 'user123', '2024-05-02 8:30:00', 101.00),

('guest', 'guest123', '2022-03-03 15:00:00', 10.00),

('tang', 'tang123', '2019-06-01 21:30:30', 1.88),




import com.tang.kite.annotation.id.IdType;import java.math.BigDecimal;import java.time.LocalDateTime;public class Account {    @Id(type = IdType.AUTO)

    private Long id;    private String username;    private String password;    private BigDecimal balance;    private LocalDateTime createTime;    private LocalDateTime updateTime;    // Getters and Setters


import com.tang.kite.annotation.id.IdType

import java.math.BigDecimal

import java.time.LocalDateTime


class Account (


    @Id(type = IdType.AUTO)

    var id: Long? = null,

    var username: String? = null,

    var password: String? = null,

    var balance: BigDecimal? = null,

    var createTime: LocalDateTime? = null,

    var updateTime: LocalDateTime? = null


)

继承 BaseMapper 接口创建 Mapper 接口

Java

import com.tang.kite.mapper.BaseMapper;

import com.tang.kite.spring.annotation.Mapper;


@Mapper:c20paper.com

public interface AccountMapper extends BaseMapper<Account> {

}

Kotlin

import com.tang.kite.mapper.BaseMapper

import com.tang.kite.spring.annotation.Mapper


@Mapper

interface AccountMapper : BaseMapper<Account>

在 Spring Boot 应用类上添加 @MapperScan 注解

Java

import com.tang.kite.spring.annotation.MapperScan;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;


@MapperScan("com.tang.application.mapper")

@SpringBootApplication:lnzxyp.com

public class KiteApplication {


    public static void main(String[] args) {

        SpringApplication.run(KiteApplication.class, args);

    }


}

Kotlin

import com.tang.kite.spring.annotation.MapperScan

import org.springframework.boot.autoconfigure.SpringBootApplication

import org.springframework.boot.runApplication


@MapperScan(["com.tang.application.mapper"])

@SpringBootApplication

class KiteApplication


fun main(args: Array<String>) {

runApplication<KiteApplication>(*args)

}

测试 Mapper 接口

Java:tjweiting.com

import com.tang.demo.mapper.AccountMapper;

import com.tang.kite.spring.annotation.MapperScan;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;


@MapperScan("com.tang.application.mapper")

@SpringBootApplication

public class KiteApplication {ttkq-qq.cn


    public static void main(String[] args) {

        var context = SpringApplication.run(KiteApplication.class, args);

        var accountMapper = context.getBean(AccountMapper.class);

        var accounts = accountMapper.select();

        accounts.forEach(System.out::println);ttkq.pro

    }


}

Kotlin

import com.tang.demo.mapper.AccountMapper

import com.tang.kite.spring.annotation.MapperScan

import org.springframework.boot.autoconfigure.SpringBootApplication

import org.springframework.boot.runApplication


@MapperScan(["com.tang.application.mapper"])

@SpringBootApplication

class KiteApplication


fun main(args: Array<String>) {ttkqw.com

val context = runApplication<KiteApplication>(*args)

val accountMapper = context.getBean(AccountMapper::class.java)





来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70048957/viewspace-3109009/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2026-01-07

  • 博文量
    108
  • 访问量
    102119