Android串口通信蓝牙通信中数据格式转换整理

1,191 阅读3分钟

Android 定制开发版上应用开发,免不了使用一些串口通信、蓝牙通信,考虑到每次发送的数据包需要尽可能的小,约定的协议中基本上都是一些字节流表示,因此特地将之前搜集到的一些数据格式转换的方法整理出来。在此感谢将这些code发布出来的博主们。

一、Byte相关的数据转换

  1. 获取Byte指定下标[0 - 7]的Bit的值,和获取Byte的所有Bit的值
/**
 * 获取第i位的bit值
 */
fun Byte.getPointedBit(position: Int): Int {
    return (this.toInt() shr position) and 0x1
}

/**
 * 通过byte获取int类型的字节list
 * IntelMode 低字节在前,如 0x55-> 0101 0101
 */
fun Byte.getBitList(intelMode: Boolean = true): List<Int> {
    val list = arrayListOf<Int>()
    val input = this
    for (i in 0 until 8) {
        val index = if (intelMode) (7 - i) else i
        list.add(input.getPointedBit(index))
    }
    return list
}
  1. Byte转16进制字符串
/**
 * 十六进制字节转字符串,不足2位的字符串则在前补0
 * 其实质是Byte->Int->String
 */
fun Byte.toHexString(): String {
    var hexStr = Integer.toHexString(this.toInt() and 0xFF)
    if (hexStr.length == 1) {
        hexStr = "0$hexStr"
    }
    return hexStr.uppercase(Locale.getDefault())
}
  1. Byte 中修改指定位置的Bit,这个需要绕一下,先将Byte转成一个长度为8的数组,然后修改指定下标的值,然后再将这个数组转换成一个Int,最后Int可以直接转成Byte。目前还未发现其他更好的方法,如有后续补充上。
/**
 * 将byte转换成bit组成的数组
 */
fun Byte.toByteArray(): ByteArray {
    val bytes = ByteArray(8)
    for (i in 0 until 8) {
        bytes[i] = this.getPointedBit(i).toByte()
    }
    return bytes
}

/**
 * 一个byte所代表的int值
 */
fun ByteArray.oneByteToIntSum(): Int {
    var sum = 0
    for (i in this.indices) {
        val tmp = this[i]
        // 2 的 n 次方
        sum += (tmp * 2.0.pow(i.toDouble())).toInt()
    }

    return sum
}

二、ByteArray相关的数据转换

  1. ByteArray转Int
/**
 * 有符号,int 占 2 个字节
 */
fun ByteArray.toIntWithTwo(): Int {
    return (this[0].toInt() shl 8) or (this[1].toInt() and 0xFF)
}

/**
 * 无符号,int 占 2 个字节
 */
fun ByteArray.toUnSignIntWithTwo(): Int {
    return (this[0].toInt() and 0xFF) shl 8 or
            (this[1].toInt() and 0xFF)
}

/**
 * 有符号, int 占 4 个字节
 */
fun ByteArray.toIntWithFour(): Int {
    return (this[0].toInt() shl 24) or
            (this[1].toInt() and 0xFF) or
            (this[2].toInt() shl 8) or
            (this[3].toInt() and 0xFF)
}

/**
 * 无符号, int 占 4 个字节
 */
fun ByteArray.toUnSignIntWithFour(): Long {
    return ((this[0].toInt() and 0xFF) shl 24 or
            (this[1].toInt() and 0xFF) shl 16 or
            (this[2].toInt() and 0xFF) shl 8 or
            (this[3].toInt() and 0xFF)).toLong()
}

/**
 * 一个Int转成2个字节的byte数组
 */
fun Int.toIntArrayFor2(): List<Int> {
    val list = arrayListOf<Int>()
    val lowH = (this shr 8) and 0xff
    val lowL = this and 0xff
    list.add(lowH)
    list.add(lowL)
    return list
}

/**
 * 一个Int转成4个字节的byte数组
 */
fun Int.toByteArray4(): ByteArray {
    val byteArray = ByteArray(4)
    val highH = ((this shr 24) and 0xff).toByte()
    val highL = ((this shr 16) and 0xff).toByte()
    val lowH = ((this shr 8) and 0xff).toByte()
    val lowL = (this and 0xff).toByte()
    byteArray[0] = highH
    byteArray[1] = highL
    byteArray[2] = lowH
    byteArray[3] = lowL
    return byteArray
}
  1. ByteArray转字符串
/**
 * 字节数组转字符串
 */
fun ByteArray.toSimpleString(format: Charset = Charsets.UTF_8): String {
    return String(this, format)
}

/**
 * 字节数组转换成16进制字符串
 */
fun ByteArray.toHexString(): String {
    var result = ""
    for (element in this) {
        var hexStr = Integer.toHexString(element.toInt() and 0xFF)
        if (hexStr.length == 1) {
            hexStr = "0$hexStr"
        }
        result += hexStr.uppercase(Locale.getDefault())
    }
    return result
}
  1. ByteArray转Long
/**
 * 字节数组转换为long 8个byte
 */
fun ByteArray.convertToLong(): Long {
    val bais = ByteArrayInputStream(this)
    val dis = DataInputStream(bais)
    return dis.readLong()
}

/**
 * long转换为字节数组 8个byte
 */
fun Long.convertToBytes(): ByteArray {
    val baos = ByteArrayOutputStream()
    val dos = DataOutputStream(baos)
    dos.writeLong(this)
    return baos.toByteArray()
}

