Android Studio Kotlin:如何将蓝牙GATT的两个uint8合并为uint16?
嗨,刚从C转Kotlin的话,确实会因为类型安全的特性遇到字节操作的小坑,我来帮你搞定这个uint16合并的问题~
首先说清楚你之前出错的核心原因:Kotlin里的Byte是有符号类型,直接用它做移位操作会自动转成Int并触发符号扩展,导致结果不符合预期。解决的关键是先把有符号字节转成无符号的UByte,再进行合并操作。
方法一:直接用无符号字节移位合并(最直观,和C逻辑最接近)
这是最贴合你原有思路的写法,先把两个字节转成无符号类型,再按位操作:
// 提取高、低字节并转为无符号类型 val highByte = characteristic.value[1].toUByte() val lowByte = characteristic.value[2].toUByte() // 高字节左移8位,再和低字节按位或,得到UShort(对应uint16) val uint16Value = (highByte shl 8) or lowByte // 转成字符串赋值给strValue val strValue = uint16Value.toString()
和C里(highByte << 8) | lowByte的逻辑完全一致,只是Kotlin需要显式转无符号类型来避免符号扩展问题。
方法二:用ByteBuffer解析(适合复杂字节数组场景)
如果后续还要解析更多不同类型的字段,用ByteBuffer会更规范,还能直接指定字节序:
import java.nio.ByteBuffer import java.nio.ByteOrder // 包装特征值的字节数组,指定大端序(因为你的高字节在前) val buffer = ByteBuffer.wrap(characteristic.value).order(ByteOrder.BIG_ENDIAN) // 跳过第一个字节,读取两个字节转为UShort val uint16Value = buffer.position(1).getShort().toUShort() // 转成字符串 val strValue = uint16Value.toString()
getShort()会自动读取当前位置开始的两个字节,toUShort()把有符号的Short转成无符号的uint16类型,完美匹配你的需求。
补充说明:为什么之前的shl会出错?
举个例子,如果你的高字节是0x80(对应有符号Byte的-128),直接做shl 8的话,Kotlin会先把它转成Int的0xFFFFFF80,左移8位后变成0xFFFF8000,这显然不是你要的uint16值。而转成UByte后,0x80就是纯粹的无符号8位值,移位后不会有多余的符号位干扰。
内容的提问来源于stack exchange,提问作者NIXIE_123
相关产品推荐
相关产品推荐

