2013-08-19 10 views
9

Sto cercando di importare TimeExample Qt Quick Extension Plugin dall'installazione di Qt 5.1.0 per Android.Come distribuire il plugin qt5 qml su Android?

libqmlqtimeexampleplugin.so è costruito con successo in build-plugins-Android_for_arm_GCC_4_6_Qt_5_1_0-Debug/imports

Poi ho creato semplice Qt Quick2 Application (built-in Elementi) da Qt Creator. Cosa devo aggiungere al file di progetto dell'applicazione per ottenere il plugin QML nel pacchetto di output ".apk"?

Ora dice:

W/Qt (23528): beni: /qml/TimeExampleTest/main.qml: 2(): beni: /qml/TimeExampleTest/main.qml: 2: 1 : modulo "TimeExample" non è installato

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 

risposta

6

con Qt 5.3, siamo riusciti ad avere il nostro plugin QML riconosciuto da un'applicazione Qt Android solo distribuendo il plugin per la directory in cui i moduli ufficiali QT_INSTALL_QML Qt QML risiedono. Questa directory è /opt/Qt/5.3/android_armv7/qml nel nostro caso.

Plugin laterale

Il nostro file .pro per il plugin si presenta come:

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 
} 

nostra (nella radice dell'albero di origine plugin) di file qmldir è:

module com.mycompany.qmlcomponents 
plugin prova 

Application Lato

Il file .pro assomiglia:

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 
} 

Noi in realtà non sappiamo se l'inclusione della libprova.so supplementare è necessario. Probabilmente no.

Il main.cpp assomiglia:

#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(); 
} 

Il main.qml include solo il plugin come:

import QtQuick 2.2 
import QtQuick.Controls 1.1 
import QtMultimedia 5.0 

import com.mycompany.qmlcomponents 1.0 

... 

costruzione e distribuzione

Il nostro modo di creare e distribuire il plugin è quello di qmake (dalla toolchain android-ARMv7 di Qt), quindi make install. Si installa il file qmldir e il plugin .so nella directory QT_INSTALL_QML.

Il nostro modo di creare e distribuire il progetto che utilizza il plugin è quello di qmake (ancora una volta, dalla toolchain android-ARMv7 di Qt), quindi make install INSTALL_ROOT=. (installa per costruire directory), quindi eseguire androiddeployqt.L'ultimo comando crea la struttura del progetto Android con i qmldirs nelle risorse/e nelle librerie in libs/e raggruppa il tutto in un apk tramite ant. Per i dettagli di questa procedura, fare riferimento a http://qt-project.org/wiki/Android.

In breve, siamo stati in grado di riconoscere il nostro plugin QML solo all'interno di un progetto Android inserendolo nella directory Qt Qt privata.

+0

Interessante, ma se c'è un modo molto più diretto, potrei scavare/provare qualche codice se sei interessato. – mlvljr

+0

Sono interessato a @mlvljr! – user981733

+0

@ user981733 OK, lasciatemi esaminare questo nei seguenti giorni :) – mlvljr

0

Dopo aver letto la fonte di Qt su QAbstractFileEngineHandler, ho trovato qualcosa di brutto in Qt:

  1. Qt fa implementato un qualche tipo di meccanismo per fornire "SearchPath" (non URL) come "QRC:", "Attività: ", dove il kernel è QAbstractFileEngineHandler.

  2. QAbstractFileEngineHandler diventa non più pubblico nei QT5, si limita a fornire astratto qfile, QFileInfo, QDir, QIcon, e le cose forniti da qfile, tra cui QImage, più QAndroidAssetsFileEngineHandler, che è specializzato per le attività di Android.

  3. Quindi lo schema di SearchPath non è compatibile con QURL anche se sembrano così simili, come sai QtQuick è setSource su qualche URL, quindi un file qml non verrà caricato direttamente dal prefisso "assets:".

  4. È possibile trovare questo sotto [static] void QDir::setSearchPaths(const QString &prefix, const QStringList &searchPaths) nel documento di Qt:

    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 
    

    troverete questo frammento non funziona perché non è stato caricato QPixmap immagine da QAbstractFileEngineHandler, possa questa essere cambiamenti non documentati di Qt. D'altra parte, QtCore unit test su SearchPath testato solo su qfile

ulteriormente più, void addResourceSearchPath(const QString &path) è obsoleto, tuttavia SetSearchPath è difettoso, mi sento abbastanza confuso su questo. Forse dovrei dare un'occhiata a QUrl ora :)