logcat日志的使用——Qt For Android

前言

最近一直用qt开发安卓app,一直无法用真机调试,可能是缺什么东西。但是如果通过Qt Creator在真机上运行,可以在电脑控制台看打印(安卓本身的日志、qDebug之类的打印),所以我是通过打印猜测问题所在,这样凑合着用。

最近换了个测试机,控制台就不打印了,包括qDebug的一些都没有,这就很难受了。

所以,就学习了一下安卓的日志工具logcat,查资料时,发现还可以与Qt的一些打印(qDebug、qInfo等)结合,都显示在命令行工具界面中,方便查看。

知识储备

Logcat 命令行工具

安卓的日志分有优先级:

  • V:详细(最低优先级)
  • D:调试
  • I:信息
  • W:警告
  • E:错误
  • F:严重错误
  • S:静默(最高优先级,绝不会输出任何内容)

如要将日志输出降低到可管理的水平,可使用过滤表达式限制日志输出。

过滤表达式采用**tag:priority ...** 格式,其中 tag 表示您感兴趣的标记,priority 表示可针对该标记报告的最低优先级。不低于指定优先级的标记的消息会写入日志。在一个过滤表达式中提供任意数量的 tag:priority 规范。一系列规范使用空格分隔。

以下是一个过滤表达式的示例,该表达式会抑制除标记为"ActivityManager"、优先级不低于"信息"的日志消息,以及标记为"MyApp"、优先级不低于"调试"的日志消息以外的所有其他日志消息:

复制代码
adb logcat ActivityManager:I MyApp:D *:S

也可控制日志输出格式 :使用 -v 选项,并指定下列某一受支持的输出格式:

  • brief:显示优先级、标记以及发出消息的进程的 PID。
  • long:显示所有元数据字段,并使用空白行分隔消息。
  • process:仅显示 PID。
  • raw:显示不包含其他元数据字段的原始日志消息。
  • tag:仅显示优先级和标记。
  • thread::旧版格式,显示优先级、PID 以及发出消息的线程的 TID。
  • threadtime(默认值):显示日期、调用时间、优先级、标记、PID 以及发出消息的线程的 TID。
  • time:显示日期、调用时间、优先级、标记以及发出消息的进程的 PID。

如:

复制代码
adb logcat -v thread

常用的命令有:

  • adb logcat ,查看输出的全部日志
  • adb logcat -v time ,带日期的日志
  • adb logcat -v time -s Tag 。仅显示指定标签的日志信息,同时带有日期

详细使用说明可看官网介绍:

Logcat 命令行工具 | Android Studio | Android Developers (google.cn)

qInstallMessageHandler

Message Handler用于打印出调试消息、警告、严重和致命错误消息。也就是说 qDebug(), qInfo(), qWarning(), qCritical(), qFatal()都是通过这个消息句柄打印出来的。

Qt提供了一个函数qInstallMessageHandler 用于安装消息处理函数,也就是可用自定义的Message Handler 替代之前默认的。

具体可见帮助文档说明

<QtGlobal> - Global Qt Declarations | Qt Core 5.15.16

我们可以使用自定义的Message Handler将打印消息收集起来写入文件,作为日志。

当然,也可以做其他处理 ,比如此次是将打印信息写入安卓的日志。

代码

上面关于logcat的帮助文档中有关于写日志的描述

日志记录系统的 C/C++ 主接口是共享库 liblog 及其头文件 <android/log.h>。所有语言特定的日志记录工具(包括 android.util.Log)最终都会调用函数 __android_log_write。默认情况下,它会调用函数 __android_log_logd_logger,该函数使用套接字将日志条目发送到 logd。从 API 级别 30 开始,可通过调用 __android_set_log_writer 更改日志记录函数

复制代码
int __android_log_write(
  int prio,
  const char *tag,
  const char *text
)

Writes the constant string text to the log, with priority prio and tag tag.

下面的代码来自网络,亲测,可用:

复制代码
#ifndef QDEBUG2LOGCAT_H

#define QDEBUG2LOGCAT_H

#include <QtMsgHandler>

#ifdef ANDROID

void installLogcatMessageHandler(const char *TAG);

#else

#define installLogcatMessageHandler(TAG)

#endif

#endif // QDEBUG2LOGCAT_H

#if defined(ANDROID)

#include "qDebug2Logcat.h"

#include <android/log.h>

#include <QDebug>

#include <QByteArray>

static const char *g_TAG = 0;

static void messageOutput2Logcat(QtMsgType type,

                                 const QMessageLogContext &context,

                                 const QString &msg)

{

    int prio = ANDROID_LOG_VERBOSE;

    QByteArray localMsg = msg.toLocal8Bit();

    switch (type) {

    case QtDebugMsg:

        prio = ANDROID_LOG_DEBUG;

        break;

    case QtWarningMsg:

        prio = ANDROID_LOG_WARN;

        break;

    case QtCriticalMsg:

        prio = ANDROID_LOG_ERROR;

        break;

    case QtFatalMsg:

        prio = ANDROID_LOG_FATAL;
        break;

    case QtInfoMsg:

        prio = ANDROID_LOG_INFO;

        break;

    default:
        break;

    }

    __android_log_write(prio, g_TAG, localMsg.data());

}

void installLogcatMessageHandler(const char *TAG)

{

    g_TAG = (TAG == 0 ? "QDebug" : TAG);

    qInstallMessageHandler(messageOutput2Logcat);

}

#endif

int main(int argc, char *argv[])
{
    //注册自定义的消息处理函数
    installLogcatMessageHandler("CustomTag");

  ...

}

运行

在电脑上通过adb连接安卓设备后,调用命令行查看日志,

比如 标签为"onboardTrainingLog"的带日期等信息的日志:

复制代码
adb logcat -v -time -s onboardTrainingLog

显示如下

附

关于通过qInstallMessageHandler实现各个平台日志,可参考下面的博客:

Qt 在Windows/Mac/Android下使用日志------------------附赠完整代码和示例-CSDN博客

结束语

有了日志,感觉就有了底气。

相关推荐
_祝你今天愉快36 分钟前
Paint Cavans高级绘制:[二] Paint-滤镜,XFERMODE
android
小乖写代码42 分钟前
字段获取代码(Android) · Android Input Examples
android·whatsapp·账号注册
booboosui1 小时前
停一个活只有杀进程:界面上少了「说点要求」
android
starzy19902 小时前
深入理解Scala隐式值:编译期自动装配
开发语言·后端·scala
布莱克6053 小时前
Swift 条件语句详解:从 if 到 switch 的完整指南
开发语言·ssh·swift·switch·条件语句·guard·if
吴可可1233 小时前
ActiveX调用WScript.Shell原理揭秘
开发语言
传奇开心果编程3 小时前
【Flutter踩坑排雷】第28课:平台目录缺失与修复坑|`flutter create` 的“重建”与“覆盖”边界
android·flutter·ios·移动开发·跨平台·dart·声明式ui
晴天的雨.9924 小时前
【C++】继承篇
java·开发语言·c++
SomeOtherTime4 小时前
第 1 讲:内存布局与所有权解剖——栈帧、胖指针与“移动/拷贝”在汇编层面的真实面目
java·开发语言·汇编
总要学点什么5 小时前
第106篇:三维特效-流动线效果——让一颗光点沿整条线一路滚到头
开发语言·javascript·ecmascript·gis·webgl·材质·cesium