【问题标题】:Custom QML module deployment to Android: QML dependencies missing自定义 QML 模块部署到 Android:缺少 QML 依赖项
【发布时间】:2016-05-22 09:35:40
【问题描述】:

我正在开发一个包含一些特殊类型的自定义 QML 模块(我们称之为 MyModule)。它被用作其他应用程序项目的预编译库(即源代码对他们不可用,它通过 import MyModule 1.0 使用,设置必要的导入路径等)。该模块包含基于 C++ 的 QML 类型以及自身导入 QtQuick 模块(如 QtQuick.Controls 和 QtQuick.Window)的 QML 文件。

当我尝试将使用 MyModule 开发的应用程序部署和执行到 Android 时,MyModule 的依赖项不会被 androiddeployqt/qmlimportscanner 拾取并包含在 APK 中,这会导致如下消息:module "QtQuick.Controls" is not installed

有没有办法让这些 QML 依赖项包含在 APK 中,而不必在应用程序源目录中创建一个包含所有导入的虚拟 qml 文件,这样它们就可以被 qmlimportscanner 拾取?

【问题讨论】:

    标签: android qt deployment qml


    【解决方案1】:

    您可以将模块MyModule 放置在使用MyModule 的Android 应用程序的基目录下的任何位置。例如放入文件夹./my-module./lib/my-module

    工作原理

    在运行 qmake / CMake 时,qmlimportscanner 将在包含项目定义文件的文件夹上运行。对于基于 qmake 的项目是 .pro 文件,对于基于 CMake 的项目是 CMakeLists.txt 文件。它将在此目录和任何子目录中查找所有 *.qml 文件,并将它们的 QML 依赖项包含到 Android APK 包中。至少这是observedqmlimportscanner 的行为。

    您仍然可以在不同的 Git 存储库中管理您的 QML 模块 MyModule 和您的 Android 应用程序。只需确保 .gitignore Android 应用程序中 ./lib/ 文件夹的内容即可。 (当然你也可以使用更复杂的方法,比如 Git 子模块。)

     

    替代解决方案

    这是我在网上找到的替代解决方案列表。它们要么不适用于我的情况,要么有一些缺点,但可能对您的情况有用。

    1。使用导入创建一个虚拟 QML 文件

    问题中也提到,这是the usual workaround

    解决方法是在项目目录中声明一个资源文件,其中包含一个包含必要导入的虚拟 qml 文件。

    更多细节与示例,来自here

    我在 .pro 文件所在的目录中创建了一个简单的 .qml 文件。然后我只添加了在其他文件夹中的所有 .qml 文件中使用的导入行。由于这会导致语法投诉,我还在最后一个导入行之后添加了文本 Page {}。

    import QtQuick 2.9
    import QtQuick.Layouts 1.3
    import QtQuick.Controls 2.4
    # [...]
    
    Page { }
    

    请注意,.pro 文件中没有引用此文件,当然它根本不是项目/应用程序的一部分。它的存在只是为了qmlimportscanner 包含正确的模块。

    2。使用 Qt 5.14 并在 .qrc 文件中列出 QML 文件

    Sine Qt 5.14,这是该问题的官方解决方案,跟踪为QTBUG-55259。有关详细信息,请参见那里。现在,qmlimportscanner 会将项目的.qrc 文件中列出的所有 QML 文件视为可用于导入语句。因此,如果您的项目在 QML 文件中显示 import MyModule.Something,它将起作用,因为现在可以解析该导入。

    但是,如果您的模块 MyModule 位于项目的源代码树之外,并且它本身导入了一个未由您的 Android 应用程序导入的 QML 模块 ExternalModule,则该导入仍然会失败。 (我希望我理解了这一点,因为我自己没有测试过。)

    3。从项目源代码树符号链接你的模块目录

    Somebody reported 在 2018 年底,qmlimportscanner 在查找包含 import 语句的 QML 文件时,将遵循从项目源树到外部树的符号链接。

    我试过了,但无法确认这种行为。

    4。多路径调用qmlimportscanner

    qmlimportscanner 能够考虑多个根路径(扫描导入其他 QML 文件的 QML 文件的位置)和导入路径(解析这些导入的位置),如下所示:

    qmlimportscanner -rootPath dir1 -rootPath dir2 -importPath dir3 -importPath dir4
    

    但是,根据QTBUG-75187androiddeployqt 目前未使用此功能。因此,无论如何,如果您使用 Android 的替代构建系统,您只能使用它。 ECM build system 在内部也调用 androiddeployqt。也许qt-android-cmake 可以提供帮助。

    5。从 qmake / CMake 调用 qml_import_qml_plugins()

    从 Qt 5.14 开始,您可以从您的 qmake / CMake 文件中调用 qmlimportscanner。不过,它只对静态 Qt 构建有用:

    在配置时运行 qmlimportscanner 以查找使用的静态 QML 插件并将它们链接到给定目标。

    注意:当与非静态 Qt 构建一起使用时,此函数不执行任何操作。

    (source)

    乍一看,似乎没有办法将多个位置交给它来查找 QML 依赖项,因此与当前情况相比,它可能不会有任何改进。但我还没有详细探讨。

    【讨论】:

      【解决方案2】:

      您可以尝试将depends 关键字添加到您的qmldir 文件中:

      声明这个模块依赖于另一个。

      例子:

      depends MyOtherModule 1.0

      只有在依赖项被隐藏的情况下才需要此声明:例如,当一个模块的 C++ 代码用于加载 QML(可能是有条件的)然后依赖于其他模块时。在这种情况下,需要依赖声明才能将其他模块包含在应用程序包中。

      要获得一些灵感,请查看以下内容:

      http://code.qt.io/cgit/qt/qtquickcontrols2.git/tree/src/imports/controls/qmldir

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-10-14
        • 2015-12-03
        • 1970-01-01
        • 2010-09-13
        • 1970-01-01
        • 2021-12-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多