You need to enable JavaScript to run this app. 如何将字节数组转换为十六进制字符串用于Android Studio Logcat日志输出
优惠活动
大模型
产品
解决方案
定价
更多

如何将字节数组转换为十六进制字符串用于Android Studio Logcat日志输出

问题背景

现有SMALI代码执行完成后,寄存器v4会存储字符串经过UTF-8编码得到的字节数组。由于Logcat无法直接输出原始字节数组内容,需要将该字节数组转换为十六进制字符串后再用于日志打印。
现有代码如下:

sget-object v5, Lkotlin/text/Charsets;->UTF_8:Ljava/nio/charset/Charset;
invoke-static {v4, v2}, Ljava/util/Objects;->requireNonNull(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;
invoke-virtual {v4, v5}, Ljava/lang/String;->getBytes(Ljava/nio/charset/Charset;)[B
move-result-object v4
实现方案

核心逻辑

每个byte占用8位,可拆分为两个4位的半字节,每个半字节的取值范围为0-15,将取值依次映射为0123456789ABCDEF对应的字符,拼接所有字符即可得到完整的十六进制字符串。
为避免内联逻辑引发寄存器冲突,优先封装独立的静态工具方法完成转换,直接在现有代码后调用即可。

第一步:新增静态转换工具方法

将以下方法添加到当前修改类的任意位置,方法入参为目标字节数组,返回值为对应的十六进制字符串:

.method public static bytesToHex([B)Ljava/lang/String;
    .registers 9
    # 入参为空时直接返回空字符串
    if-eqz p0, :return_empty
    const-string v0, "0123456789ABCDEF"
    # 获取字节数组长度
    array-length v1, p0
    # 每个字节对应2个十六进制字符,提前初始化StringBuilder容量减少扩容开销
    mul-int/lit8 v2, v1, 0x2
    new-instance v3, Ljava/lang/StringBuilder;
    invoke-direct {v3, v2}, Ljava/lang/StringBuilder;-><init>(I)V

    const/4 v4, 0x0
    :loop_start
    if-ge v4, v1, :loop_end
    # 取出当前遍历的字节
    aget-byte v5, p0, v4
    # 提取高4位映射对应字符
    shr-int/lit8 v6, v5, 0x4
    and-int/lit8 v6, v6, 0xf
    invoke-virtual {v0, v6}, Ljava/lang/String;->charAt(I)C
    move-result v7
    invoke-virtual {v3, v7}, Ljava/lang/StringBuilder;->append(C)Ljava/lang/StringBuilder;
    # 提取低4位映射对应字符
    and-int/lit8 v6, v5, 0xf
    invoke-virtual {v0, v6}, Ljava/lang/String;->charAt(I)C
    move-result v7
    invoke-virtual {v3, v7}, Ljava/lang/StringBuilder;->append(C)Ljava/lang/StringBuilder;
    # 循环指针后移
    add-int/lit8 v4, v4, 0x1
    goto :loop_start

    :loop_end
    invoke-virtual {v3}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
    move-result-object v0
    return-object v0

    :return_empty
    const-string v0, ""
    return-object v0
.end method

第二步:新增转换与日志输出逻辑

在原有代码的最后一行(即move-result-object v4)之后,添加以下代码完成转换并输出到Logcat:

# 调用转换方法,将v4中的字节数组转为十六进制字符串
invoke-static {v4}, L<你当前修改的类的全路径>;->bytesToHex([B)Ljava/lang/String;
move-result-object v0
# 调用Android系统日志方法输出,日志tag可自定义修改
const-string v1, "HexDebug"
invoke-static {v1, v0}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I

注意事项

  • 代码中的<你当前修改的类的全路径>需要替换为实际类路径,例如Lcom/example/app/MainActivity;
  • 需确认当前所在方法的寄存器声明数量足够,若寄存器不足需调整.registers声明的数值,避免运行时崩溃
  • 新增的调用逻辑中,用于存储hex字符串和日志tag的寄存器,需要选择当前方法后续逻辑不会再用到的空闲寄存器,避免覆盖原有值导致逻辑异常
  • 若需要输出小写十六进制字符,将工具方法中的映射字符串0123456789ABCDEF替换为0123456789abcdef即可

内容的提问来源于stack exchange,提问作者azazazaza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.04 11:06:09