本原创文章帖发布在华为开发者联盟社区,欢迎开发者前往访问评论交流,更多与该内容相关讨论,请点击原帖查看:ErrorManager助力高效应对AppFreeze问题:Native崩溃日志的AI辅助定位-华为开发者话题 | 华为开发者联盟
引言
应用使用过程中,点击屏幕后毫无反应是件让人抓狂的事。手指点在屏幕上,界面却像凝固了一样,既不知道应用是在认真处理,还是已经彻底卡死。这种情况有个专门的名字:AppFreeze(应用冻屏)。
对开发者来说,冻屏问题一直是个麻烦事。系统检测到冻屏后生成的日志,常常缺少足够的上下文。看到日志只知道"线程卡住了",却不知道"为什么卡住",定位问题像在雾里摸索。
现在,这个情况有了改善。HarmonyOS SDK 提供了 OH_HiCollie_SetFreezeCallback 冻屏回调接口,开发者可以在系统冻屏时主动写入自定义日志,这些日志会被迁移到 APP_FREEZE 或 APP_HICOLLIE 事件中。配合系统日志一起看,问题定位会清晰很多。
什么是应用冻屏
先从基础说起。应用冻屏指的是应用持续一段时间不响应用户操作的现象。从系统角度看,当主线程长时间阻塞,无法处理输入事件或完成生命周期回调时,就会触发冻屏检测。
根据触发场景不同,冻屏分为以下几类:
系统会自动检测这些场景并生成故障日志。
冻屏回调:主动注入业务上下文
传统维测是"事后分析"模式——应用卡死了,日志生成了,开发者再根据日志反推原因。问题在于,系统日志不感知业务语义。同样是主线程卡 6 秒,可能是网络请求卡住、数据库操作慢、还是计算任务阻塞消息队列,系统日志看不出区别。
OH_HiCollie_SetFreezeCallback 就是来解决这个问题的。系统在冻屏事件触发时,会回调开发者注册的函数。开发者可以在回调里写入当前业务状态的自定义日志,这些内容最终会出现在 APP_FREEZE 或 APP_HICOLLIE 事件中。
接口声明
void* OH_HiCollie_SetFreezeCallback(OH_HiCollie_FreezeCallback callback)
系统发生冻屏事件时,会自动调用开发者注册的自定义函数。开发者可以在回调中写入业务状态日志、记录关键变量值、输出链路追踪信息。这些内容会被迁移到 APP_FREEZE 或 APP_HICOLLIE 事件,结合系统日志形成完整的故障信息。
回调函数签名
typedef size_t (*OH_HiCollie_FreezeCallback)(OH_HiCollie_Freeze_Type type, void* buffer, size_t size)
回调接收三个参数:
返回值表示写入的字节数。
支持的冻屏类型
API version 24 起支持以下冻屏类型:
快速上手
来看怎么使用这个接口。
示例代码
#include "hicollie/hicollie.h"static size_t UserFreezeCallback(OH_HiCollie_Freeze_Type type, void* buffer, size_t size){ std::string logInfo = "Business state: "; switch (type) { case OH_THREAD_BLOCK_3S: logInfo += "Main thread blocked for 3s"; break; case OH_THREAD_BLOCK_6S: logInfo += "Main thread blocked for 6s"; break; case OH_LIFECYCLE_TIMEOUT: logInfo += "Ability lifecycle timeout"; break; case OH_APP_INPUT_BLOCK: logInfo += "Input event blocked"; break; default: logInfo += "Other freeze type"; break; } logInfo += ", Current screen: HomePage, User action: button_click"; char* bufferPtr = static_cast<char*>(buffer); int written = snprintf(bufferPtr, size, "%s", logInfo.c_str()); return written;}void InitFreezeCallback(){ OH_HiCollie_SetFreezeCallback(UserFreezeCallback);}使用步骤
引入头文件:在 C++ 代码中包含 #include "hicollie/hicollie.h"
实现回调函数:根据业务需求,在回调中写入有助于定位问题的日志信息
注册回调:在应用启动阶段调用 OH_HiCollie_SetFreezeCallback 注册回调函数
订阅事件:通过 HiAppEvent 接口订阅 APP_FREEZE 或 APP_HICOLLIE 事件,获取包含自定义日志的完整故障信息
查看日志
冻屏事件发生后,订阅的事件中会包含 external_callback_log 字段,这个字段就是在回调里写入的自定义日志。结合系统的线程堆栈、Binder 调用链、内存信息等,可以更快定位问题根因。
应用场景举例
场景一:网络请求超时追踪
static size_t NetworkFreezeCallback(OH_HiCollie_Freeze_Type type, void* buffer, size_t size){ std::string log; log += "Network request info: "; log += "URL=" + g_currentRequestUrl + ", "; log += "Timeout=" + std::to_string(g_requestTimeout) + "ms, "; log += "Retry count=" + std::to_string(g_retryCount); char* buf = static_cast<char*>(buffer); return snprintf(buf, size, "%s", log.c_str());}场景二:数据库操作日志
static size_t DatabaseFreezeCallback(OH_HiCollie_Freeze_Type type, void* buffer, size_t size){ std::string log; log += "Database operation: "; log += "Table=" + g_currentTable + ", "; log += "Operation=" + g_currentOperation + ", "; log += "Records affected=" + std::to_string(g_recordsAffected); char* buf = static_cast<char*>(buffer); return snprintf(buf, size, "%s", log.c_str());}场景三:页面状态记录
static size_t PageFreezeCallback(OH_HiCollie_Freeze_Type type, void* buffer, size_t size){ std::string log; log += "Page context: "; log += "Current page=" + g_currentPageName + ", "; log += "Navigation stack depth=" + std::to_string(g_navStackSize) + ", "; log += "Last user interaction=" + g_lastInteraction; char* buf = static_cast<char*>(buffer); return snprintf(buf, size, "%s", log.c_str());}最佳实践
使用冻屏回调时有几点建议:
1. 写入关键业务上下文
避免写入无意义的固定字符串,尽量记录与当前业务状态相关的信息:
• 正在处理的业务类型
• 关键变量的当前值
• 用户最近的操作行为
2. 控制日志长度
缓冲区最大支持 64KB,但建议日志控制在 1KB 以内,超过之后大概率会导致崩库。内容要简洁明确。
3. 避免在回调中执行耗时操作
回调执行时系统状态可能已不稳定,避免在回调中进行 I/O 操作或获取锁,以免加重系统负担。
4. 结合多种维测手段
冻屏回调是维测工具箱的一员,建议与线程卡死检测(OH_HiCollie_Init_StuckDetection)、卡顿检测(OH_HiCollie_Init_JankDetection)等能力结合使用。
总结
OH_HiCollie_SetFreezeCallback 冻屏回调接口让开发者可以主动注入业务语义,不再被动等待系统日志。配合原有的维测能力使用,能大幅提升故障定位效率。
如果应用经常出现卡死问题,或者需要快速响应线上故障,这个接口值得关注。
🔗 官网开发者学堂视频:https://developer.huawei.com/consumer/cn/training/result?type2List=201783644516849879&orderBy=1&courseType=5

🔗 社区 DFX 专题文章: https://developer.huawei.com/consumer/cn/forum/subject/2101218731402391001


【扫码加入 HarmonyOS DFX 技术交流群】





