From 91d48fe7270cf73e764764dd6ecd3ad6cacacf21 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Fri, 19 Apr 2013 12:27:58 +0200 Subject: [PATCH] Enable mechanism to bundle Qt in APK If the Qt version built against is Qt 5, and the deployment method is "Use libs on device" + "Use local Qt libs", Creator will copy the required files into the app bundle and set the necessary meta-data to make the Java code in the app actually load them from the app bundle. We also make this deployment method the default on Qt 5. Change-Id: Ib7a33e7d1fbd22f76c85c31e1dbc68912a38eda8 Reviewed-by: Daniel Teske Reviewed-by: Shawn Rutledge Reviewed-by: Eike Ziller --- src/plugins/android/androiddeploystep.cpp | 14 +- src/plugins/android/androidmanager.cpp | 90 ++++++-- src/plugins/android/androidmanager.h | 20 +- .../android/androidpackagecreationstep.cpp | 215 +++++++++++++++++- .../android/androidpackagecreationstep.h | 15 ++ .../android/androidpackagecreationwidget.cpp | 16 +- 6 files changed, 330 insertions(+), 40 deletions(-) diff --git a/src/plugins/android/androiddeploystep.cpp b/src/plugins/android/androiddeploystep.cpp index 0eba7056726..ebb4337a93c 100644 --- a/src/plugins/android/androiddeploystep.cpp +++ b/src/plugins/android/androiddeploystep.cpp @@ -82,7 +82,11 @@ void AndroidDeployStep::ctor() //: AndroidDeployStep default display name setDefaultDisplayName(tr("Deploy to Android device")); m_deployAction = NoDeploy; + m_useLocalQtLibs = false; + if (QtSupport::BaseQtVersion *qt = QtSupport::QtKitInformation::qtVersion(target()->kit())) + if (qt->qtVersion() >= QtSupport::QtVersionNumber(5, 0, 0)) + m_useLocalQtLibs = true; } bool AndroidDeployStep::init() @@ -197,22 +201,20 @@ void AndroidDeployStep::cleanLibsFinished() void AndroidDeployStep::setDeployAction(AndroidDeployStep::AndroidDeployAction deploy) { m_deployAction = deploy; + + AndroidManager::updateDeploymentSettings(target()); } void AndroidDeployStep::setDeployQASIPackagePath(const QString &package) { m_QASIPackagePath = package; - m_deployAction = InstallQASI; + setDeployAction(InstallQASI); } void AndroidDeployStep::setUseLocalQtLibs(bool useLocal) { m_useLocalQtLibs = useLocal; - - // ### Passes -1 for API level, which means it won't work with setups that require - // library selection based on API level. Use the old approach (command line argument) - // in these cases. - AndroidManager::setUseLocalLibs(target(), useLocal, -1); + AndroidManager::updateDeploymentSettings(target()); } bool AndroidDeployStep::runCommand(QProcess *buildProc, diff --git a/src/plugins/android/androidmanager.cpp b/src/plugins/android/androidmanager.cpp index e8b3694d312..29ff4ed09bd 100644 --- a/src/plugins/android/androidmanager.cpp +++ b/src/plugins/android/androidmanager.cpp @@ -62,6 +62,7 @@ namespace { const QLatin1String AndroidLibsFileName("/res/values/libs.xml"); const QLatin1String AndroidStringsFileName("/res/values/strings.xml"); const QLatin1String AndroidDefaultPropertiesName("project.properties"); + const QLatin1String AndroidLibraryPrefix("--Managed_by_Qt_Creator--"); QString cleanPackageName(QString packageName) { @@ -373,7 +374,20 @@ QString AndroidManager::targetApplication(ProjectExplorer::Target *target) return QString(); } -bool AndroidManager::setUseLocalLibs(ProjectExplorer::Target *target, bool useLocalLibs, int deviceAPILevel) +bool AndroidManager::bundleQt(ProjectExplorer::Target *target) +{ + ProjectExplorer::RunConfiguration *runConfiguration = target->activeRunConfiguration(); + AndroidRunConfiguration *androidRunConfiguration = qobject_cast(runConfiguration); + if (androidRunConfiguration != 0) { + AndroidDeployStep *deployStep = androidRunConfiguration->deployStep(); + return deployStep->deployAction() == AndroidDeployStep::NoDeploy + && deployStep->useLocalQtLibs(); + } + + return false; +} + +bool AndroidManager::updateDeploymentSettings(ProjectExplorer::Target *target) { // For Qt 4, the "use local libs" options is handled by passing command line arguments to the // app, so no need to alter the AndroidManifest.xml @@ -381,19 +395,32 @@ bool AndroidManager::setUseLocalLibs(ProjectExplorer::Target *target, bool useLo if (baseQtVersion == 0 || baseQtVersion->qtVersion() < QtSupport::QtVersionNumber(5,0,0)) return true; + ProjectExplorer::RunConfiguration *runConfiguration = target->activeRunConfiguration(); + AndroidRunConfiguration *androidRunConfiguration = qobject_cast(runConfiguration); + if (androidRunConfiguration == 0) + return false; + + AndroidDeployStep *deployStep = androidRunConfiguration->deployStep(); + bool useLocalLibs = deployStep->useLocalQtLibs(); + bool deployQtLibs = deployStep->deployAction() != AndroidDeployStep::NoDeploy; + bool bundleQtLibs = useLocalLibs && !deployQtLibs; + QDomDocument doc; if (!openManifest(target, doc)) return false; QDomElement metadataElem = doc.documentElement().firstChildElement(QLatin1String("application")).firstChildElement(QLatin1String("activity")).firstChildElement(QLatin1String("meta-data")); + // ### Passes -1 for API level, which means it won't work with setups that require + // library selection based on API level. Use the old approach (command line argument) + // in these cases. Hence the Qt version > 4 condition at the beginning of this function. QString localLibs; QString localJars; QString staticInitClasses; if (useLocalLibs) { - localLibs = loadLocalLibs(target, deviceAPILevel); - localJars = loadLocalJars(target, deviceAPILevel); - staticInitClasses = loadLocalJarsInitClasses(target, deviceAPILevel); + localLibs = loadLocalLibs(target, -1); + localJars = loadLocalJars(target, -1); + staticInitClasses = loadLocalJarsInitClasses(target, -1); } bool changedManifest = false; @@ -418,6 +445,11 @@ bool AndroidManager::setUseLocalLibs(ProjectExplorer::Target *target, bool useLo metadataElem.setAttribute(QLatin1String("android:value"), staticInitClasses); changedManifest = true; } + } else if (metadataElem.attribute(QLatin1String("android:name")) == QLatin1String("android.app.bundle_local_qt_libs")) { + if (metadataElem.attribute(QLatin1String("android:value")).toInt() != bundleQtLibs) { + metadataElem.setAttribute(QLatin1String("android:value"), int(bundleQtLibs)); + changedManifest = true; + } } metadataElem = metadataElem.nextSiblingElement(QLatin1String("meta-data")); @@ -653,14 +685,21 @@ QString AndroidManager::loadLocalLibs(ProjectExplorer::Target *target, int apiLe return loadLocal(target, apiLevel, Lib); } +QString AndroidManager::loadLocalBundledFiles(ProjectExplorer::Target *target, int apiLevel) +{ + return loadLocal(target, apiLevel, BundledFile); +} + QString AndroidManager::loadLocalJars(ProjectExplorer::Target *target, int apiLevel) { - return loadLocal(target, apiLevel, Jar); + ItemType type = bundleQt(target) ? BundledJar : Jar; + return loadLocal(target, apiLevel, type); } QString AndroidManager::loadLocalJarsInitClasses(ProjectExplorer::Target *target, int apiLevel) { - return loadLocal(target, apiLevel, Jar, QLatin1String("initClass")); + ItemType type = bundleQt(target) ? BundledJar : Jar; + return loadLocal(target, apiLevel, type, QLatin1String("initClass")); } QVector AndroidManager::availableQtLibsWithDependencies(ProjectExplorer::Target *target) @@ -756,6 +795,16 @@ bool AndroidManager::setQtLibs(ProjectExplorer::Target *target, const QStringLis return setLibsXml(target, libs, QLatin1String("qt_libs")); } +bool AndroidManager::setBundledInAssets(ProjectExplorer::Target *target, const QStringList &fileList) +{ + return setLibsXml(target, fileList, QLatin1String("bundled_in_assets")); +} + +bool AndroidManager::setBundledInLib(ProjectExplorer::Target *target, const QStringList &fileList) +{ + return setLibsXml(target, fileList, QLatin1String("bundled_in_lib")); +} + QStringList AndroidManager::availablePrebundledLibs(ProjectExplorer::Target *target) { QStringList libs; @@ -799,7 +848,9 @@ QString AndroidManager::loadLocal(ProjectExplorer::Target *target, int apiLevel, QString itemType; if (item == Lib) itemType = QLatin1String("lib"); - else + else if (item == BundledFile) + itemType = QLatin1String("bundled"); + else // Jar or BundledJar itemType = QLatin1String("jar"); QString localLibs; @@ -841,16 +892,18 @@ QString AndroidManager::loadLocal(ProjectExplorer::Target *target, int apiLevel, if (libs.contains(element.attribute(QLatin1String("name")))) { QDomElement libElement = element.firstChildElement(QLatin1String("depends")).firstChildElement(itemType); while (!libElement.isNull()) { - if (libElement.hasAttribute(attribute)) { - QString dependencyLib = libElement.attribute(attribute).arg(apiLevel); - if (!dependencyLibs.contains(dependencyLib)) - dependencyLibs << dependencyLib; - } + if (libElement.attribute(QLatin1String("bundling")).toInt() == (item == BundledJar ? 1 : 0)) { + if (libElement.hasAttribute(attribute)) { + QString dependencyLib = libElement.attribute(attribute).arg(apiLevel); + if (!dependencyLibs.contains(dependencyLib)) + dependencyLibs << dependencyLib; + } - if (libElement.hasAttribute(QLatin1String("replaces"))) { - QString replacedLib = libElement.attribute(QLatin1String("replaces")).arg(apiLevel); - if (!replacedLibs.contains(replacedLib)) - replacedLibs << replacedLib; + if (libElement.hasAttribute(QLatin1String("replaces"))) { + QString replacedLib = libElement.attribute(QLatin1String("replaces")).arg(apiLevel); + if (!replacedLibs.contains(replacedLib)) + replacedLibs << replacedLib; + } } libElement = libElement.nextSiblingElement(itemType); @@ -1058,5 +1111,10 @@ QString AndroidManager::libGnuStl(const QString &arch, const QString &ndkToolCha + QLatin1String("/libgnustl_shared.so"); } +QString AndroidManager::libraryPrefix() +{ + return AndroidLibraryPrefix; +} + } // namespace Internal } // namespace Qt4ProjectManager diff --git a/src/plugins/android/androidmanager.h b/src/plugins/android/androidmanager.h index 1671108e997..3f47c3440da 100644 --- a/src/plugins/android/androidmanager.h +++ b/src/plugins/android/androidmanager.h @@ -85,7 +85,8 @@ public: static bool setTargetApplication(ProjectExplorer::Target *target, const QString &name); static QString targetApplicationPath(ProjectExplorer::Target *target); - static bool setUseLocalLibs(ProjectExplorer::Target *target, bool useLocalLibs, int deviceAPILevel); + static bool updateDeploymentSettings(ProjectExplorer::Target *target); + static bool bundleQt(ProjectExplorer::Target *target); static QString targetSDK(ProjectExplorer::Target *target); static bool setTargetSDK(ProjectExplorer::Target *target, const QString &sdk); @@ -103,9 +104,10 @@ public: const QString &name = QString()); static Utils::FileName localLibsRulesFilePath(ProjectExplorer::Target *target); - static QString loadLocalLibs(ProjectExplorer::Target *target, int apiLevel); - static QString loadLocalJars(ProjectExplorer::Target *target, int apiLevel); - static QString loadLocalJarsInitClasses(ProjectExplorer::Target *target, int apiLevel); + static QString loadLocalLibs(ProjectExplorer::Target *target, int apiLevel = -1); + static QString loadLocalJars(ProjectExplorer::Target *target, int apiLevel = -1); + static QString loadLocalBundledFiles(ProjectExplorer::Target *target, int apiLevel = -1); + static QString loadLocalJarsInitClasses(ProjectExplorer::Target *target, int apiLevel = -1); class Library { @@ -123,11 +125,17 @@ public: static QStringList qtLibs(ProjectExplorer::Target *target); static bool setQtLibs(ProjectExplorer::Target *target, const QStringList &libs); + static bool setBundledInLib(ProjectExplorer::Target *target, + const QStringList &fileList); + static bool setBundledInAssets(ProjectExplorer::Target *target, + const QStringList &fileList); + static QStringList availablePrebundledLibs(ProjectExplorer::Target *target); static QStringList prebundledLibs(ProjectExplorer::Target *target); static bool setPrebundledLibs(ProjectExplorer::Target *target, const QStringList &libs); static QString libGnuStl(const QString &arch, const QString &ndkToolChainVersion); + static QString libraryPrefix(); private: static void raiseError(const QString &reason); @@ -143,7 +151,9 @@ private: enum ItemType { Lib, - Jar + Jar, + BundledFile, + BundledJar }; static QString loadLocal(ProjectExplorer::Target *target, int apiLevel, ItemType item, const QString &attribute=QLatin1String("file")); diff --git a/src/plugins/android/androidpackagecreationstep.cpp b/src/plugins/android/androidpackagecreationstep.cpp index 1bc2da7712d..b38f5897dfc 100644 --- a/src/plugins/android/androidpackagecreationstep.cpp +++ b/src/plugins/android/androidpackagecreationstep.cpp @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -129,6 +130,7 @@ void AndroidPackageCreationStep::ctor() { setDefaultDisplayName(tr("Packaging for Android")); m_openPackageLocation = true; + m_bundleQt = false; connect(&m_outputParser, SIGNAL(addTask(ProjectExplorer::Task)), this, SIGNAL(addTask(ProjectExplorer::Task))); } @@ -314,6 +316,17 @@ void AndroidPackageCreationStep::initCheckRequiredLibrariesForRun() m_prebundledLibs = AndroidManager::prebundledLibs(target()); } +void AndroidPackageCreationStep::getBundleInformation() +{ + m_bundleQt = AndroidManager::bundleQt(target()); + if (m_bundleQt) { + m_bundledJars = AndroidManager::loadLocalJars(target()).split(QLatin1Char(':'), + QString::SkipEmptyParts); + m_otherBundledFiles = AndroidManager::loadLocalBundledFiles(target()).split(QLatin1Char(':'), + QString::SkipEmptyParts); + } +} + void AndroidPackageCreationStep::checkRequiredLibrariesForRun() { QProcess readelfProc; @@ -329,8 +342,11 @@ void AndroidPackageCreationStep::checkRequiredLibrariesForRun() QStringList libs; parseSharedLibs(readelfProc.readAll(), &libs); + m_qtLibsWithDependencies = requiredLibraries(m_availableQtLibs, m_qtLibs, libs); QMetaObject::invokeMethod(this, "setQtLibs",Qt::BlockingQueuedConnection, - Q_ARG(QStringList, requiredLibraries(m_availableQtLibs, m_qtLibs, libs))); + Q_ARG(QStringList, m_qtLibsWithDependencies)); + + QMetaObject::invokeMethod(this, "getBundleInformation"); QStringList prebundledLibraries; foreach (const AndroidManager::Library &qtLib, m_availableQtLibs) { @@ -429,6 +445,160 @@ QVariantMap AndroidPackageCreationStep::toMap() const return map; } +QStringList AndroidPackageCreationStep::collectRelativeFilePaths(const QString &parentPath) +{ + QStringList relativeFilePaths; + + QDirIterator libsIt(parentPath, QDir::NoFilter, QDirIterator::Subdirectories); + int pos = parentPath.size(); + while (libsIt.hasNext()) { + libsIt.next(); + if (!libsIt.fileInfo().isDir()) + relativeFilePaths.append(libsIt.filePath().mid(pos)); + } + + return relativeFilePaths; +} + +void AndroidPackageCreationStep::collectFiles(QList *deployList, + QList *pluginsAndImportsList) +{ + Q_ASSERT(deployList != 0); + QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(target()->kit()); + if (!version) + return; + + Qt4Project *project = static_cast(target()->project()); + QString androidTargetArch = project->rootQt4ProjectNode()->singleVariableValue(Qt4ProjectManager::AndroidArchVar); + + QString androidAssetsPath = m_androidDir.toString() + QLatin1String("/assets/"); + QString androidJarPath = m_androidDir.toString() + QLatin1String("/libs/"); + QString androidLibPath = m_androidDir.toString() + QLatin1String("/libs/") + androidTargetArch; + + QString qtVersionSourcePath = version->sourcePath().toString(); + + foreach (QString qtLib, m_qtLibsWithDependencies) { + QString fullPath = qtVersionSourcePath + + QLatin1String("/lib/lib") + + qtLib + + QLatin1String(".so"); + QString destinationPath = androidLibPath + + QLatin1String("/lib") + + qtLib + + QLatin1String(".so"); + + DeployItem deployItem(fullPath, 0, destinationPath, true); + deployList->append(deployItem); + } + + foreach (QString jar, m_bundledJars) { + QString fullPath = qtVersionSourcePath + QLatin1Char('/') + jar; + QFileInfo fileInfo(fullPath); + if (fileInfo.exists()) { + QString destinationPath = androidJarPath + + AndroidManager::libraryPrefix() + + fileInfo.fileName(); + deployList->append(DeployItem(fullPath, 0, destinationPath, true)); + } + } + + QSet alreadyListed; + foreach (QString bundledFile, m_otherBundledFiles) { + if (!bundledFile.endsWith(QLatin1Char('/'))) + bundledFile.append(QLatin1Char('/')); + + QStringList allFiles = collectRelativeFilePaths(qtVersionSourcePath + QLatin1Char('/') + bundledFile); + foreach (QString file, allFiles) { + QString fullPath = qtVersionSourcePath + QLatin1Char('/') + bundledFile + QLatin1Char('/') + file; + if (alreadyListed.contains(fullPath)) + continue; + + alreadyListed.insert(fullPath); + + QString garbledFileName; + QString destinationPath; + bool shouldStrip = false; + if (file.endsWith(QLatin1String(".so"))) { + garbledFileName = QLatin1String("lib") + + AndroidManager::libraryPrefix() + + QString(bundledFile).replace(QLatin1Char('/'), QLatin1Char('_')) + + QString(file).replace(QLatin1Char('/'), QLatin1Char('_')); + destinationPath = androidLibPath + QLatin1Char('/') + garbledFileName; + shouldStrip = true; + } else { + garbledFileName = AndroidManager::libraryPrefix() + bundledFile + file; + destinationPath = androidAssetsPath + garbledFileName; + } + + deployList->append(DeployItem(fullPath, 0, destinationPath, shouldStrip)); + pluginsAndImportsList->append(DeployItem(garbledFileName, + 0, + bundledFile + file, + shouldStrip)); + } + } +} + +void AndroidPackageCreationStep::removeManagedFilesFromPackage() +{ + // Clean up all files managed by Qt Creator + { + QString androidLibPath = m_androidDir.toString() + QLatin1String("/libs/"); + QDirIterator dirIt(m_androidDir.toString(), QDirIterator::Subdirectories); + while (dirIt.hasNext()) { + dirIt.next(); + + if (!dirIt.fileInfo().isDir()) { + bool isQtLibrary = dirIt.fileInfo().path().startsWith(androidLibPath) + && dirIt.fileName().startsWith(QLatin1String("libQt5")) + && dirIt.fileName().endsWith(QLatin1String(".so")); + + if (dirIt.filePath().contains(AndroidManager::libraryPrefix()) || isQtLibrary) + QFile::remove(dirIt.filePath()); + } + } + } +} + +void AndroidPackageCreationStep::copyFilesIntoPackage(const QList &deployList) +{ + foreach (DeployItem item, deployList) { + QFileInfo info(item.remoteFileName); + if (info.exists()) + QFile::remove(item.remoteFileName); + else + QDir().mkpath(info.absolutePath()); + + QFile::copy(item.localFileName, item.remoteFileName); + } +} + +void AndroidPackageCreationStep::stripFiles(const QList &deployList) +{ + + QStringList fileList; + foreach (DeployItem item, deployList) + if (item.needsStrip) + fileList.append(item.remoteFileName); + + ProjectExplorer::ToolChain *tc = ProjectExplorer::ToolChainKitInformation::toolChain(target()->kit()); + if (tc->type() != QLatin1String(Constants::ANDROID_TOOLCHAIN_TYPE)) + return; + + AndroidToolChain *atc = static_cast(tc); + stripAndroidLibs(fileList, + target()->activeRunConfiguration()->abi().architecture(), + atc->ndkToolChainVersion()); +} + +void AndroidPackageCreationStep::updateXmlForFiles(const QStringList &inLibList, + const QStringList &inAssetsList) +{ + AndroidManager::setBundledInLib(target(), inLibList); + AndroidManager::setBundledInAssets(target(), inAssetsList); +} + + bool AndroidPackageCreationStep::createPackage() { checkRequiredLibrariesForRun(); @@ -451,6 +621,49 @@ bool AndroidPackageCreationStep::createPackage() build << QLatin1String("release"); } + QList deployFiles; + QList importsAndPlugins; + + QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(target()->kit()); + + // Qt 5 supports bundling libraries inside the apk. We guard the code for Qt 5 to be sure we + // do not disrupt existing projects. + if (version && version->qtVersion() >= QtSupport::QtVersionNumber(5, 0, 0)) { + bool bundleQt = AndroidManager::bundleQt(target()); + + // Collect the files to bundle in the package + if (bundleQt) + collectFiles(&deployFiles, &importsAndPlugins); + + // Remove files from package if they are not needed + removeManagedFilesFromPackage(); + + // Deploy files to package + if (bundleQt) { + copyFilesIntoPackage(deployFiles); + stripFiles(deployFiles); + + QStringList inLibList; + QStringList inAssetsList; + foreach (DeployItem deployItem, importsAndPlugins) { + QString conversionInfo = deployItem.localFileName + + QLatin1Char(':') + + deployItem.remoteFileName; + + if (deployItem.localFileName.endsWith(QLatin1String(".so"))) + inLibList.append(conversionInfo); + else + inAssetsList.append(conversionInfo); + } + + QMetaObject::invokeMethod(this, + "updateXmlForFiles", + Qt::BlockingQueuedConnection, + Q_ARG(QStringList, inLibList), + Q_ARG(QStringList, inAssetsList)); + } + } + emit addOutput(tr("Creating package file ..."), MessageOutput); QProcess *const buildProc = new QProcess; diff --git a/src/plugins/android/androidpackagecreationstep.h b/src/plugins/android/androidpackagecreationstep.h index 13a6fd96938..19c01682937 100644 --- a/src/plugins/android/androidpackagecreationstep.h +++ b/src/plugins/android/androidpackagecreationstep.h @@ -45,6 +45,8 @@ QT_END_NAMESPACE namespace Android { namespace Internal { +class DeployItem; + class AndroidPackageCreationStep : public ProjectExplorer::BuildStep { Q_OBJECT @@ -82,6 +84,8 @@ private slots: void showInGraphicalShell(); void setQtLibs(const QStringList &qtLibs); void setPrebundledLibs(const QStringList &prebundledLibs); + void updateXmlForFiles(const QStringList &inLibList, const QStringList &inAssetsList); + void getBundleInformation(); signals: void updateRequiredLibrariesModels(); @@ -100,6 +104,12 @@ private: void raiseError(const QString &shortMsg, const QString &detailedMsg = QString()); + QStringList collectRelativeFilePaths(const QString &parentPath); + void collectFiles(QList *deployList, QList *pluginsAndImports); + void removeManagedFilesFromPackage(); + void copyFilesIntoPackage(const QList &deployList); + void stripFiles(const QList &deployList); + static const Core::Id CreatePackageId; private: @@ -126,8 +136,13 @@ private: Utils::FileName m_appPath; Utils::FileName m_readElf; QStringList m_qtLibs; + QStringList m_qtLibsWithDependencies; QVector m_availableQtLibs; QStringList m_prebundledLibs; + + QStringList m_bundledJars; + QStringList m_otherBundledFiles; + bool m_bundleQt; }; } // namespace Internal diff --git a/src/plugins/android/androidpackagecreationwidget.cpp b/src/plugins/android/androidpackagecreationwidget.cpp index 571f18f04ef..bd8502aebb8 100644 --- a/src/plugins/android/androidpackagecreationwidget.cpp +++ b/src/plugins/android/androidpackagecreationwidget.cpp @@ -387,24 +387,16 @@ void AndroidPackageCreationWidget::setQtLibs(QModelIndex, QModelIndex) { AndroidManager::setQtLibs(m_step->target(), m_qtLibsModel->checkedItems()); AndroidDeployStep * const deployStep = AndroidGlobal::buildStep(m_step->target()->activeDeployConfiguration()); - if (deployStep->useLocalQtLibs()) { - // ### Passes -1 for API level, which means it won't work with setups that require - // library selection based on API level. Use the old approach (command line argument) - // in these cases. - AndroidManager::setUseLocalLibs(m_step->target(), true, -1); - } + if (deployStep->useLocalQtLibs()) + AndroidManager::updateDeploymentSettings(m_step->target()); } void AndroidPackageCreationWidget::setPrebundledLibs(QModelIndex, QModelIndex) { AndroidManager::setPrebundledLibs(m_step->target(), m_prebundledLibs->checkedItems()); AndroidDeployStep * const deployStep = AndroidGlobal::buildStep(m_step->target()->activeDeployConfiguration()); - if (deployStep->useLocalQtLibs()) { - // ### Passes -1 for API level, which means it won't work with setups that require - // library selection based on API level. Use the old approach (command line argument) - // in these cases. - AndroidManager::setUseLocalLibs(m_step->target(), true, -1); - } + if (deployStep->useLocalQtLibs()) + AndroidManager::updateDeploymentSettings(m_step->target()); } void AndroidPackageCreationWidget::prebundledLibSelected(const QModelIndex &index)