【问题标题】:How to deploy qt5 qml plugin to android?如何将qt5 qml插件部署到android?
【发布时间】:2013-08-20 23:16:59
【问题描述】:

我正在尝试从 Qt 5.1.0 android 安装中导入 TimeExample Qt Quick Extension Plugin。

libqmlqtimeexampleplugin.sobuild-plugins-Android_for_arm_GCC_4_6_Qt_5_1_0-Debug/imports中成功构建

然后我从 Qt Creator 创建了简单的 Qt Quick2 应用程序(内置元素)。我应该在应用程序项目文件中添加什么以在输出“.apk”包中获取 QML 插件?

现在它说:

W/Qt (23528): assets:/qml/TimeExampleTest/main.qml:2 (): assets:/qml/TimeExampleTest/main.qml:2:1: 模块“TimeExample”未安装

main.qml

 import QtQuick 2.0

 import TimeExample 1.0 // import types from the plugin

 Rectangle {
    width: 360
    height: 360
    Text {
        text: qsTr("Hello World")
        anchors.centerIn: parent
    }
    MouseArea {
       anchors.fill: parent
        onClicked: {
          Qt.quit();
       }
    }

   Clock { // this class is defined in QML (imports/TimeExample/Clock.qml)

        Time { // this class is defined in C++ (plugin.cpp)
            id: time
      }

        hours: time.hour
      minutes: time.minute

    }
}

TimeExampleTest.pro

folder_01.source = qml/TimeExampleTest

 folder_01.target = qml

 folder_02.source = /home/artem/Projects/Veedo/Test/build-plugins-Android_for_arm_GCC_4_6_Qt_5_1_0-Debug/imports/TimeExample

 folder_02.target = imports

 DEPLOYMENTFOLDERS = folder_01 folder_02

 QML_IMPORT_PATH = /home/artem/Projects/Veedo/Test/build-plugins-Android_for_arm_GCC_4_6_Qt_5_1_0-Debug/imports/TimeExample

 SOURCES += main.cpp

 include(qtquick2applicationviewer/qtquick2applicationviewer.pri)

 qtcAddDeployment()

 OTHER_FILES += \
    android/src/org/kde/necessitas/ministro/IMinistro.aidl \
    android/src/org/kde/necessitas/ministro/IMinistroCallback.aidl \
    android/src/org/qtproject/qt5/android/bindings/QtActivity.java \
    android/src/org/qtproject/qt5/android/bindings/QtApplication.java \
    android/AndroidManifest.xml \
    android/version.xml \
    android/res/values-ja/strings.xml \
    android/res/values-rs/strings.xml \
    android/res/values-zh-rTW/strings.xml \
    android/res/values-fa/strings.xml \
    android/res/values-ru/strings.xml \
    android/res/values-fr/strings.xml \
    android/res/values-ro/strings.xml \
    android/res/values-el/strings.xml \
    android/res/values-ms/strings.xml \
    android/res/values-nb/strings.xml \
    android/res/values-et/strings.xml \
    android/res/values-pl/strings.xml \
    android/res/values-pt-rBR/strings.xml \
    android/res/values-es/strings.xml \
    android/res/values-id/strings.xml \
    android/res/values-de/strings.xml \
    android/res/values-it/strings.xml \
    android/res/values-zh-rCN/strings.xml \
    android/res/values/strings.xml \
    android/res/values/libs.xml \
    android/res/layout/splash.xml \
    android/res/values-nl/strings.xml

