| 
									
										
										
										
											2016-01-15 14:57:40 +01:00
										 |  |  | /****************************************************************************
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:30:57 +03:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2016-01-15 14:57:40 +01:00
										 |  |  | ** Copyright (C) 2016 BogDan Vatra <bog_dan_ro@yahoo.com> | 
					
						
							|  |  |  | ** Contact: https://www.qt.io/licensing/
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:30:57 +03:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2012-10-02 09:12:39 +02:00
										 |  |  | ** This file is part of Qt Creator. | 
					
						
							| 
									
										
										
										
											2012-04-18 20:30:57 +03:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2012-10-02 09:12:39 +02:00
										 |  |  | ** Commercial License Usage | 
					
						
							|  |  |  | ** Licensees holding valid commercial Qt licenses may use this file in | 
					
						
							|  |  |  | ** accordance with the commercial license agreement provided with the | 
					
						
							|  |  |  | ** Software or, alternatively, in accordance with the terms contained in | 
					
						
							| 
									
										
										
										
											2016-01-15 14:57:40 +01:00
										 |  |  | ** a written agreement between you and The Qt Company. For licensing terms | 
					
						
							|  |  |  | ** and conditions see https://www.qt.io/terms-conditions. For further
 | 
					
						
							|  |  |  | ** information use the contact form at https://www.qt.io/contact-us.
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:30:57 +03:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2016-01-15 14:57:40 +01:00
										 |  |  | ** GNU General Public License Usage | 
					
						
							|  |  |  | ** Alternatively, this file may be used under the terms of the GNU | 
					
						
							|  |  |  | ** General Public License version 3 as published by the Free Software | 
					
						
							|  |  |  | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT | 
					
						
							|  |  |  | ** included in the packaging of this file. Please review the following | 
					
						
							|  |  |  | ** information to ensure the GNU General Public License requirements will | 
					
						
							|  |  |  | ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:30:57 +03:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2012-10-02 09:12:39 +02:00
										 |  |  | ****************************************************************************/ | 
					
						
							| 
									
										
										
										
											2012-04-18 20:30:57 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-24 15:49:09 +02:00
										 |  |  | #include "androidmanager.h"
 | 
					
						
							| 
									
										
										
										
											2019-01-18 18:07:54 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "androidbuildapkstep.h"
 | 
					
						
							| 
									
										
										
										
											2015-03-05 11:56:15 +01:00
										 |  |  | #include "androidconstants.h"
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:30:57 +03:00
										 |  |  | #include "androidconfigurations.h"
 | 
					
						
							|  |  |  | #include "androidrunconfiguration.h"
 | 
					
						
							|  |  |  | #include "androidglobal.h"
 | 
					
						
							| 
									
										
										
										
											2013-01-25 16:49:22 +01:00
										 |  |  | #include "androidtoolchain.h"
 | 
					
						
							| 
									
										
										
										
											2013-09-17 18:24:57 +02:00
										 |  |  | #include "androiddeployqtstep.h"
 | 
					
						
							| 
									
										
										
										
											2014-06-25 15:42:11 +02:00
										 |  |  | #include "androidqtversion.h"
 | 
					
						
							| 
									
										
										
										
											2017-04-03 11:11:17 +02:00
										 |  |  | #include "androidavdmanager.h"
 | 
					
						
							| 
									
										
										
										
											2017-08-18 08:22:34 +02:00
										 |  |  | #include "androidsdkmanager.h"
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:30:57 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-16 17:27:06 +02:00
										 |  |  | #include <coreplugin/documentmanager.h>
 | 
					
						
							| 
									
										
										
										
											2013-09-17 18:24:57 +02:00
										 |  |  | #include <coreplugin/messagemanager.h>
 | 
					
						
							| 
									
										
										
										
											2014-03-11 18:09:23 +01:00
										 |  |  | #include <coreplugin/icore.h>
 | 
					
						
							| 
									
										
										
										
											2014-06-24 16:47:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-25 15:42:11 +02:00
										 |  |  | #include <projectexplorer/buildconfiguration.h>
 | 
					
						
							|  |  |  | #include <projectexplorer/project.h>
 | 
					
						
							| 
									
										
										
										
											2018-12-05 10:29:48 +01:00
										 |  |  | #include <projectexplorer/projectnodes.h>
 | 
					
						
							| 
									
										
										
										
											2012-04-24 15:49:09 +02:00
										 |  |  | #include <projectexplorer/projectexplorer.h>
 | 
					
						
							|  |  |  | #include <projectexplorer/session.h>
 | 
					
						
							|  |  |  | #include <projectexplorer/target.h>
 | 
					
						
							| 
									
										
										
										
											2014-06-25 15:42:11 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-03 18:31:44 +02:00
										 |  |  | #include <qtsupport/qtkitinformation.h>
 | 
					
						
							| 
									
										
										
										
											2012-04-24 15:49:09 +02:00
										 |  |  | #include <qtsupport/qtsupportconstants.h>
 | 
					
						
							| 
									
										
										
										
											2018-07-27 11:18:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-16 18:25:52 +04:00
										 |  |  | #include <utils/algorithm.h>
 | 
					
						
							| 
									
										
										
										
											2018-07-27 11:18:06 +02:00
										 |  |  | #include <utils/qtcassert.h>
 | 
					
						
							| 
									
										
										
										
											2016-04-29 16:52:58 +02:00
										 |  |  | #include <utils/synchronousprocess.h>
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:30:57 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <QDir>
 | 
					
						
							|  |  |  | #include <QFileSystemWatcher>
 | 
					
						
							|  |  |  | #include <QList>
 | 
					
						
							| 
									
										
										
										
											2018-06-18 11:49:14 +02:00
										 |  |  | #include <QLoggingCategory>
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:30:57 +03:00
										 |  |  | #include <QProcess>
 | 
					
						
							| 
									
										
										
										
											2017-03-09 23:02:32 +01:00
										 |  |  | #include <QRegExp>
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:30:57 +03:00
										 |  |  | #include <QMessageBox>
 | 
					
						
							|  |  |  | #include <QApplication>
 | 
					
						
							|  |  |  | #include <QDomDocument>
 | 
					
						
							| 
									
										
										
										
											2017-04-10 15:02:57 +03:00
										 |  |  | #include <QVersionNumber>
 | 
					
						
							| 
									
										
										
										
											2018-07-03 11:53:25 +02:00
										 |  |  | #include <QRegularExpression>
 | 
					
						
							| 
									
										
										
										
											2018-06-18 11:49:14 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:30:57 +03:00
										 |  |  | namespace { | 
					
						
							|  |  |  |     const QLatin1String AndroidManifestName("AndroidManifest.xml"); | 
					
						
							|  |  |  |     const QLatin1String AndroidDefaultPropertiesName("project.properties"); | 
					
						
							| 
									
										
										
										
											2014-06-25 15:42:11 +02:00
										 |  |  |     const QLatin1String AndroidDeviceSn("AndroidDeviceSerialNumber"); | 
					
						
							| 
									
										
										
										
											2019-08-26 14:19:07 +03:00
										 |  |  |     const QLatin1String AndroidDeviceAbis("AndroidDeviceAbis"); | 
					
						
							| 
									
										
										
										
											2017-03-30 14:43:13 +02:00
										 |  |  |     const QLatin1String ApiLevelKey("AndroidVersion.ApiLevel"); | 
					
						
							| 
									
										
										
										
											2018-08-07 14:47:08 +02:00
										 |  |  |     const QString packageNameRegEx("(?<token>package: )(.*?)(name=)'(?<target>.*?)'"); | 
					
						
							|  |  |  |     const QString activityRegEx("(?<token>launchable-activity: )(.*?)(name=)'(?<target>.*?)'"); | 
					
						
							|  |  |  |     const QString apkVersionRegEx("(?<token>package: )(.*?)(versionCode=)'(?<target>.*?)'"); | 
					
						
							|  |  |  |     const QString versionCodeRegEx("(?<token>versionCode=)(?<version>\\d*)"); | 
					
						
							| 
									
										
										
										
											2014-06-25 15:42:11 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-12 09:33:30 +03:00
										 |  |  |     Q_LOGGING_CATEGORY(androidManagerLog, "qtc.android.androidManager", QtWarningMsg) | 
					
						
							| 
									
										
										
										
											2018-07-03 11:51:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-03 11:53:25 +02:00
										 |  |  |     QString parseAaptOutput(const QString &output, const QString ®Ex) { | 
					
						
							|  |  |  |         const QRegularExpression regRx(regEx, | 
					
						
							|  |  |  |                                        QRegularExpression::CaseInsensitiveOption | | 
					
						
							|  |  |  |                                        QRegularExpression::MultilineOption); | 
					
						
							|  |  |  |         QRegularExpressionMatch match = regRx.match(output); | 
					
						
							|  |  |  |         if (match.hasMatch()) | 
					
						
							| 
									
										
										
										
											2018-08-07 14:47:08 +02:00
										 |  |  |             return match.captured("target"); | 
					
						
							| 
									
										
										
										
											2018-07-03 11:53:25 +02:00
										 |  |  |         return QString(); | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2012-04-18 20:30:57 +03:00
										 |  |  | } // anonymous namespace
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-31 10:51:37 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-05 10:29:48 +01:00
										 |  |  | using namespace ProjectExplorer; | 
					
						
							| 
									
										
										
										
											2018-05-31 10:51:37 +02:00
										 |  |  | using namespace Utils; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:30:57 +03:00
										 |  |  | namespace Android { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-25 15:42:11 +02:00
										 |  |  | using namespace Internal; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-22 13:45:41 +02:00
										 |  |  | class Library | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     Library() | 
					
						
							|  |  |  |     { level = -1; } | 
					
						
							|  |  |  |     int level; | 
					
						
							|  |  |  |     QStringList dependencies; | 
					
						
							|  |  |  |     QString name; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-25 12:19:15 +02:00
										 |  |  | using LibrariesMap = QMap<QString, Library>; | 
					
						
							| 
									
										
										
										
											2014-07-22 13:45:41 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-28 13:49:26 +02:00
										 |  |  | static bool openXmlFile(QDomDocument &doc, const Utils::FilePath &fileName); | 
					
						
							| 
									
										
										
										
											2014-07-22 13:45:41 +02:00
										 |  |  | static bool openManifest(ProjectExplorer::Target *target, QDomDocument &doc); | 
					
						
							| 
									
										
										
										
											2016-08-17 18:46:12 +02:00
										 |  |  | static int parseMinSdk(const QDomElement &manifestElem); | 
					
						
							| 
									
										
										
										
											2014-07-22 13:45:41 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-05 10:29:48 +01:00
										 |  |  | static const ProjectNode *currentProjectNode(Target *target) | 
					
						
							| 
									
										
										
										
											2017-12-08 17:20:48 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-12-05 10:29:48 +01:00
										 |  |  |     if (RunConfiguration *rc = target->activeRunConfiguration()) | 
					
						
							|  |  |  |         return target->project()->findNodeForBuildKey(rc->buildKey()); | 
					
						
							|  |  |  |     return nullptr; | 
					
						
							| 
									
										
										
										
											2017-12-08 17:20:48 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-24 15:49:09 +02:00
										 |  |  | QString AndroidManager::packageName(ProjectExplorer::Target *target) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QDomDocument doc; | 
					
						
							|  |  |  |     if (!openManifest(target, doc)) | 
					
						
							|  |  |  |         return QString(); | 
					
						
							|  |  |  |     QDomElement manifestElem = doc.documentElement(); | 
					
						
							|  |  |  |     return manifestElem.attribute(QLatin1String("package")); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:30:57 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-28 13:49:26 +02:00
										 |  |  | QString AndroidManager::packageName(const Utils::FilePath &manifestFile) | 
					
						
							| 
									
										
										
										
											2014-10-24 17:53:05 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     QDomDocument doc; | 
					
						
							|  |  |  |     if (!openXmlFile(doc, manifestFile)) | 
					
						
							|  |  |  |         return QString(); | 
					
						
							|  |  |  |     QDomElement manifestElem = doc.documentElement(); | 
					
						
							|  |  |  |     return manifestElem.attribute(QLatin1String("package")); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-03 11:53:25 +02:00
										 |  |  | bool AndroidManager::packageInstalled(const QString &deviceSerial, | 
					
						
							|  |  |  |                                       const QString &packageName) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (deviceSerial.isEmpty() || packageName.isEmpty()) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     QStringList args = AndroidDeviceInfo::adbSelector(deviceSerial); | 
					
						
							|  |  |  |     args << "shell" << "pm" << "list" << "packages"; | 
					
						
							| 
									
										
										
										
											2018-08-07 11:12:45 +02:00
										 |  |  |     QStringList lines = runAdbCommand(args).stdOut().split(QRegularExpression("[\\n\\r]"), | 
					
						
							|  |  |  |                                                            QString::SkipEmptyParts); | 
					
						
							| 
									
										
										
										
											2018-07-03 11:53:25 +02:00
										 |  |  |     for (const QString &line : lines) { | 
					
						
							|  |  |  |         // Don't want to confuse com.abc.xyz with com.abc.xyz.def so check with
 | 
					
						
							|  |  |  |         // endsWith
 | 
					
						
							|  |  |  |         if (line.endsWith(packageName)) | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-07 14:47:08 +02:00
										 |  |  | int AndroidManager::packageVersionCode(const QString &deviceSerial, | 
					
						
							|  |  |  |                                               const QString &packageName) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (deviceSerial.isEmpty() || packageName.isEmpty()) | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QStringList args = AndroidDeviceInfo::adbSelector(deviceSerial); | 
					
						
							|  |  |  |     args << "shell" << "dumpsys" << "package" << packageName; | 
					
						
							|  |  |  |     const QRegularExpression regRx(versionCodeRegEx, | 
					
						
							|  |  |  |                                    QRegularExpression::CaseInsensitiveOption | | 
					
						
							|  |  |  |                                    QRegularExpression::MultilineOption); | 
					
						
							|  |  |  |     QRegularExpressionMatch match = regRx.match(runAdbCommand(args).stdOut()); | 
					
						
							|  |  |  |     if (match.hasMatch()) | 
					
						
							|  |  |  |         return match.captured("version").toInt(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-28 13:49:26 +02:00
										 |  |  | void AndroidManager::apkInfo(const Utils::FilePath &apkPath, | 
					
						
							| 
									
										
										
										
											2018-07-03 11:53:25 +02:00
										 |  |  |                                     QString *packageName, | 
					
						
							| 
									
										
										
										
											2018-08-07 14:47:08 +02:00
										 |  |  |                                     int *version, | 
					
						
							| 
									
										
										
										
											2018-07-03 11:53:25 +02:00
										 |  |  |                                     QString *activityPath) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-08-07 11:12:45 +02:00
										 |  |  |     SdkToolResult result; | 
					
						
							|  |  |  |     result = runAaptCommand({"dump", "badging", apkPath.toString()}); | 
					
						
							| 
									
										
										
										
											2018-07-03 11:53:25 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     QString packageStr; | 
					
						
							|  |  |  |     if (activityPath) { | 
					
						
							| 
									
										
										
										
											2018-08-07 11:12:45 +02:00
										 |  |  |         packageStr = parseAaptOutput(result.stdOut(), packageNameRegEx); | 
					
						
							|  |  |  |         QString path = parseAaptOutput(result.stdOut(), activityRegEx); | 
					
						
							| 
									
										
										
										
											2018-07-03 11:53:25 +02:00
										 |  |  |         if (!packageStr.isEmpty() && !path.isEmpty()) | 
					
						
							|  |  |  |             *activityPath = packageStr + '/' + path; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (packageName) { | 
					
						
							|  |  |  |         *packageName = activityPath ? packageStr : | 
					
						
							| 
									
										
										
										
											2018-08-07 11:12:45 +02:00
										 |  |  |                                       parseAaptOutput(result.stdOut(), packageNameRegEx); | 
					
						
							| 
									
										
										
										
											2018-07-03 11:53:25 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (version) { | 
					
						
							| 
									
										
										
										
											2018-08-07 11:12:45 +02:00
										 |  |  |         QString versionStr = parseAaptOutput(result.stdOut(), apkVersionRegEx); | 
					
						
							| 
									
										
										
										
											2018-08-07 14:47:08 +02:00
										 |  |  |         *version = versionStr.toInt(); | 
					
						
							| 
									
										
										
										
											2018-07-03 11:53:25 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-24 15:49:09 +02:00
										 |  |  | QString AndroidManager::intentName(ProjectExplorer::Target *target) | 
					
						
							| 
									
										
										
										
											2012-04-18 20:30:57 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-04-24 15:49:09 +02:00
										 |  |  |     return packageName(target) + QLatin1Char('/') + activityName(target); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:30:57 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-24 15:49:09 +02:00
										 |  |  | QString AndroidManager::activityName(ProjectExplorer::Target *target) | 
					
						
							| 
									
										
										
										
											2012-04-18 20:30:57 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-04-24 15:49:09 +02:00
										 |  |  |     QDomDocument doc; | 
					
						
							|  |  |  |     if (!openManifest(target, doc)) | 
					
						
							|  |  |  |         return QString(); | 
					
						
							|  |  |  |     QDomElement activityElem = doc.documentElement().firstChildElement(QLatin1String("application")).firstChildElement(QLatin1String("activity")); | 
					
						
							|  |  |  |     return activityElem.attribute(QLatin1String("android:name")); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:30:57 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 18:46:12 +02:00
										 |  |  | /*!
 | 
					
						
							|  |  |  |     Returns the minimum Android API level set for the APK. Minimum API level | 
					
						
							| 
									
										
										
										
											2018-10-22 16:34:31 +02:00
										 |  |  |     of the kit is returned if the manifest file of the APK cannot be found | 
					
						
							| 
									
										
										
										
											2016-08-17 18:46:12 +02:00
										 |  |  |     or parsed. | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2013-08-28 15:23:04 +02:00
										 |  |  | int AndroidManager::minimumSDK(ProjectExplorer::Target *target) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QDomDocument doc; | 
					
						
							| 
									
										
										
										
											2015-01-27 18:46:40 +01:00
										 |  |  |     if (!openXmlFile(doc, AndroidManager::manifestSourcePath(target))) | 
					
						
							| 
									
										
										
										
											2016-08-17 18:46:12 +02:00
										 |  |  |         return minimumSDK(target->kit()); | 
					
						
							|  |  |  |     return parseMinSdk(doc.documentElement()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |     Returns the minimum Android API level required by the kit to compile. -1 is | 
					
						
							|  |  |  |     returned if the kit does not support Android. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | int AndroidManager::minimumSDK(const ProjectExplorer::Kit *kit) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int minSDKVersion = -1; | 
					
						
							| 
									
										
										
										
											2019-02-06 12:50:51 +01:00
										 |  |  |     QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(kit); | 
					
						
							| 
									
										
										
										
											2017-12-19 10:32:39 +01:00
										 |  |  |     if (version && version->targetDeviceTypes().contains(Constants::ANDROID_DEVICE_TYPE)) { | 
					
						
							| 
									
										
										
										
											2019-09-30 14:34:31 +02:00
										 |  |  |         Utils::FilePath stockManifestFilePath = Utils::FilePath::fromUserInput( | 
					
						
							|  |  |  |             version->prefix().toString() + "/src/android/templates/AndroidManifest.xml"); | 
					
						
							| 
									
										
										
										
											2016-08-17 18:46:12 +02:00
										 |  |  |         QDomDocument doc; | 
					
						
							|  |  |  |         if (openXmlFile(doc, stockManifestFilePath)) { | 
					
						
							|  |  |  |             minSDKVersion = parseMinSdk(doc.documentElement()); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2013-08-28 15:23:04 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-08-17 18:46:12 +02:00
										 |  |  |     return minSDKVersion; | 
					
						
							| 
									
										
										
										
											2013-08-28 15:23:04 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-08-28 15:20:54 +02:00
										 |  |  | QString AndroidManager::buildTargetSDK(ProjectExplorer::Target *target) | 
					
						
							| 
									
										
										
										
											2012-04-18 20:30:57 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-01-18 18:07:54 +01:00
										 |  |  |     if (auto androidBuildApkStep = AndroidBuildApkStep::findInBuild(target->activeBuildConfiguration())) | 
					
						
							| 
									
										
										
										
											2014-06-25 15:42:11 +02:00
										 |  |  |         return androidBuildApkStep->buildTargetSdk(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-18 08:22:34 +02:00
										 |  |  |     QString fallback = AndroidConfig::apiLevelNameFor( | 
					
						
							|  |  |  |                 AndroidConfigurations::sdkManager()->latestAndroidSdkPlatform()); | 
					
						
							| 
									
										
										
										
											2014-06-25 15:42:11 +02:00
										 |  |  |     return fallback; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-26 14:19:07 +03:00
										 |  |  | QStringList AndroidManager::applicationAbis(const Target *target) | 
					
						
							| 
									
										
										
										
											2013-05-03 15:10:21 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-02-06 12:50:51 +01:00
										 |  |  |     auto qt = static_cast<AndroidQtVersion *>(QtSupport::QtKitAspect::qtVersion(target->kit())); | 
					
						
							| 
									
										
										
										
											2019-08-26 14:19:07 +03:00
										 |  |  |     return qt->androidAbis(); | 
					
						
							| 
									
										
										
										
											2013-05-03 15:10:21 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-06 14:17:17 +02:00
										 |  |  | QJsonObject AndroidManager::deploymentSettings(const Target *target) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QtSupport::BaseQtVersion *qt = QtSupport::QtKitAspect::qtVersion(target->kit()); | 
					
						
							|  |  |  |     if (!qt) | 
					
						
							|  |  |  |         return {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto tc = ProjectExplorer::ToolChainKitAspect::toolChain(target->kit(), ProjectExplorer::Constants::CXX_LANGUAGE_ID); | 
					
						
							| 
									
										
										
										
											2019-06-14 11:12:19 +02:00
										 |  |  |     if (!tc || tc->typeId() != Constants::ANDROID_TOOLCHAIN_TYPEID) | 
					
						
							| 
									
										
										
										
											2019-03-06 14:17:17 +02:00
										 |  |  |         return {}; | 
					
						
							|  |  |  |     QJsonObject settings; | 
					
						
							| 
									
										
										
										
											2019-08-26 14:19:07 +03:00
										 |  |  |     settings["_description"] = "This file is generated by QtCreator to be read by androiddeployqt and should not be modified by hand."; | 
					
						
							| 
									
										
										
										
											2019-09-30 14:34:31 +02:00
										 |  |  |     settings["qt"] = qt->prefix().toString(); | 
					
						
							| 
									
										
										
										
											2019-03-06 14:17:17 +02:00
										 |  |  |     settings["ndk"] = AndroidConfigurations::currentConfig().ndkLocation().toString(); | 
					
						
							|  |  |  |     settings["sdk"] = AndroidConfigurations::currentConfig().sdkLocation().toString(); | 
					
						
							| 
									
										
										
										
											2019-08-26 14:19:07 +03:00
										 |  |  |     settings["stdcpp-path"] = AndroidConfigurations::currentConfig().toolchainPath().pathAppended("sysroot/usr/lib/").toString(); | 
					
						
							| 
									
										
										
										
											2019-03-06 14:17:17 +02:00
										 |  |  |     settings["toolchain-prefix"] =  "llvm"; | 
					
						
							|  |  |  |     settings["tool-prefix"] = "llvm"; | 
					
						
							|  |  |  |     settings["useLLVM"] = true; | 
					
						
							|  |  |  |     settings["ndk-host"] = AndroidConfigurations::currentConfig().toolchainHost(); | 
					
						
							|  |  |  |     return settings; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-28 13:49:26 +02:00
										 |  |  | Utils::FilePath AndroidManager::dirPath(const ProjectExplorer::Target *target) | 
					
						
							| 
									
										
										
										
											2012-04-18 20:30:57 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-01-27 18:46:40 +01:00
										 |  |  |     if (target->activeBuildConfiguration()) | 
					
						
							| 
									
										
										
										
											2019-05-17 13:20:41 +02:00
										 |  |  |         return target->activeBuildConfiguration()->buildDirectory().pathAppended(Constants::ANDROID_BUILDDIRECTORY); | 
					
						
							| 
									
										
										
										
											2019-05-28 13:49:26 +02:00
										 |  |  |     return Utils::FilePath(); | 
					
						
							| 
									
										
										
										
											2015-01-27 18:46:40 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-28 13:49:26 +02:00
										 |  |  | Utils::FilePath AndroidManager::apkPath(const ProjectExplorer::Target *target) | 
					
						
							| 
									
										
										
										
											2018-07-27 11:18:06 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-05-28 13:49:26 +02:00
										 |  |  |     QTC_ASSERT(target, return Utils::FilePath()); | 
					
						
							| 
									
										
										
										
											2018-07-27 11:18:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-18 18:07:54 +01:00
										 |  |  |     auto buildApkStep = AndroidBuildApkStep::findInBuild(target->activeBuildConfiguration()); | 
					
						
							| 
									
										
										
										
											2018-07-27 11:18:06 +02:00
										 |  |  |     if (!buildApkStep) | 
					
						
							| 
									
										
										
										
											2019-05-28 13:49:26 +02:00
										 |  |  |         return Utils::FilePath(); | 
					
						
							| 
									
										
										
										
											2018-07-27 11:18:06 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     QString apkPath("build/outputs/apk/android-build-"); | 
					
						
							|  |  |  |     if (buildApkStep->signPackage()) | 
					
						
							|  |  |  |         apkPath += QLatin1String("release.apk"); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         apkPath += QLatin1String("debug.apk"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-17 13:20:41 +02:00
										 |  |  |     return dirPath(target).pathAppended(apkPath); | 
					
						
							| 
									
										
										
										
											2018-07-27 11:18:06 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-26 14:19:07 +03:00
										 |  |  | FilePath AndroidManager::aabPath(const Target *target) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTC_ASSERT(target, return Utils::FilePath()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto buildApkStep = AndroidBuildApkStep::findInBuild(target->activeBuildConfiguration()); | 
					
						
							|  |  |  |     if (!buildApkStep) | 
					
						
							|  |  |  |         return Utils::FilePath(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QString buildType; | 
					
						
							|  |  |  |     if (buildApkStep->buildConfiguration()->buildType() == BuildConfiguration::Release) | 
					
						
							|  |  |  |         buildType = "release"; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         buildType = "debug"; | 
					
						
							|  |  |  |     return dirPath(target).pathAppended(QString("build/outputs/bundle/%1/android-build-%1.aab").arg(buildType)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool AndroidManager::matchedAbis(const QStringList &deviceAbis, const QStringList &appAbis) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     for (const auto &abi : appAbis) { | 
					
						
							|  |  |  |         if (deviceAbis.contains(abi)) | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QString AndroidManager::devicePreferredAbi(const QStringList &deviceAbis, const QStringList &appAbis) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     for (const auto &abi : appAbis) { | 
					
						
							|  |  |  |         if (deviceAbis.contains(abi)) | 
					
						
							|  |  |  |             return abi; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return {}; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Abi AndroidManager::androidAbi2Abi(const QString &androidAbi) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (androidAbi == "arm64-v8a") { | 
					
						
							|  |  |  |         return Abi{Abi::Architecture::ArmArchitecture, | 
					
						
							|  |  |  |                    Abi::OS::LinuxOS, | 
					
						
							|  |  |  |                    Abi::OSFlavor::AndroidLinuxFlavor, | 
					
						
							|  |  |  |                    Abi::BinaryFormat::ElfFormat, | 
					
						
							|  |  |  |                    64, androidAbi}; | 
					
						
							|  |  |  |     } else if (androidAbi == "armeabi-v7a") { | 
					
						
							|  |  |  |         return Abi{Abi::Architecture::ArmArchitecture, | 
					
						
							|  |  |  |                    Abi::OS::LinuxOS, | 
					
						
							|  |  |  |                    Abi::OSFlavor::AndroidLinuxFlavor, | 
					
						
							|  |  |  |                    Abi::BinaryFormat::ElfFormat, | 
					
						
							|  |  |  |                    32, androidAbi}; | 
					
						
							|  |  |  |     } else if (androidAbi == "x86_64") { | 
					
						
							|  |  |  |         return Abi{Abi::Architecture::X86Architecture, | 
					
						
							|  |  |  |                    Abi::OS::LinuxOS, | 
					
						
							|  |  |  |                    Abi::OSFlavor::AndroidLinuxFlavor, | 
					
						
							|  |  |  |                    Abi::BinaryFormat::ElfFormat, | 
					
						
							|  |  |  |                    64, androidAbi}; | 
					
						
							|  |  |  |     } else if (androidAbi == "x86") { | 
					
						
							|  |  |  |         return Abi{Abi::Architecture::X86Architecture, | 
					
						
							|  |  |  |                    Abi::OS::LinuxOS, | 
					
						
							|  |  |  |                    Abi::OSFlavor::AndroidLinuxFlavor, | 
					
						
							|  |  |  |                    Abi::BinaryFormat::ElfFormat, | 
					
						
							|  |  |  |                    32, androidAbi}; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         return Abi{Abi::Architecture::UnknownArchitecture, | 
					
						
							|  |  |  |                    Abi::OS::LinuxOS, | 
					
						
							|  |  |  |                    Abi::OSFlavor::AndroidLinuxFlavor, | 
					
						
							|  |  |  |                    Abi::BinaryFormat::ElfFormat, | 
					
						
							|  |  |  |                    0, androidAbi}; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-28 13:49:26 +02:00
										 |  |  | Utils::FilePath AndroidManager::manifestSourcePath(ProjectExplorer::Target *target) | 
					
						
							| 
									
										
										
										
											2015-01-27 18:46:40 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-12-05 10:29:48 +01:00
										 |  |  |     if (const ProjectNode *node = currentProjectNode(target)) { | 
					
						
							| 
									
										
										
										
											2018-07-27 12:58:10 +02:00
										 |  |  |         const QString packageSource | 
					
						
							| 
									
										
										
										
											2018-12-18 17:52:19 +01:00
										 |  |  |                 = node->data(Android::Constants::AndroidPackageSourceDir).toString(); | 
					
						
							| 
									
										
										
										
											2018-05-31 10:51:37 +02:00
										 |  |  |         if (!packageSource.isEmpty()) { | 
					
						
							| 
									
										
										
										
											2019-05-28 13:49:26 +02:00
										 |  |  |             const FilePath manifest = FilePath::fromUserInput(packageSource + "/AndroidManifest.xml"); | 
					
						
							| 
									
										
										
										
											2018-05-31 10:51:37 +02:00
										 |  |  |             if (manifest.exists()) | 
					
						
							|  |  |  |                 return manifest; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-01-30 18:19:46 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-01-27 18:46:40 +01:00
										 |  |  |     return manifestPath(target); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:30:57 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-28 13:49:26 +02:00
										 |  |  | Utils::FilePath AndroidManager::manifestPath(ProjectExplorer::Target *target) | 
					
						
							| 
									
										
										
										
											2012-04-18 20:30:57 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-03 18:10:35 +02:00
										 |  |  |     QVariant manifest = target->namedSettings(AndroidManifestName); | 
					
						
							|  |  |  |     if (manifest.isValid()) | 
					
						
							| 
									
										
										
										
											2019-05-28 13:49:26 +02:00
										 |  |  |         return manifest.value<FilePath>(); | 
					
						
							| 
									
										
										
										
											2019-05-17 13:20:41 +02:00
										 |  |  |     return dirPath(target).pathAppended(AndroidManifestName); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:30:57 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-28 13:49:26 +02:00
										 |  |  | void AndroidManager::setManifestPath(Target *target, const FilePath &path) | 
					
						
							| 
									
										
										
										
											2019-04-03 18:10:35 +02:00
										 |  |  | { | 
					
						
							|  |  |  |      target->setNamedSettings(AndroidManifestName, QVariant::fromValue(path)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-28 13:49:26 +02:00
										 |  |  | Utils::FilePath AndroidManager::defaultPropertiesPath(ProjectExplorer::Target *target) | 
					
						
							| 
									
										
										
										
											2012-04-18 20:30:57 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-05-17 13:20:41 +02:00
										 |  |  |     return dirPath(target).pathAppended(AndroidDefaultPropertiesName); | 
					
						
							| 
									
										
										
										
											2012-04-24 15:49:09 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2012-04-18 20:30:57 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-17 18:24:57 +02:00
										 |  |  | QString AndroidManager::deviceSerialNumber(ProjectExplorer::Target *target) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2014-06-25 15:42:11 +02:00
										 |  |  |     return target->namedSettings(AndroidDeviceSn).toString(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AndroidManager::setDeviceSerialNumber(ProjectExplorer::Target *target, const QString &deviceSerialNumber) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-06-18 11:49:14 +02:00
										 |  |  |     qCDebug(androidManagerLog) << "Device serial for the target changed" | 
					
						
							|  |  |  |                                << target->displayName() << deviceSerialNumber; | 
					
						
							| 
									
										
										
										
											2014-06-25 15:42:11 +02:00
										 |  |  |     target->setNamedSettings(AndroidDeviceSn, deviceSerialNumber); | 
					
						
							| 
									
										
										
										
											2013-09-17 18:24:57 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-26 14:19:07 +03:00
										 |  |  | QString AndroidManager::devicePreferredAbi(Target *target) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     auto appAbis = applicationAbis(target); | 
					
						
							|  |  |  |     const auto deviceAbis = target->namedSettings(AndroidDeviceAbis).toStringList(); | 
					
						
							|  |  |  |     for (const auto &abi : deviceAbis) { | 
					
						
							|  |  |  |         if (appAbis.contains(abi)) | 
					
						
							|  |  |  |             return abi; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return {}; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AndroidManager::setDeviceAbis(ProjectExplorer::Target *target, const QStringList &deviceAbis) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     target->setNamedSettings(AndroidDeviceAbis, deviceAbis); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-17 09:31:56 +02:00
										 |  |  | int AndroidManager::deviceApiLevel(ProjectExplorer::Target *target) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return target->namedSettings(ApiLevelKey).toInt(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AndroidManager::setDeviceApiLevel(ProjectExplorer::Target *target, int level) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-06-18 11:49:14 +02:00
										 |  |  |     qCDebug(androidManagerLog) << "Device API level for the target changed" | 
					
						
							|  |  |  |                                << target->displayName() << level; | 
					
						
							| 
									
										
										
										
											2018-03-17 09:31:56 +02:00
										 |  |  |     target->setNamedSettings(ApiLevelKey, level); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-07 15:03:43 +03:00
										 |  |  | QPair<int, int> AndroidManager::apiLevelRange() | 
					
						
							| 
									
										
										
										
											2013-08-14 13:39:45 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-08-27 16:01:27 +03:00
										 |  |  |     return qMakePair(16, 29); | 
					
						
							| 
									
										
										
										
											2013-08-14 13:39:45 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QString AndroidManager::androidNameForApiLevel(int x) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     switch (x) { | 
					
						
							|  |  |  |     case 4: | 
					
						
							|  |  |  |         return QLatin1String("Android 1.6"); | 
					
						
							|  |  |  |     case 5: | 
					
						
							|  |  |  |         return QLatin1String("Android 2.0"); | 
					
						
							|  |  |  |     case 6: | 
					
						
							|  |  |  |         return QLatin1String("Android 2.0.1"); | 
					
						
							|  |  |  |     case 7: | 
					
						
							|  |  |  |         return QLatin1String("Android 2.1.x"); | 
					
						
							|  |  |  |     case 8: | 
					
						
							|  |  |  |         return QLatin1String("Android 2.2.x"); | 
					
						
							|  |  |  |     case 9: | 
					
						
							|  |  |  |         return QLatin1String("Android 2.3, 2.3.1, 2.3.2"); | 
					
						
							|  |  |  |     case 10: | 
					
						
							|  |  |  |         return QLatin1String("Android 2.3.3, 2.3.4"); | 
					
						
							|  |  |  |     case 11: | 
					
						
							|  |  |  |         return QLatin1String("Android 3.0.x"); | 
					
						
							|  |  |  |     case 12: | 
					
						
							|  |  |  |         return QLatin1String("Android 3.1.x"); | 
					
						
							|  |  |  |     case 13: | 
					
						
							|  |  |  |         return QLatin1String("Android 3.2"); | 
					
						
							|  |  |  |     case 14: | 
					
						
							|  |  |  |         return QLatin1String("Android 4.0, 4.0.1, 4.0.2"); | 
					
						
							|  |  |  |     case 15: | 
					
						
							|  |  |  |         return QLatin1String("Android 4.0.3, 4.0.4"); | 
					
						
							|  |  |  |     case 16: | 
					
						
							|  |  |  |         return QLatin1String("Android 4.1, 4.1.1"); | 
					
						
							|  |  |  |     case 17: | 
					
						
							|  |  |  |         return QLatin1String("Android 4.2, 4.2.2"); | 
					
						
							|  |  |  |     case 18: | 
					
						
							|  |  |  |         return QLatin1String("Android 4.3"); | 
					
						
							| 
									
										
										
										
											2013-11-12 12:14:33 +01:00
										 |  |  |     case 19: | 
					
						
							|  |  |  |         return QLatin1String("Android 4.4"); | 
					
						
							| 
									
										
										
										
											2014-07-16 17:39:24 +02:00
										 |  |  |     case 20: | 
					
						
							| 
									
										
										
										
											2014-11-25 11:37:09 +01:00
										 |  |  |         return QLatin1String("Android 4.4W"); | 
					
						
							| 
									
										
										
										
											2014-11-14 15:29:48 +02:00
										 |  |  |     case 21: | 
					
						
							|  |  |  |         return QLatin1String("Android 5.0"); | 
					
						
							| 
									
										
										
										
											2015-05-20 15:10:50 +03:00
										 |  |  |     case 22: | 
					
						
							|  |  |  |         return QLatin1String("Android 5.1"); | 
					
						
							| 
									
										
										
										
											2015-12-01 11:29:47 +01:00
										 |  |  |     case 23: | 
					
						
							|  |  |  |         return QLatin1String("Android 6.0"); | 
					
						
							| 
									
										
										
										
											2016-09-04 19:28:58 +03:00
										 |  |  |     case 24: | 
					
						
							|  |  |  |         return QLatin1String("Android 7.0"); | 
					
						
							| 
									
										
										
										
											2016-12-07 11:20:37 +02:00
										 |  |  |     case 25: | 
					
						
							|  |  |  |         return QLatin1String("Android 7.1"); | 
					
						
							| 
									
										
										
										
											2017-08-16 12:47:00 +02:00
										 |  |  |     case 26: | 
					
						
							|  |  |  |         return QLatin1String("Android 8.0"); | 
					
						
							| 
									
										
										
										
											2018-06-18 13:17:49 +02:00
										 |  |  |     case 27: | 
					
						
							|  |  |  |         return QLatin1String("Android 8.1"); | 
					
						
							| 
									
										
										
										
											2018-11-22 14:17:11 +01:00
										 |  |  |     case 28: | 
					
						
							|  |  |  |         return QLatin1String("Android 9"); | 
					
						
							| 
									
										
										
										
											2019-08-27 16:01:27 +03:00
										 |  |  |     case 29: | 
					
						
							|  |  |  |         return QLatin1String("Android 10"); | 
					
						
							| 
									
										
										
										
											2013-08-14 13:39:45 +02:00
										 |  |  |     default: | 
					
						
							| 
									
										
										
										
											2014-07-16 17:36:21 +02:00
										 |  |  |         return tr("Unknown Android version. API Level: %1").arg(QString::number(x)); | 
					
						
							| 
									
										
										
										
											2013-08-14 13:39:45 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-22 13:45:41 +02:00
										 |  |  | static void raiseError(const QString &reason) | 
					
						
							| 
									
										
										
										
											2012-04-18 20:30:57 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-07-25 12:19:15 +02:00
										 |  |  |     QMessageBox::critical(nullptr, AndroidManager::tr("Error creating Android templates."), reason); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:30:57 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-28 13:49:26 +02:00
										 |  |  | static bool openXmlFile(QDomDocument &doc, const Utils::FilePath &fileName) | 
					
						
							| 
									
										
										
										
											2012-04-18 20:30:57 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-04-24 15:49:09 +02:00
										 |  |  |     QFile f(fileName.toString()); | 
					
						
							|  |  |  |     if (!f.open(QIODevice::ReadOnly)) | 
					
						
							| 
									
										
										
										
											2012-04-18 20:30:57 +03:00
										 |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-24 15:49:09 +02:00
										 |  |  |     if (!doc.setContent(f.readAll())) { | 
					
						
							| 
									
										
										
										
											2014-07-22 13:45:41 +02:00
										 |  |  |         raiseError(AndroidManager::tr("Cannot parse \"%1\".").arg(fileName.toUserOutput())); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:30:57 +03:00
										 |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-04-24 15:49:09 +02:00
										 |  |  |     return true; | 
					
						
							| 
									
										
										
										
											2012-04-18 20:30:57 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-22 13:45:41 +02:00
										 |  |  | static bool openManifest(ProjectExplorer::Target *target, QDomDocument &doc) | 
					
						
							| 
									
										
										
										
											2012-04-18 20:30:57 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-07-22 13:45:41 +02:00
										 |  |  |     return openXmlFile(doc, AndroidManager::manifestPath(target)); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:30:57 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 18:46:12 +02:00
										 |  |  | static int parseMinSdk(const QDomElement &manifestElem) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QDomElement usesSdk = manifestElem.firstChildElement(QLatin1String("uses-sdk")); | 
					
						
							|  |  |  |     if (usesSdk.isNull()) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     if (usesSdk.hasAttribute(QLatin1String("android:minSdkVersion"))) { | 
					
						
							|  |  |  |         bool ok; | 
					
						
							|  |  |  |         int tmp = usesSdk.attribute(QLatin1String("android:minSdkVersion")).toInt(&ok); | 
					
						
							|  |  |  |         if (ok) | 
					
						
							|  |  |  |             return tmp; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-17 18:24:57 +02:00
										 |  |  | void AndroidManager::installQASIPackage(ProjectExplorer::Target *target, const QString &packagePath) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-08-26 14:19:07 +03:00
										 |  |  |     const QStringList appAbis = AndroidManager::applicationAbis(target); | 
					
						
							|  |  |  |     if (appAbis.isEmpty()) | 
					
						
							| 
									
										
										
										
											2013-10-09 16:24:25 +02:00
										 |  |  |         return; | 
					
						
							| 
									
										
										
										
											2015-06-10 10:34:03 +02:00
										 |  |  |     const int deviceAPILevel = AndroidManager::minimumSDK(target); | 
					
						
							| 
									
										
										
										
											2019-08-26 14:19:07 +03:00
										 |  |  |     AndroidDeviceInfo info = AndroidConfigurations::showDeviceDialog(target->project(), deviceAPILevel, appAbis); | 
					
						
							| 
									
										
										
										
											2015-12-04 10:03:45 +02:00
										 |  |  |     if (!info.isValid()) // aborted
 | 
					
						
							| 
									
										
										
										
											2013-09-17 18:24:57 +02:00
										 |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QString deviceSerialNumber = info.serialNumber; | 
					
						
							|  |  |  |     if (info.type == AndroidDeviceInfo::Emulator) { | 
					
						
							| 
									
										
										
										
											2017-04-03 11:11:17 +02:00
										 |  |  |         deviceSerialNumber = AndroidAvdManager().startAvd(info.avdname); | 
					
						
							| 
									
										
										
										
											2013-09-17 18:24:57 +02:00
										 |  |  |         if (deviceSerialNumber.isEmpty()) | 
					
						
							| 
									
										
										
										
											2013-10-09 16:37:42 +02:00
										 |  |  |             Core::MessageManager::write(tr("Starting Android virtual device failed.")); | 
					
						
							| 
									
										
										
										
											2013-09-17 18:24:57 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QStringList arguments = AndroidDeviceInfo::adbSelector(deviceSerialNumber); | 
					
						
							| 
									
										
										
										
											2018-08-07 11:12:45 +02:00
										 |  |  |     arguments << "install" << "-r " << packagePath; | 
					
						
							|  |  |  |     QString error; | 
					
						
							|  |  |  |     if (!runAdbCommandDetached(arguments, &error, true)) | 
					
						
							|  |  |  |         Core::MessageManager::write(tr("Android package installation failed.\n%1").arg(error)); | 
					
						
							| 
									
										
										
										
											2013-09-17 18:24:57 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool AndroidManager::checkKeystorePassword(const QString &keystorePath, const QString &keystorePasswd) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (keystorePasswd.isEmpty()) | 
					
						
							|  |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2019-06-06 16:27:55 +02:00
										 |  |  |     const CommandLine cmd(AndroidConfigurations::currentConfig().keytoolPath(), | 
					
						
							|  |  |  |                           {"-list", "-keystore", keystorePath, "--storepass", keystorePasswd}); | 
					
						
							|  |  |  |     SynchronousProcess proc; | 
					
						
							| 
									
										
										
										
											2016-04-29 16:52:58 +02:00
										 |  |  |     proc.setTimeoutS(10); | 
					
						
							| 
									
										
										
										
											2019-06-06 16:27:55 +02:00
										 |  |  |     SynchronousProcessResponse response = proc.run(cmd); | 
					
						
							| 
									
										
										
										
											2016-04-29 16:52:58 +02:00
										 |  |  |     return (response.result == Utils::SynchronousProcessResponse::Finished && response.exitCode == 0); | 
					
						
							| 
									
										
										
										
											2013-09-17 18:24:57 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool AndroidManager::checkCertificatePassword(const QString &keystorePath, const QString &keystorePasswd, const QString &alias, const QString &certificatePasswd) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // assumes that the keystore password is correct
 | 
					
						
							| 
									
										
										
										
											2017-02-22 15:09:35 +01:00
										 |  |  |     QStringList arguments = {"-certreq", "-keystore", keystorePath, | 
					
						
							|  |  |  |                              "--storepass", keystorePasswd, "-alias", alias, "-keypass"}; | 
					
						
							| 
									
										
										
										
											2013-09-17 18:24:57 +02:00
										 |  |  |     if (certificatePasswd.isEmpty()) | 
					
						
							|  |  |  |         arguments << keystorePasswd; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         arguments << certificatePasswd; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-06 16:27:55 +02:00
										 |  |  |     SynchronousProcess proc; | 
					
						
							| 
									
										
										
										
											2016-04-29 16:52:58 +02:00
										 |  |  |     proc.setTimeoutS(10); | 
					
						
							| 
									
										
										
										
											2019-06-06 16:27:55 +02:00
										 |  |  |     SynchronousProcessResponse response | 
					
						
							|  |  |  |             = proc.run({AndroidConfigurations::currentConfig().keytoolPath(), arguments}); | 
					
						
							|  |  |  |     return response.result == SynchronousProcessResponse::Finished && response.exitCode == 0; | 
					
						
							| 
									
										
										
										
											2017-01-10 16:33:56 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool AndroidManager::checkCertificateExists(const QString &keystorePath, | 
					
						
							|  |  |  |                                             const QString &keystorePasswd, const QString &alias) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // assumes that the keystore password is correct
 | 
					
						
							| 
									
										
										
										
											2017-02-07 16:59:21 +01:00
										 |  |  |     QStringList arguments = { "-list", "-keystore", keystorePath, | 
					
						
							|  |  |  |                               "--storepass", keystorePasswd, "-alias", alias }; | 
					
						
							| 
									
										
										
										
											2017-01-10 16:33:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-06 16:27:55 +02:00
										 |  |  |     SynchronousProcess proc; | 
					
						
							| 
									
										
										
										
											2017-01-10 16:33:56 +01:00
										 |  |  |     proc.setTimeoutS(10); | 
					
						
							| 
									
										
										
										
											2019-06-06 16:27:55 +02:00
										 |  |  |     SynchronousProcessResponse response | 
					
						
							|  |  |  |             = proc.run({AndroidConfigurations::currentConfig().keytoolPath(), arguments}); | 
					
						
							|  |  |  |     return response.result == SynchronousProcessResponse::Finished && response.exitCode == 0; | 
					
						
							| 
									
										
										
										
											2013-09-17 18:24:57 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-25 12:19:15 +02:00
										 |  |  | using GradleProperties = QMap<QByteArray, QByteArray>; | 
					
						
							| 
									
										
										
										
											2014-09-22 16:20:51 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | static GradleProperties readGradleProperties(const QString &path) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     GradleProperties properties; | 
					
						
							|  |  |  |     QFile file(path); | 
					
						
							|  |  |  |     if (!file.open(QIODevice::ReadOnly)) | 
					
						
							|  |  |  |         return properties; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     foreach (const QByteArray &line, file.readAll().split('\n')) { | 
					
						
							|  |  |  |         if (line.trimmed().startsWith('#')) | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         QList<QByteArray> prop(line.split('=')); | 
					
						
							|  |  |  |         if (prop.size() > 1) | 
					
						
							|  |  |  |             properties[prop.at(0).trimmed()] = prop.at(1).trimmed(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     file.close(); | 
					
						
							|  |  |  |     return properties; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static bool mergeGradleProperties(const QString &path, GradleProperties properties) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QFile::remove(path + QLatin1Char('~')); | 
					
						
							|  |  |  |     QFile::rename(path, path + QLatin1Char('~')); | 
					
						
							|  |  |  |     QFile file(path); | 
					
						
							|  |  |  |     if (!file.open(QIODevice::Truncate | QIODevice::WriteOnly | QIODevice::Text)) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QFile oldFile(path + QLatin1Char('~')); | 
					
						
							|  |  |  |     if (oldFile.open(QIODevice::ReadOnly)) { | 
					
						
							|  |  |  |         while (!oldFile.atEnd()) { | 
					
						
							|  |  |  |             QByteArray line(oldFile.readLine()); | 
					
						
							|  |  |  |             QList<QByteArray> prop(line.split('=')); | 
					
						
							|  |  |  |             if (prop.size() > 1) { | 
					
						
							|  |  |  |                 GradleProperties::iterator it = properties.find(prop.at(0).trimmed()); | 
					
						
							|  |  |  |                 if (it != properties.end()) { | 
					
						
							|  |  |  |                     file.write(it.key() + '=' + it.value() + '\n'); | 
					
						
							|  |  |  |                     properties.erase(it); | 
					
						
							|  |  |  |                     continue; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             file.write(line); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         oldFile.close(); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         file.write("## This file is automatically generated by QtCreator.\n" | 
					
						
							|  |  |  |                    "#\n" | 
					
						
							|  |  |  |                    "# This file must *NOT* be checked into Version Control Systems,\n" | 
					
						
							|  |  |  |                    "# as it contains information specific to your local configuration.\n\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-01 11:19:32 +02:00
										 |  |  |     for (GradleProperties::const_iterator it = properties.constBegin(); it != properties.constEnd(); | 
					
						
							|  |  |  |          ++it) | 
					
						
							| 
									
										
										
										
											2014-09-22 16:20:51 +03:00
										 |  |  |         file.write(it.key() + '=' + it.value() + '\n'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     file.close(); | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-01 10:12:34 +02:00
										 |  |  | bool AndroidManager::updateGradleProperties(ProjectExplorer::Target *target, const QString &buildKey) | 
					
						
							| 
									
										
										
										
											2014-09-22 16:20:51 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-02-06 12:50:51 +01:00
										 |  |  |     QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(target->kit()); | 
					
						
							| 
									
										
										
										
											2014-09-22 16:20:51 +03:00
										 |  |  |     if (!version) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-01 10:12:34 +02:00
										 |  |  |     QString key = buildKey; | 
					
						
							|  |  |  |     if (key.isEmpty()) { | 
					
						
							|  |  |  |         // FIXME: This case is triggered from AndroidBuildApkWidget::createApplicationGroup
 | 
					
						
							|  |  |  |         // and should be avoided.
 | 
					
						
							|  |  |  |         if (RunConfiguration *rc = target->activeRunConfiguration()) | 
					
						
							|  |  |  |             key = rc->buildKey(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QTC_ASSERT(!key.isEmpty(), return false); | 
					
						
							|  |  |  |     const ProjectNode *node = target->project()->findNodeForBuildKey(key); | 
					
						
							| 
									
										
										
										
											2018-12-05 10:29:48 +01:00
										 |  |  |     if (!node) | 
					
						
							| 
									
										
										
										
											2018-05-09 09:55:37 +02:00
										 |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2014-09-22 16:20:51 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-06 14:17:17 +02:00
										 |  |  |     const QString sourceDirName = node->data(Constants::AndroidPackageSourceDir).toString(); | 
					
						
							|  |  |  |     QFileInfo sourceDirInfo(sourceDirName); | 
					
						
							| 
									
										
										
										
											2019-05-28 13:49:26 +02:00
										 |  |  |     const FilePath packageSourceDir = FilePath::fromString(sourceDirInfo.canonicalFilePath()) | 
					
						
							| 
									
										
										
										
											2019-05-20 17:28:20 +02:00
										 |  |  |             .pathAppended("gradlew"); | 
					
						
							|  |  |  |     if (!packageSourceDir.exists()) | 
					
						
							| 
									
										
										
										
											2014-09-22 16:20:51 +03:00
										 |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-28 13:49:26 +02:00
										 |  |  |     const FilePath wrapperProps = packageSourceDir.pathAppended("gradle/wrapper/gradle-wrapper.properties"); | 
					
						
							| 
									
										
										
										
											2016-01-05 15:48:51 +02:00
										 |  |  |     if (wrapperProps.exists()) { | 
					
						
							|  |  |  |         GradleProperties wrapperProperties = readGradleProperties(wrapperProps.toString()); | 
					
						
							|  |  |  |         QString distributionUrl = QString::fromLocal8Bit(wrapperProperties["distributionUrl"]); | 
					
						
							| 
									
										
										
										
											2017-03-22 13:45:20 +02:00
										 |  |  |         // Update only old gradle distributionUrl
 | 
					
						
							|  |  |  |         if (distributionUrl.endsWith(QLatin1String("distributions/gradle-1.12-all.zip"))) { | 
					
						
							| 
									
										
										
										
											2016-01-05 15:48:51 +02:00
										 |  |  |             wrapperProperties["distributionUrl"] = "https\\://services.gradle.org/distributions/gradle-2.2.1-all.zip"; | 
					
						
							|  |  |  |             mergeGradleProperties(wrapperProps.toString(), wrapperProperties); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-22 16:20:51 +03:00
										 |  |  |     GradleProperties localProperties; | 
					
						
							|  |  |  |     localProperties["sdk.dir"] = AndroidConfigurations::currentConfig().sdkLocation().toString().toLocal8Bit(); | 
					
						
							| 
									
										
										
										
											2019-05-28 13:49:26 +02:00
										 |  |  |     const FilePath localPropertiesFile = packageSourceDir.pathAppended("local.properties"); | 
					
						
							| 
									
										
										
										
											2019-05-20 17:28:20 +02:00
										 |  |  |     if (!mergeGradleProperties(localPropertiesFile.toString(), localProperties)) | 
					
						
							| 
									
										
										
										
											2014-09-22 16:20:51 +03:00
										 |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-20 17:28:20 +02:00
										 |  |  |     const QString gradlePropertiesPath = packageSourceDir.pathAppended("gradle.properties").toString(); | 
					
						
							| 
									
										
										
										
											2014-09-22 16:20:51 +03:00
										 |  |  |     GradleProperties gradleProperties = readGradleProperties(gradlePropertiesPath); | 
					
						
							| 
									
										
										
										
											2019-09-30 14:34:31 +02:00
										 |  |  |     gradleProperties["qt5AndroidDir"] = (version->prefix().toString() + "/src/android/java") | 
					
						
							|  |  |  |                                             .toLocal8Bit(); | 
					
						
							| 
									
										
										
										
											2014-09-22 16:20:51 +03:00
										 |  |  |     gradleProperties["buildDir"] = ".build"; | 
					
						
							|  |  |  |     gradleProperties["androidCompileSdkVersion"] = buildTargetSDK(target).split(QLatin1Char('-')).last().toLocal8Bit(); | 
					
						
							|  |  |  |     if (gradleProperties["androidBuildToolsVersion"].isEmpty()) { | 
					
						
							| 
									
										
										
										
											2017-09-04 14:54:50 +02:00
										 |  |  |         QVersionNumber buildtoolVersion = AndroidConfigurations::currentConfig().buildToolsVersion(); | 
					
						
							|  |  |  |         if (buildtoolVersion.isNull()) | 
					
						
							| 
									
										
										
										
											2014-09-22 16:20:51 +03:00
										 |  |  |             return false; | 
					
						
							| 
									
										
										
										
											2017-09-04 14:54:50 +02:00
										 |  |  |         gradleProperties["androidBuildToolsVersion"] = buildtoolVersion.toString().toLocal8Bit(); | 
					
						
							| 
									
										
										
										
											2014-09-22 16:20:51 +03:00
										 |  |  |     } | 
					
						
							|  |  |  |     return mergeGradleProperties(gradlePropertiesPath, gradleProperties); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-28 13:49:26 +02:00
										 |  |  | int AndroidManager::findApiLevel(const Utils::FilePath &platformPath) | 
					
						
							| 
									
										
										
										
											2017-03-30 14:43:13 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     int apiLevel = -1; | 
					
						
							| 
									
										
										
										
											2019-05-28 13:49:26 +02:00
										 |  |  |     const Utils::FilePath propertiesPath = platformPath.pathAppended("/source.properties"); | 
					
						
							| 
									
										
										
										
											2017-03-30 14:43:13 +02:00
										 |  |  |     if (propertiesPath.exists()) { | 
					
						
							|  |  |  |         QSettings sdkProperties(propertiesPath.toString(), QSettings::IniFormat); | 
					
						
							|  |  |  |         bool validInt = false; | 
					
						
							|  |  |  |         apiLevel = sdkProperties.value(ApiLevelKey).toInt(&validInt); | 
					
						
							|  |  |  |         if (!validInt) | 
					
						
							|  |  |  |             apiLevel = -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return apiLevel; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-07 11:12:45 +02:00
										 |  |  | QProcess *AndroidManager::runAdbCommandDetached(const QStringList &args, QString *err, | 
					
						
							|  |  |  |                                                 bool deleteOnFinish) | 
					
						
							| 
									
										
										
										
											2018-07-03 11:51:28 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-08-07 11:12:45 +02:00
										 |  |  |     std::unique_ptr<QProcess> p(new QProcess); | 
					
						
							| 
									
										
										
										
											2018-07-03 11:51:28 +02:00
										 |  |  |     const QString adb = AndroidConfigurations::currentConfig().adbToolPath().toString(); | 
					
						
							| 
									
										
										
										
											2018-08-07 11:12:45 +02:00
										 |  |  |     qCDebug(androidManagerLog) << "Running command:" << adb << args.join(' '); | 
					
						
							|  |  |  |     p->start(adb, args); | 
					
						
							|  |  |  |     if (p->waitForStarted(500) && p->state() == QProcess::Running) { | 
					
						
							|  |  |  |         if (deleteOnFinish) { | 
					
						
							| 
									
										
										
										
											2019-02-26 09:40:49 +01:00
										 |  |  |             connect(p.get(), QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), | 
					
						
							| 
									
										
										
										
											2018-08-07 11:12:45 +02:00
										 |  |  |                     p.get(), &QObject::deleteLater); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return p.release(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QString errorStr = QString::fromUtf8(p->readAllStandardError()); | 
					
						
							|  |  |  |     qCDebug(androidManagerLog) << "Running command failed" << adb << args.join(' ') << errorStr; | 
					
						
							|  |  |  |     if (err) | 
					
						
							|  |  |  |         *err = errorStr; | 
					
						
							|  |  |  |     return nullptr; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-06 16:27:55 +02:00
										 |  |  | SdkToolResult AndroidManager::runCommand(const CommandLine &command, | 
					
						
							| 
									
										
										
										
											2018-08-07 11:12:45 +02:00
										 |  |  |                                          const QByteArray &writeData, int timeoutS) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Android::SdkToolResult cmdResult; | 
					
						
							|  |  |  |     Utils::SynchronousProcess cmdProc; | 
					
						
							|  |  |  |     cmdProc.setTimeoutS(timeoutS); | 
					
						
							| 
									
										
										
										
											2019-06-06 16:27:55 +02:00
										 |  |  |     qCDebug(androidManagerLog) << "Running command: " << command.toUserOutput(); | 
					
						
							|  |  |  |     SynchronousProcessResponse response = cmdProc.run(command, writeData); | 
					
						
							| 
									
										
										
										
											2018-08-07 11:12:45 +02:00
										 |  |  |     cmdResult.m_stdOut = response.stdOut().trimmed(); | 
					
						
							|  |  |  |     cmdResult.m_stdErr = response.stdErr().trimmed(); | 
					
						
							|  |  |  |     cmdResult.m_success = response.result == Utils::SynchronousProcessResponse::Finished; | 
					
						
							| 
									
										
										
										
											2019-06-06 16:27:55 +02:00
										 |  |  |     qCDebug(androidManagerLog) << "Running command finshed:" << command.toUserOutput() | 
					
						
							| 
									
										
										
										
											2018-08-07 11:12:45 +02:00
										 |  |  |                                << "Success:" << cmdResult.m_success | 
					
						
							|  |  |  |                                << "Output:" << response.allRawOutput(); | 
					
						
							|  |  |  |     if (!cmdResult.success()) | 
					
						
							| 
									
										
										
										
											2019-06-06 16:27:55 +02:00
										 |  |  |         cmdResult.m_exitMessage = response.exitMessage(command.executable().toString(), timeoutS); | 
					
						
							| 
									
										
										
										
											2018-08-07 11:12:45 +02:00
										 |  |  |     return cmdResult; | 
					
						
							| 
									
										
										
										
											2018-07-03 11:51:28 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-07 11:12:45 +02:00
										 |  |  | SdkToolResult AndroidManager::runAdbCommand(const QStringList &args, | 
					
						
							|  |  |  |                                             const QByteArray &writeData, int timeoutS) | 
					
						
							| 
									
										
										
										
											2018-07-03 11:51:28 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-06-06 16:27:55 +02:00
										 |  |  |     return runCommand({AndroidConfigurations::currentConfig().adbToolPath(), args}, | 
					
						
							| 
									
										
										
										
											2018-08-07 11:12:45 +02:00
										 |  |  |                       writeData, timeoutS); | 
					
						
							| 
									
										
										
										
											2018-07-03 11:51:28 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2018-07-03 11:53:25 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-07 11:12:45 +02:00
										 |  |  | SdkToolResult AndroidManager::runAaptCommand(const QStringList &args, int timeoutS) | 
					
						
							| 
									
										
										
										
											2018-07-03 11:53:25 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-06-06 16:27:55 +02:00
										 |  |  |     return runCommand({AndroidConfigurations::currentConfig().aaptToolPath(), args}, {}, | 
					
						
							| 
									
										
										
										
											2018-08-07 11:12:45 +02:00
										 |  |  |                       timeoutS); | 
					
						
							| 
									
										
										
										
											2018-07-03 11:53:25 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2013-10-16 11:02:37 +02:00
										 |  |  | } // namespace Android
 |