/**
 * Long 类型转成4个字节数组
 * 时间只能精确到秒
 */
fun Long.convertToBytes4(): ByteArray {
    var tmp = this
    val bytes = ByteArray(4)
    for (i in bytes.size - 1 downTo 0) {
        bytes[i] = (tmp and 0xFF).toByte()
        tmp = tmp shr 8
    }
    return bytes
}

/**
 * 4个字节数组转成Long 类型
 * 时间只能精确到秒
 */
fun ByteArray.convertToLong4(): Long {
    var num: Long = 0
    for (i in 0 until 4) {
        num = num shl 8
        num = num or ((this[i].toInt() and 0xFF).toLong())
    }
    return num
}
  1. 两个ByteArray拼接
/**
 * byte数组拼接一个byte数组
 */
fun ByteArray.appendByteArray(extraBytes: ByteArray): ByteArray {
    val inputSize = this.size
    val extraSize = extraBytes.size
    val totalSize = inputSize + extraSize
    val combineBytes = ByteArray(totalSize)
    System.arraycopy(this, 0, combineBytes, 0, inputSize)
    System.arraycopy(extraBytes, 0, combineBytes, inputSize, extraSize)
    return combineBytes
}
  1. ByteArray转Double,此种转换较为复杂,目前未找到稳定可用的代码
none
  1. ByteArray 和 BCD 格式的时间相互转换
/**
 * BCD字节数组转为字符串
 */
fun ByteArray.bcdToString(): String {
    val sb = StringBuilder(this.size / 2)
    for (i in 0 until this.size) {
        // 高四位
        sb.append((this[i].toInt() and 0xF0) ushr 4)
        // 低四位
        sb.append(this[i].toInt() and 0x0F)
    }
    val retStr = sb.toString()
    return if (retStr.substring(0, 1).equals("0", ignoreCase = true)) {
        retStr.substring(1)
    } else {
        retStr
    }
}

/**
 * 字符串转BCD字节数组
 */
fun String.bcdToByteArray(): ByteArray {
    var len = this.length
    val mod = len % 2
    val srcStr = if (0 != mod) {
        len += 1
        "0$this"
    } else this
    val bytes = srcStr.toByteArray()
    len = if (len >= 2) len / 2 else len
    val secondBytes = ByteArray(len)
    var j: Int
    var k: Int
    for (p in 0 until srcStr.length / 2) {
        val jIndex = 2 * p
        j = if (bytes[jIndex].toInt().toChar() in '0'..'9') {
            bytes[jIndex].toInt().toChar() - '0'
        } else if (bytes[jIndex].toInt().toChar() in 'a'..'z') {
            bytes[jIndex].toInt().toChar() - 'a' + 0x0a
        } else {
            bytes[jIndex].toInt().toChar() - 'A' + 0x0a
        }
        val kIndex = 2 * p + 1
        k = if (bytes[kIndex].toInt().toChar() in '0'..'9') {
            bytes[kIndex].toInt().toChar() - '0'
        } else if (bytes[kIndex].toInt().toChar() in 'a'..'z') {
            bytes[kIndex].toInt().toChar() - 'a' + 0x0a
        } else {
            bytes[kIndex].toInt().toChar() - 'A' + 0x0a
        }
        val a = (j shl 4) + k
        val b = a.toByte()
        secondBytes[p] = b
    }
    return secondBytes
}

三、String相关的类型转换,主要是方便把二进制字节流转换成易于查看的字符串

  1. 16进制字符串转ByteArray
private fun char2Byte(input: Char): Byte {
    return "0123456789ABCDEF".indexOf(input).toByte()
}

/**
 * 16进制字符串转字节数组,提供3种转换方式
 */
fun String.hexStringToBytes(type: Int = 0): ByteArray {
    if (this.isEmpty()) {
        return ByteArray(0)
    }
    val hexStr = this.uppercase(Locale.getDefault())
    val length = hexStr.length / 2
    val outBytes = ByteArray(length)
    when (type) {
        0 -> {
            val hexCharArr = this.toCharArray()
            for (i in 0 until length) {
                val p = 2 * i
                val p1 = char2Byte(hexCharArr[p]).toInt() shl 4
                val p2 = char2Byte(hexCharArr[p + 1])
                outBytes[i] = p1.toByte() or p2
            }
        }
        1 -> {
            for (i in 0 until length step 2) {
                val v1 = (this[i].digitToIntOrNull(16) ?: -1) shl 4
                val v2 = this[i + 1].digitToIntOrNull(16) ?: -1
                outBytes[i / 2] = (v1 + v2).toByte()
            }
        }
        else -> {
            for (i in outBytes.indices) {
                val subStr = this.substring(2 * i, 2 * i + 2)
                outBytes[i] = subStr.toInt(16).toByte()
            }
        }
    }
    return outBytes
}
  1. 字符串Json格式转Map
/**
 * json 字符串转 Map
 */
fun String.jsonStringToMap(): HashMap<String, Any>? {
    val jsonObject: JSONObject
    try {
        jsonObject = JSONObject(this)
        val keyIter: Iterator<String> = jsonObject.keys()
        var key: String
        var value: Any
        val valueMap = HashMap<String, Any>()
        while (keyIter.hasNext()) {
            key = keyIter.next()
            value = jsonObject[key] as Any
            valueMap[key] = value
        }
        return valueMap
    } catch (e: JSONException) {
        e.printStackTrace()
    }
    return null
}