4

注意我不是QtCreator 用户。我使用 qmake、make 和 androiddeployqt 在构建脚本中构建 android 应用程序,并使用 adb install 将它们部署到设备上。

我希望能够在 abd logcat 输出中看到 qDebug、qInfo 等的输出,以及来自 QML 引擎的任何 qml conole.log 输出和任何其他喋喋不休。但在 Android 的 Qt 应用程序的香草版本中,任何此类消息似乎都是黑洞(或者至少我不知道它们要去哪里)。

我通过以下组合取得了一些成功:

  • 使用qInstallMessageHandler将日志重定向到 stderr (如此所示)。

  • 使用此处的代码将 stderr 重定向到 Android 日志记录。(更新:后来发现这种方法相当不令人满意,因为它依赖于另一个线程在管道上侦听,并且崩溃的应用程序可能会在崩溃之前立即丢失日志记录)。

但这一切似乎有点笨拙和过于复杂。肯定有更好更简单的方法吗?(例如,使用 Windows 上的 Qt,您可以简单地构建CONFIG += console以获取显示日志记录的控制台窗口,但该选项是特定于 Windows 的)。

感兴趣的 Qt 版本从 5.7 开始。

谷歌搜索这个输出重定向问题出现了很多提及adb shell setprop log.redirect-stdio true,但据我所知,它对 Qt 应用程序的 stout/stderr 没有影响。

4

1 回答 1

1

实际上,结合问题中链接的两个解决方案的各个方面至少将其简化为一个功能:

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);
  ...

这会获取诸如qInfo() <<来自 C++ console.log消息和来自 QML 的消息之类的东西。它没有得到 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 是否也这样做了;但如果它发出任何东西,它必须在我的处理程序安装之前发出)。

于 2017-08-02T11:49:21.453 回答