我正在尝试从Qt 5.1.0安卓安装中导入TimeExample Qt快速扩展插件。
在build-plugins-Android_for_arm_GCC_4_6_Qt_5_1_0-Debug/imports
中成功构建了libqmlqtimeexampleplugin.so
然后我从Qt Creator创建了一个简单的Qt Quick2应用程序(内置元素)。我应该向应用程序项目文件添加什么才能在输出".apk"包中获得QML插件?
现在它说:
W/Qt(23528):assets:/qml/TimeExampleTest/main.qml:2():assets:/qml/TimeoutExampleTest-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
使用Qt 5.3,我们仅通过将插件部署到官方Qt QML模块所在的Qt_INSTALL_QML目录,就成功地让我们的QML插件被Qt Android应用程序识别。在我们的例子中,这个目录是/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
应用程序端
.pr文件看起来像:
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/中的qmldir和libs/中的库创建Android项目结构,并通过ant
将整个内容捆绑在apk中。有关此步骤的详细信息,请参阅http://qt-project.org/wiki/Android.
简而言之,我们只能通过将QML插件放在专用Qt-QML目录中,才能在Android项目中识别QML插件。
在阅读了Qt关于QAbstractFileEngineHandler的源代码后,我在Qt:中发现了一些丑陋的东西
-
Qt确实实现了某种机制来提供"searchpath"(而不是URL),如"qrc:"、"assets:",其中内核是QAbstractFileEngineHandler。
-
QAbstractFileEngineHandler在Qt5中不再公开,它只提供对QFile、QFileInfo、QDir、QIcon以及QFile提供的东西的抽象,包括QImage,以及专门用于Android资产的QAndroidAssetsFileEngineHandler。
-
因此,SearchPath模式与QUrl不兼容,即使它们看起来非常相似,正如您所知,QtQuick将Source设置为某个URL,因此qml文件不会直接以"assets:"前缀加载。
-
您可以在Qt的文档中的
[static] void QDir::setSearchPaths(const QString &prefix, const QStringList &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
你会发现这个片段不起作用,因为QPixmap没有从QAbstractFileEngineHandler加载图像,这可能是Qt的未记录更改。另一方面,关于searchpath的QtCore单元测试仅在QFile 上测试
此外,void addResourceSearchPath(const QString &path)
已经过时,但是setSearchPath有缺陷,我对此感到非常困惑。也许我现在应该看看QUrl:)
以下是我如何做到这一点的。
将此添加到您的应用程序代码中:
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
中。