【问题讨论】:

    标签: android qml qt5


    【解决方案1】:

    在 Qt 5.3 中,我们仅通过将插件部署到官方 Qt QML 模块所在的 QT_INSTALL_QML 目录就设法让 Qt Android 应用程序识别我们的 QML 插件。在我们的例子中,这个目录是 /opt/Qt/5.3/android_armv7/qml。

    插件端

    我们的插件.pro 文件如下所示:

    TEMPLATE = lib
    TARGET = prova
    QT += qml quick multimedia
    CONFIG += qt plugin c++11 console
    CONFIG -= android_install
    TARGET = $$qtLibraryTarget($$TARGET)
    uri = com.mycompany.qmlcomponents
    
    # Input
    SOURCES += \
        src1.cpp \
        src2.cpp
    
    HEADERS += \
        src1.h \
        src2.h
    
    ##The below is generated automatically by Qt Creator when you create a new "Qt Quick 2 Extension Plugin" project for Android
    
    #Copies the qmldir file to the build directory
    !equals(_PRO_FILE_PWD_, $$OUT_PWD) {
        copy_qmldir.target = $$OUT_PWD/qmldir
        copy_qmldir.depends = $$_PRO_FILE_PWD_/qmldir
        copy_qmldir.commands = $(COPY_FILE) \"$$replace(copy_qmldir.depends, /, $$QMAKE_DIR_SEP)\" \"$$replace(copy_qmldir.target, /, $$QMAKE_DIR_SEP)\"
        QMAKE_EXTRA_TARGETS += copy_qmldir
        PRE_TARGETDEPS += $$copy_qmldir.target
    }
    
    #Copies the qmldir file and the built plugin .so to the QT_INSTALL_QML directory
    qmldir.files = qmldir
    unix {
        installPath = $$[QT_INSTALL_QML]/$$replace(uri, \\., /)
        qmldir.path = $$installPath
        target.path = $$installPath
        INSTALLS += target qmldir
    }
    

    我们的qmldir(在插件源码树根目录)文件是:

    module com.mycompany.qmlcomponents
    plugin prova
    

    应用端

    .pro 文件如下所示:

    TEMPLATE = app
    
    QT += qml quick widgets multimedia
    
    CONFIG+= console
    SOURCES += main.cpp
    
    RESOURCES += qml.qrc
    
    # Additional import path used to resolve QML modules in Qt Creator's code model
    QML_IMPORT_PATH =
    # Default rules for deployment.
    include(deployment.pri)
    
    contains(ANDROID_TARGET_ARCH,armeabi-v7a) {
        ANDROID_EXTRA_LIBS = \
            /opt/Qt/5.3/android_armv7/qml/com/mycompany/qmlcomponents/libprova.so
    }
    

    我们实际上并不知道是否需要包含额外的 libprova.so。很可能不是。

    main.cpp 看起来像:

    #include <QApplication>
    #include <QQmlApplicationEngine>
    int main(int argc, char *argv[]){
        QApplication app(argc, argv);
        QQmlApplicationEngine engine;
        engine.load(QUrl(QStringLiteral("qrc:///main.qml")));
        return app.exec();
    }
    

    main.qml 只包含如下插件:

    import QtQuick 2.2
    import QtQuick.Controls 1.1
    import QtMultimedia 5.0
    
    import com.mycompany.qmlcomponents 1.0
    
    ...
    

    构建和部署

    我们构建和部署插件的方式是到qmake(来自Qt的android-armv7工具链),然后是make install。它将 qmldir 文件和插件 .so 安装到 QT_INSTALL_QML 目录。

    我们构建和部署使用插件的项目的方式是到qmake(同样来自Qt的android-armv7工具链),然后make install INSTALL_ROOT=.(安装到构建目录),然后运行androiddeployqt。最后一个命令使用 assets/ 中的 qmldirs 和 libs/ 中的库创建 Android 项目结构,并通过 ant 将整个东西捆绑在 apk 中。有关此过程的详细信息,请参阅http://qt-project.org/wiki/Android

    简而言之,我们只能通过将 QML 插件放在私有 Qt qml 目录中来让我们的 QML 插件在 Android 项目中被识别。

    【讨论】:

    • 有趣,但是 iirc 有一个更直接的方法,如果你有兴趣,我可以挖掘/尝试一些代码。
    • 我很感兴趣@mlvljr !
    • @user981733 好的,让我在接下来的几天里看看这个:)
    【解决方案2】:

    在阅读了Qt关于QAbstractFileEngineHandler的源码后,我发现Qt中有一些丑陋的东西:

    1. Qt 确实实现了某种机制来提供“搜索路径”(不是 URL),例如“qrc:”、“assets:”,其中内核是 QAbstractFileEngineHandler。

    2. QAbstractFileEngineHandler 在 Qt5 中不再公开,它只为 QFile、QFileInfo、QDir、QIcon 以及 QFile 提供的东西提供抽象,包括 QImage,以及专门用于 Android 资产的 QAndroidAssetsFileEngineHandler。

    3. 1234563 /li>
    4. 您可以在 Qt 的文档中的[static] void QDir::setSearchPaths(const QString &amp;prefix, const QStringList &amp;searchPaths) 下方找到此内容:

      QDir::setSearchPaths("icons", QStringList(QDir::homePath() + "/images"));
      QDir::setSearchPaths("docs", QStringList(":/embeddedDocuments"));
      
      ...    
      QPixmap pixmap("icons:undo.png"); // will look for undo.png in QDir::homePath() + "/images"    
      QFile file("docs:design.odf"); // will look in the :/embeddedDocuments resource path
      

      你会发现这个 sn-p 不起作用,因为 QPixmap 没有从 QAbstractFileEngineHandler 加载图像,这可能是 Qt 未记录的更改。另一方面,关于搜索路径的 QtCore 单元测试仅在 QFile 上进行了测试

    此外,void addResourceSearchPath(const QString &amp;path) 已过时,但 setSearchPath 有缺陷,我对此感到很困惑。也许我现在应该看看 QUrl :)

    【讨论】:

      【解决方案3】:

      这就是我完成这项工作的方法。

      将此添加到您的应用程序代码中:

      QQuickView *m_view;
      m_view->engine()->addImportPath("assets:/");
      m_view->engine()->addPluginPath(QCoreApplication::applicationDirPath());
      

      “assets:”后面的斜杠很重要,没有它就行不通。 在您的构建文件夹中,您需要具有如下目录结构:/home/my_name/project_build_directory/qml/my_plugin。你的插件目录应该有你的.so 库和qmldir 文件。 然后你需要把插件打包。这应该可以通过将以下内容添加到您的 .pro 文件中来实现:

      ANDROID_EXTRA_PLUGINS += /full/path/to/your/plugin/folder
      

      但是,这对我使用 Qt 5.11 的 Qt Creator 不起作用,所以我必须手动将其添加到 .json 部署文件:

      "android-extra-plugins":"/full/path/to/your/plugin",
      

      构建变量可能适用于早期版本的 Qt Creator。 如果您的插件具有 Qt 依赖项,它们将不会被 androiddeployqt 拾取,您必须手动添加它们。这可以通过向 .pro 文件添加构建变量来完成:

      ANDROID_EXTRA_LIBS += /your/qt/path/lib/libQt5Xml.so
      ... etc
      

      或者如果这不起作用,您必须手动将其添加到 JSON 构建文件中:

      "android-extra-libs":"/your/qt/path/lib/libQt5Xml.so,/your/qt/path/lib/libQt5Network.so",
      ...etc
      

      这个过程很混乱,在对构建进行一些更改时会自动重新生成 JSON 文件,因此必须再次将更改粘贴到该文件中。如果有人知道如何改进该过程,将不胜感激。你应该在你的 android 设备上最终得到的是,你的插件 .so 最终将位于所有 .so 库所在的同一目录中,而你的 qmldir 最终将位于 assets:/your_plugin_name/qmldir 中。

      【讨论】:

        猜你喜欢
        • 2015-10-20
        • 1970-01-01
        • 2015-12-03
        • 2014-08-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多