XuqmGroup-AndroidSDK/sdk-bugcollect/src/main/java/com/xuqm/sdk/bugcollect/Fingerprint.kt
XuqmGroup 3d62a6ed72 fix: docx MIME 检测 + Fingerprint 协程帧稳定性
sdk-webview:
  选文件时 DISPLAY_NAME 在 vivo content://media/external/file/ URI
  上返回 null,导致扩展名推断失效;ContentResolver.getType() 对 .docx
  返回 application/msword(错误)→ allowed 检查拒绝文件。
  修复:DISPLAY_NAME 为 null 时回退查 MediaStore.DATA 提取文件名;
  优先使用扩展名推断的 MIME 而非 ContentResolver 的返回值,
  避免厂商 ROM 返回错误 MIME 的干扰。copyUriToWebViewCache 同步修复。

sdk-bugcollect:
  Fingerprint.compute 取 top3 stack 帧,Kotlin 协程 dispatcher 的
  第 2、3 帧在每次调度时不固定,相同逻辑错误产生不同指纹 → 多条 issue。
  修改为 top1(只取抛出点帧),保证同一位置抛出的异常总被归为一条。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 15:19:51 +08:00

19 行
891 B
Kotlin

package com.xuqm.sdk.bugcollect
object Fingerprint {
// exceptionType = exception class name (e.g. "NullPointerException"), NOT the level string
// Only the innermost "at" frame (throw site) is used for grouping.
// Kotlin coroutine dispatcher frames (frame 2+) vary across runs of the same logical error,
// which caused identical errors to create separate issues.
fun compute(exceptionType: String, message: String, stack: String): String {
val top1 = stack.lines().filter { it.trim().startsWith("at ") }.take(1).joinToString("|")
val normalized = message.replace(Regex("\\b\\d{4,}\\b"), "N")
return sha256("$exceptionType:$normalized:$top1")
}
private fun sha256(s: String): String =
java.security.MessageDigest.getInstance("SHA-256")
.digest(s.toByteArray())
.joinToString("") { "%02x".format(it) }
}