From a20dd013a7bb35fa1163b36c53230621b28fa689 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Thu, 7 Mar 2013 13:22:21 +0100 Subject: [PATCH] Android: Fix use_local_libs when running from launcher The old way of passing the use_local_libs settings to the app (which is still supported for compatibility with Necessitas) was to pass it as command line arguments when the app is launched from Qt Creator. This will make the app depend on Ministro if it's later launched from the Android launcher. To avoid this, we pass the info as part of AndroidManifest.xml instead. Task-number: QTCREATORBUG-8643 Change-Id: Ib044ce8bf7e285cf46075a8713bd7fc6736052d5 Reviewed-by: Daniel Teske --- src/plugins/android/androiddeploystep.cpp | 5 ++ src/plugins/android/androidmanager.cpp | 56 +++++++++++++++++++ src/plugins/android/androidmanager.h | 2 + .../android/androidpackagecreationwidget.cpp | 16 ++++++ 4 files changed, 79 insertions(+) diff --git a/src/plugins/android/androiddeploystep.cpp b/src/plugins/android/androiddeploystep.cpp index 9f9fc4d2cea..0eba7056726 100644 --- a/src/plugins/android/androiddeploystep.cpp +++ b/src/plugins/android/androiddeploystep.cpp @@ -208,6 +208,11 @@ void AndroidDeployStep::setDeployQASIPackagePath(const QString &package) 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); } bool AndroidDeployStep::runCommand(QProcess *buildProc, diff --git a/src/plugins/android/androidmanager.cpp b/src/plugins/android/androidmanager.cpp index 449a80575c5..edb77dcd91f 100644 --- a/src/plugins/android/androidmanager.cpp +++ b/src/plugins/android/androidmanager.cpp @@ -348,6 +348,62 @@ QString AndroidManager::targetApplication(ProjectExplorer::Target *target) return QString(); } +bool AndroidManager::setUseLocalLibs(ProjectExplorer::Target *target, bool useLocalLibs, int deviceAPILevel) +{ + // 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 + QtSupport::BaseQtVersion *baseQtVersion = QtSupport::QtKitInformation::qtVersion(target->kit()); + if (baseQtVersion == 0 || baseQtVersion->qtVersion() < QtSupport::QtVersionNumber(5,0,0)) + return true; + + QDomDocument doc; + if (!openManifest(target, doc)) + return false; + + QDomElement metadataElem = doc.documentElement().firstChildElement(QLatin1String("application")).firstChildElement(QLatin1String("activity")).firstChildElement(QLatin1String("meta-data")); + + QString localLibs; + QString localJars; + QString staticInitClasses; + if (useLocalLibs) { + localLibs = loadLocalLibs(target, deviceAPILevel); + localJars = loadLocalJars(target, deviceAPILevel); + staticInitClasses = loadLocalJarsInitClasses(target, deviceAPILevel); + } + + bool changedManifest = false; + while (!metadataElem.isNull()) { + if (metadataElem.attribute(QLatin1String("android:name")) == QLatin1String("android.app.use_local_qt_libs")) { + if (metadataElem.attribute(QLatin1String("android:value")).toInt() != useLocalLibs) { + metadataElem.setAttribute(QLatin1String("android:value"), int(useLocalLibs)); + changedManifest = true; + } + } else if (metadataElem.attribute(QLatin1String("android:name")) == QLatin1String("android.app.load_local_libs")) { + if (metadataElem.attribute(QLatin1String("android:value")) != localLibs) { + metadataElem.setAttribute(QLatin1String("android:value"), localLibs); + changedManifest = true; + } + } else if (metadataElem.attribute(QLatin1String("android:name")) == QLatin1String("android.app.load_local_jars")) { + if (metadataElem.attribute(QLatin1String("android:value")) != localJars) { + metadataElem.setAttribute(QLatin1String("android:value"), localJars); + changedManifest = true; + } + } else if (metadataElem.attribute(QLatin1String("android:name")) == QLatin1String("android.app.static_init_classes")) { + if (metadataElem.attribute(QLatin1String("android:value")) != staticInitClasses) { + metadataElem.setAttribute(QLatin1String("android:value"), staticInitClasses); + changedManifest = true; + } + } + + metadataElem = metadataElem.nextSiblingElement(QLatin1String("meta-data")); + } + + if (changedManifest) + return saveManifest(target, doc); + else + return true; +} + bool AndroidManager::setTargetApplication(ProjectExplorer::Target *target, const QString &name) { QDomDocument doc; diff --git a/src/plugins/android/androidmanager.h b/src/plugins/android/androidmanager.h index a03e0980174..6316dfdafc9 100644 --- a/src/plugins/android/androidmanager.h +++ b/src/plugins/android/androidmanager.h @@ -84,6 +84,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 QString targetSDK(ProjectExplorer::Target *target); static bool setTargetSDK(ProjectExplorer::Target *target, const QString &sdk); diff --git a/src/plugins/android/androidpackagecreationwidget.cpp b/src/plugins/android/androidpackagecreationwidget.cpp index a22172b57c5..21701e79db5 100644 --- a/src/plugins/android/androidpackagecreationwidget.cpp +++ b/src/plugins/android/androidpackagecreationwidget.cpp @@ -32,6 +32,8 @@ #include "androidconfigurations.h" #include "androidcreatekeystorecertificate.h" #include "androidmanager.h" +#include "androiddeploystep.h" +#include "androidglobal.h" #include "ui_androidpackagecreationwidget.h" #include @@ -376,11 +378,25 @@ void AndroidPackageCreationWidget::setTarget(const QString &target) 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); + } } 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); + } } void AndroidPackageCreationWidget::prebundledLibSelected(const QModelIndex &index)