在 adb logcat 输出中查看 Qt 应用程序在 Android 上的日志记录的最简单方法是什么?
What's the simplest way to see logging from a Qt app on Android in adb logcat output?
注意我不是 QtCreator 用户。我使用 qmake、make 和 androiddeployqt 在构建脚本中构建 android 应用程序,并使用 adb install 将它们部署到设备。
我希望能够在 abd logcat 输出中看到 qDebug、qInfo 等的输出,以及任何 qml conole.log 输出和来自 QML 引擎的任何其他信息。但是在 Android 的 Qt 应用程序的香草版本中,任何此类消息似乎都是黑洞(或者至少我不知道它们要去哪里)。
我通过以下组合取得了一些成功:
使用 qInstallMessageHandler (as shown here).
将日志记录重定向到 stderr
使用代码 here 将 stderr 重定向到 Android 日志记录。 (更新:随后发现这种方法并不令人满意,因为它依赖于另一个线程监听管道,崩溃的应用程序可能会在崩溃前立即丢失日志记录)。
但这一切似乎有点笨拙和过于复杂。当然有更好更简单的方法吗? (例如,在 Windows 上使用 Qt,您可以简单地使用 CONFIG += console
进行构建以获得显示日志记录的控制台 window,但该选项是 Windows 特定的)。
感兴趣的 Qt 版本从 5.7 开始。
用谷歌搜索这个输出重定向问题,发现很多人提到 adb shell setprop log.redirect-stdio true
,但据我所知,它对 Qt 应用程序的 stout/stderr.
没有影响
实际上,结合问题中链接的两个解决方案的各个方面至少将其简化为一个功能:
const char*const applicationName="myapp";
#ifdef ANDROIDQUIRKS // Set in my myapp.pro file for android builds
#include <android/log.h>
void myMessageHandler(
QtMsgType type,
const QMessageLogContext& context,
const QString& msg
) {
QString report=msg;
if (context.file && !QString(context.file).isEmpty()) {
report+=" in file ";
report+=QString(context.file);
report+=" line ";
report+=QString::number(context.line);
}
if (context.function && !QString(context.function).isEmpty()) {
report+=+" function ";
report+=QString(context.function);
}
const char*const local=report.toLocal8Bit().constData();
switch (type) {
case QtDebugMsg:
__android_log_write(ANDROID_LOG_DEBUG,applicationName,local);
break;
case QtInfoMsg:
__android_log_write(ANDROID_LOG_INFO,applicationName,local);
break;
case QtWarningMsg:
__android_log_write(ANDROID_LOG_WARN,applicationName,local);
break;
case QtCriticalMsg:
__android_log_write(ANDROID_LOG_ERROR,applicationName,local);
break;
case QtFatalMsg:
default:
__android_log_write(ANDROID_LOG_FATAL,applicationName,local);
abort();
}
}
#endif
...
int main(int argc,char* argv[]) {
QGuiApplication app(argc,argv);
#ifdef ANDROIDQUIRKS
qInstallMessageHandler(myMessageHandler);
#endif
app.setApplicationName(applicationName);
...
这会从 C++ 中获取 qInfo() <<
消息 和从 QML 中获取 console.log
消息。它没有得到的是 stdout/stderr 输出,但是对于可以在整个过程中使用 Qt 日志记录的新代码,我可以接受它。
在logcat中,QML代码Component.onCompleted: console.log("QML completed")
导致
08-02 12:27:53.378 1199 1220 D myapp : QML completed in file qrc:///main.qml line 7 function onCompleted
在 C++ 中,代码 qInfo() << "QQuickViewer setup completed";
生成
08-02 12:27:53.562 1199 1220 I myapp : QQuickViewer setup completed
甚至在实例化 QGuiApplication 之前安装消息处理程序似乎同样有效,但它不会生成任何额外的输出(我注意到 iOS 上的 Qt 在启动时向 xcode 控制台,例如链接到 https://wiki.qt.io/V4 的性能警告,想知道 Android 是否也这样做;但如果它发出任何东西,它必须在我的处理程序安装之前发出)。
注意我不是 QtCreator 用户。我使用 qmake、make 和 androiddeployqt 在构建脚本中构建 android 应用程序,并使用 adb install 将它们部署到设备。
我希望能够在 abd logcat 输出中看到 qDebug、qInfo 等的输出,以及任何 qml conole.log 输出和来自 QML 引擎的任何其他信息。但是在 Android 的 Qt 应用程序的香草版本中,任何此类消息似乎都是黑洞(或者至少我不知道它们要去哪里)。
我通过以下组合取得了一些成功:
使用 qInstallMessageHandler (as shown here).
将日志记录重定向到 stderr
使用代码 here 将 stderr 重定向到 Android 日志记录。 (更新:随后发现这种方法并不令人满意,因为它依赖于另一个线程监听管道,崩溃的应用程序可能会在崩溃前立即丢失日志记录)。
但这一切似乎有点笨拙和过于复杂。当然有更好更简单的方法吗? (例如,在 Windows 上使用 Qt,您可以简单地使用 CONFIG += console
进行构建以获得显示日志记录的控制台 window,但该选项是 Windows 特定的)。
感兴趣的 Qt 版本从 5.7 开始。
用谷歌搜索这个输出重定向问题,发现很多人提到 adb shell setprop log.redirect-stdio true
,但据我所知,它对 Qt 应用程序的 stout/stderr.
实际上,结合问题中链接的两个解决方案的各个方面至少将其简化为一个功能:
const char*const applicationName="myapp";
#ifdef ANDROIDQUIRKS // Set in my myapp.pro file for android builds
#include <android/log.h>
void myMessageHandler(
QtMsgType type,
const QMessageLogContext& context,
const QString& msg
) {
QString report=msg;
if (context.file && !QString(context.file).isEmpty()) {
report+=" in file ";
report+=QString(context.file);
report+=" line ";
report+=QString::number(context.line);
}
if (context.function && !QString(context.function).isEmpty()) {
report+=+" function ";
report+=QString(context.function);
}
const char*const local=report.toLocal8Bit().constData();
switch (type) {
case QtDebugMsg:
__android_log_write(ANDROID_LOG_DEBUG,applicationName,local);
break;
case QtInfoMsg:
__android_log_write(ANDROID_LOG_INFO,applicationName,local);
break;
case QtWarningMsg:
__android_log_write(ANDROID_LOG_WARN,applicationName,local);
break;
case QtCriticalMsg:
__android_log_write(ANDROID_LOG_ERROR,applicationName,local);
break;
case QtFatalMsg:
default:
__android_log_write(ANDROID_LOG_FATAL,applicationName,local);
abort();
}
}
#endif
...
int main(int argc,char* argv[]) {
QGuiApplication app(argc,argv);
#ifdef ANDROIDQUIRKS
qInstallMessageHandler(myMessageHandler);
#endif
app.setApplicationName(applicationName);
...
这会从 C++ 中获取 qInfo() <<
消息 和从 QML 中获取 console.log
消息。它没有得到的是 stdout/stderr 输出,但是对于可以在整个过程中使用 Qt 日志记录的新代码,我可以接受它。
在logcat中,QML代码Component.onCompleted: console.log("QML completed")
导致
08-02 12:27:53.378 1199 1220 D myapp : QML completed in file qrc:///main.qml line 7 function onCompleted
在 C++ 中,代码 qInfo() << "QQuickViewer setup completed";
生成
08-02 12:27:53.562 1199 1220 I myapp : QQuickViewer setup completed
甚至在实例化 QGuiApplication 之前安装消息处理程序似乎同样有效,但它不会生成任何额外的输出(我注意到 iOS 上的 Qt 在启动时向 xcode 控制台,例如链接到 https://wiki.qt.io/V4 的性能警告,想知道 Android 是否也这样做;但如果它发出任何东西,它必须在我的处理程序安装之前发出)。