summaryrefslogtreecommitdiff
path: root/src/androiddeployqt
diff options
context:
space:
mode:
authorBogDan Vatra <bogdan@kde.org>2014-08-07 11:33:23 +0300
committerBogDan Vatra <bogdan@kde.org>2014-08-07 12:28:01 +0200
commit28f0d610e3e4c5f1e244bcc73a13b6dda84b8574 (patch)
treea6871faf428797d136564dca784473d325a0bb02 /src/androiddeployqt
parentf911cebdcc4695d0b7589a3c122c19dd09e445c5 (diff)
downloadqttools-28f0d610e3e4c5f1e244bcc73a13b6dda84b8574.tar.gz
Android: Say hello to gradle support!
Using gradle it doesn't need ant to be installed anymore. It's also much way faster than ant (on multiple builds), on my computer is 25-50% faster than ant. [ChangeLog][Android][androiddeployqt] Added Gradle support to build the APK. Change-Id: I3ed2c7215e38a43f5d5f62c3e6eedb601182e81a Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@digia.com>
Diffstat (limited to 'src/androiddeployqt')
-rw-r--r--src/androiddeployqt/main.cpp420
1 files changed, 351 insertions, 69 deletions
diff --git a/src/androiddeployqt/main.cpp b/src/androiddeployqt/main.cpp
index 6b1d7bbc2..ca5d7e343 100644
--- a/src/androiddeployqt/main.cpp
+++ b/src/androiddeployqt/main.cpp
@@ -105,6 +105,7 @@ struct Options
, timing(false)
, generateAssetsFileList(true)
, build(true)
+ , gradle(false)
, minimumAndroidVersion(9)
, targetAndroidVersion(10)
, deploymentMechanism(Bundled)
@@ -137,6 +138,7 @@ struct Options
bool timing;
bool generateAssetsFileList;
bool build;
+ bool gradle;
QTime timer;
// External tools
@@ -279,6 +281,37 @@ static QString shellQuote(const QString &arg)
}
+void deleteMissingFiles(const Options &options, const QDir &srcDir, const QDir &dstDir)
+{
+ if (options.verbose)
+ fprintf(stdout, "Delete missing files %s %s\n", qPrintable(srcDir.absolutePath()), qPrintable(dstDir.absolutePath()));
+
+ QFileInfoList srcEntries = srcDir.entryInfoList(QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs);
+ QFileInfoList dstEntries = dstDir.entryInfoList(QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs);
+ foreach (const QFileInfo &dst, dstEntries) {
+ bool found = false;
+ foreach (const QFileInfo &src, srcEntries)
+ if (dst.fileName() == src.fileName()) {
+ if (dst.isDir())
+ deleteMissingFiles(options, src.absoluteFilePath(), dst.absoluteFilePath());
+ found = true;
+ break;
+ }
+
+ if (!found) {
+ if (options.verbose)
+ fprintf(stdout, "%s not found in %s, removing it.\n", qPrintable(dst.fileName()), qPrintable(srcDir.absolutePath()));
+
+ if (dst.isDir())
+ deleteRecursively(dst.absolutePath());
+ else
+ QFile::remove(dst.absoluteFilePath());
+ }
+ }
+ fflush(stdout);
+}
+
+
Options parseOptions()
{
Options options;
@@ -289,8 +322,11 @@ Options parseOptions()
if (argument.compare(QLatin1String("--output"), Qt::CaseInsensitive) == 0) {
if (i + 1 == arguments.size())
options.helpRequested = true;
- else
- options.outputDirectory = arguments.at(++i);
+ else {
+ options.outputDirectory = arguments.at(++i).trimmed();
+ if (!options.outputDirectory.endsWith(QLatin1Char('/')))
+ options.outputDirectory += QLatin1Char('/');
+ }
} else if (argument.compare(QLatin1String("--input"), Qt::CaseInsensitive) == 0) {
if (i + 1 == arguments.size())
options.helpRequested = true;
@@ -313,6 +349,8 @@ Options parseOptions()
options.helpRequested = true;
} else if (argument.compare(QLatin1String("--verbose"), Qt::CaseInsensitive) == 0) {
options.verbose = true;
+ } else if (argument.compare(QLatin1String("--gradle"), Qt::CaseInsensitive) == 0) {
+ options.gradle = true;
} else if (argument.compare(QLatin1String("--ant"), Qt::CaseInsensitive) == 0) {
if (i + 1 == arguments.size())
options.helpRequested = true;
@@ -453,6 +491,7 @@ void printHelp()
" --android-platform <platform>: Builds against the given android\n"
" platform. By default, the highest available version will be\n"
" used.\n"
+ " --gradle. Use gradle instead of ant to create and install the apk.\n"
" --ant <path/to/ant>: If unspecified, ant from the PATH will be\n"
" used.\n"
" --release: Builds a package ready for release. By default, the\n"
@@ -544,6 +583,7 @@ bool copyFileIfNewer(const QString &sourceFileName,
return false;
} else if (verbose) {
fprintf(stdout, " -- Copied %s\n", qPrintable(destinationFileName));
+ fflush(stdout);
}
return true;
@@ -815,23 +855,73 @@ bool copyFiles(const QDir &sourceDirectory, const QDir &destinationDirectory, bo
return true;
}
-bool copyAndroidTemplate(const Options &options)
+void cleanTopFolders(const Options &options, const QDir &srcDir, const QString &dstDir)
{
- if (options.verbose)
- fprintf(stdout, "Copying Android package template.\n");
+ foreach (const QFileInfo &dir, srcDir.entryInfoList(QDir::NoDotAndDotDot | QDir::Dirs)) {
+ if (dir.fileName() != QLatin1String("libs"))
+ deleteMissingFiles(options, dir.absoluteFilePath(), dstDir + dir.fileName());
+ }
+}
+
+void cleanAndroidFiles(const Options &options)
+{
+ deleteRecursively(options.outputDirectory + "assets");
+
+ if (!options.androidSourceDirectory.isEmpty())
+ cleanTopFolders(options, options.androidSourceDirectory, options.outputDirectory);
+
+ cleanTopFolders(options, options.qtInstallDirectory + QLatin1String("/src/android/templates"), options.outputDirectory);
+ cleanTopFolders(options, options.qtInstallDirectory + QLatin1String("/src/android/java"), options.outputDirectory + "__qt5__android__files__");
+}
- QDir sourceDirectory(options.qtInstallDirectory + QLatin1String("/src/android/java"));
+bool copyAndroidTemplate(const Options &options, const QString &androidTemplate, const QString &outDirPrefix = QString())
+{
+ QDir sourceDirectory(options.qtInstallDirectory + androidTemplate);
+ if (!sourceDirectory.exists()) {
+ fprintf(stderr, "Cannot find template directory %s\n", qPrintable(sourceDirectory.absolutePath()));
+ return false;
+ }
+
+ QString outDir = options.outputDirectory + outDirPrefix;
+
+ if (!QDir::current().mkpath(outDir)) {
+ fprintf(stderr, "Cannot create output directory %s\n", qPrintable(options.outputDirectory));
+ return false;
+ }
+
+ return copyFiles(sourceDirectory, QDir(outDir), options.verbose);
+}
+
+bool copyGradleTemplate(const Options &options)
+{
+ QDir sourceDirectory(options.sdkPath + "/tools/templates/gradle/wrapper");
if (!sourceDirectory.exists()) {
fprintf(stderr, "Cannot find template directory %s\n", qPrintable(sourceDirectory.absolutePath()));
return false;
}
- if (!QDir::current().mkpath(options.outputDirectory)) {
+ QString outDir(options.outputDirectory);
+ if (!QDir::current().mkpath(outDir)) {
fprintf(stderr, "Cannot create output directory %s\n", qPrintable(options.outputDirectory));
return false;
}
- return copyFiles(sourceDirectory, QDir(options.outputDirectory), options.verbose);
+ return copyFiles(sourceDirectory, QDir(outDir), options.verbose);
+}
+
+bool copyAndroidTemplate(const Options &options)
+{
+ if (options.verbose)
+ fprintf(stdout, "Copying Android package template.\n");
+
+ if (options.gradle && !copyGradleTemplate(options))
+ return false;
+
+ if (!copyAndroidTemplate(options, QLatin1String("/src/android/templates")))
+ return false;
+
+ return copyAndroidTemplate(options, QLatin1String("/src/android/java"),
+ options.gradle ? QLatin1String("/__qt5__android__files__/") : QString());
}
bool copyAndroidSources(const Options &options)
@@ -949,10 +1039,14 @@ bool updateFile(const QString &fileName, const QHash<QString, QString> &replacem
bool hasReplacements = false;
QHash<QString, QString>::const_iterator it;
for (it = replacements.constBegin(); it != replacements.constEnd(); ++it) {
- int index = contents.indexOf(it.key().toUtf8());
- if (index >= 0) {
- contents.replace(index, it.key().length(), it.value().toUtf8());
- hasReplacements = true;
+ forever {
+ int index = contents.indexOf(it.key().toUtf8());
+ if (index >= 0) {
+ contents.replace(index, it.key().length(), it.value().toUtf8());
+ hasReplacements = true;
+ } else {
+ break;
+ }
}
}
@@ -1047,6 +1141,65 @@ bool updateLibsXml(const Options &options)
return true;
}
+bool updateStringsXml(const Options &options)
+{
+ if (options.verbose)
+ fprintf(stdout, " -- res/values/strings.xml\n");
+
+ QHash<QString, QString> replacements;
+ replacements["<!-- %%INSERT_APP_NAME%% -->"] = QFileInfo(options.applicationBinary).baseName().mid(sizeof("lib") - 1);
+
+ QString fileName = options.outputDirectory + QLatin1String("/res/values/strings.xml");
+ if (!QFile::exists(fileName)) {
+ if (options.verbose)
+ fprintf(stdout, " -- Create strings.xml since it's missing.\n");
+ QFile file(fileName);
+ if (!file.open(QIODevice::WriteOnly)) {
+ fprintf(stderr, "Can't open %s for writing.\n", qPrintable(fileName));
+ return false;
+ }
+ file.write(QByteArray("<?xml version='1.0' encoding='utf-8'?><resources><string name=\"app_name\">")
+ .append(QFileInfo(options.applicationBinary).baseName().mid(sizeof("lib") - 1).toLatin1())
+ .append("</string></resources>\n"));
+ return true;
+ }
+
+ if (!updateFile(fileName, replacements))
+ return false;
+
+ if (options.gradle)
+ return true;
+
+ // ant can't (easily) build multiple res folders,
+ // so we need to replace the "<!-- %%INSERT_STRINGS -->" placeholder
+ // from the main res folder
+ QFile stringsXml(fileName);
+ if (!stringsXml.open(QIODevice::ReadOnly)) {
+ fprintf(stderr, "Cannot open %s for reading.\n", qPrintable(fileName));
+ return false;
+ }
+
+ QXmlStreamReader reader(&stringsXml);
+ while (!reader.atEnd()) {
+ reader.readNext();
+ if (reader.isStartElement() &&
+ reader.name() == QLatin1String("string") &&
+ reader.attributes().hasAttribute(QLatin1String("name")) &&
+ reader.attributes().value(QLatin1String("name")) == QLatin1String("app_name")) {
+ return true;
+ }
+ }
+
+ replacements.clear();
+ replacements["<!-- %%INSERT_STRINGS -->"] = QString(QLatin1String("<string name=\"app_name\">%1</string>\n"))
+ .arg(QFileInfo(options.applicationBinary).baseName().mid(sizeof("lib") - 1));
+
+ if (!updateFile(fileName, replacements))
+ return false;
+
+ return true;
+}
+
bool updateAndroidManifest(Options &options)
{
if (options.verbose)
@@ -1089,6 +1242,7 @@ bool updateAndroidManifest(Options &options)
}
QHash<QString, QString> replacements;
+ replacements[QLatin1String("-- %%INSERT_APP_NAME%% --")] = QFileInfo(options.applicationBinary).baseName().mid(sizeof("lib") - 1);
replacements[QLatin1String("-- %%INSERT_APP_LIB_NAME%% --")] = QFileInfo(options.applicationBinary).baseName().mid(sizeof("lib") - 1);
replacements[QLatin1String("-- %%INSERT_LOCAL_LIBS%% --")] = localLibs.join(QLatin1Char(':'));
replacements[QLatin1String("-- %%INSERT_LOCAL_JARS%% --")] = options.localJars.join(QLatin1Char(':'));
@@ -1117,6 +1271,7 @@ bool updateAndroidManifest(Options &options)
return false;
// read the package, min & target sdk API levels from manifest file.
+ bool checkOldAndroidLabelString = false;
QFile androidManifestXml(androidManifestPath);
if (androidManifestXml.exists()) {
if (!androidManifestXml.open(QIODevice::ReadOnly)) {
@@ -1141,6 +1296,11 @@ bool updateAndroidManifest(Options &options)
if (reader.attributes().hasAttribute(QLatin1String("android:targetSdkVersion")))
options.targetAndroidVersion = reader.attributes().value(QLatin1String("android:targetSdkVersion")).toInt();
+ } else if ((reader.name() == QLatin1String("application") ||
+ reader.name() == QLatin1String("activity")) &&
+ reader.attributes().hasAttribute(QLatin1String("android:label")) &&
+ reader.attributes().value(QLatin1String("android:label")) == QLatin1String("@string/app_name")) {
+ checkOldAndroidLabelString = true;
}
}
}
@@ -1153,26 +1313,9 @@ bool updateAndroidManifest(Options &options)
fprintf(stderr, "No android manifest file");
return false;
}
- return true;
-}
-
-bool updateStringsXml(const Options &options)
-{
- if (options.verbose)
- fprintf(stdout, " -- res/values/strings.xml\n");
-
- QHash<QString, QString> replacements;
- replacements["<!-- %%INSERT_APP_NAME%% -->"] = QFileInfo(options.applicationBinary).baseName().mid(sizeof("lib") - 1);
-
- QString fileName = options.outputDirectory + QLatin1String("/res/values/strings.xml");
- if (!QFile::exists(fileName)) {
- if (options.verbose)
- fprintf(stdout, " -- Skipping update of strings.xml since it's missing.\n");
- return true;
- }
- if (!updateFile(fileName, replacements))
- return false;
+ if (checkOldAndroidLabelString)
+ updateStringsXml(options);
return true;
}
@@ -1182,7 +1325,12 @@ bool updateJavaFiles(const Options &options)
if (options.verbose)
fprintf(stdout, " -- /src/org/qtproject/qt5/android/bindings/QtActivity.java\n");
- QString fileName(options.outputDirectory + QLatin1String("/src/org/qtproject/qt5/android/bindings/QtActivity.java"));
+
+ QString fileName(options.outputDirectory +
+ (options.gradle ? QLatin1String("/__qt5__android__files__")
+ : QString()) +
+ QLatin1String("/src/org/qtproject/qt5/android/bindings/QtActivity.java"));
+
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly)) {
fprintf(stderr, "Cannot open %s.\n", qPrintable(fileName));
@@ -1247,9 +1395,6 @@ bool updateAndroidFiles(Options &options)
if (!updateAndroidManifest(options))
return false;
- if (!updateStringsXml(options))
- return false;
-
if (!updateJavaFiles(options))
return false;
@@ -2089,10 +2234,10 @@ QString findInPath(const QString &fileName)
return QString();
}
-bool buildAndroidProject(const Options &options)
+bool buildAntProject(const Options &options)
{
if (options.verbose)
- fprintf(stdout, "Building Android package.\n");
+ fprintf(stdout, "Building Android package using ant.\n");
QString antTool = options.antTool;
if (antTool.isEmpty()) {
@@ -2126,8 +2271,10 @@ bool buildAndroidProject(const Options &options)
}
char buffer[512];
- while (fgets(buffer, sizeof(buffer), antCommand) != 0)
+ while (fgets(buffer, sizeof(buffer), antCommand) != 0) {
fprintf(stdout, "%s", buffer);
+ fflush(stdout);
+ }
int errorCode = pclose(antCommand);
if (errorCode != 0) {
@@ -2145,6 +2292,131 @@ bool buildAndroidProject(const Options &options)
return true;
}
+typedef QMap<QByteArray, QByteArray> GradleProperties;
+
+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)) {
+ fprintf(stderr, "Can't open file: %s for writing\n", qPrintable(file.fileName()));
+ 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();
+ }
+
+ for (GradleProperties::const_iterator it = properties.begin(); it != properties.end(); ++it)
+ file.write(it.key() + '=' + it.value() + '\n');
+
+ file.close();
+ return true;
+}
+
+bool buildGradleProject(const Options &options)
+{
+ GradleProperties localProperties;
+ localProperties["sdk.dir"] = options.sdkPath.toLocal8Bit();
+
+ if (!mergeGradleProperties(options.outputDirectory + QLatin1String("local.properties"), localProperties))
+ return false;
+
+ QString gradlePropertiesPath = options.outputDirectory + QLatin1String("gradle.properties");
+ GradleProperties gradleProperties = readGradleProperties(gradlePropertiesPath);
+ gradleProperties["buildDir"] = "build";
+ gradleProperties["qt5AndroidDir"] = "__qt5__android__files__";
+ gradleProperties["androidCompileSdkVersion"] = options.androidPlatform.split(QLatin1Char('-')).last().toLocal8Bit();
+ if (gradleProperties["androidBuildToolsVersion"].isEmpty())
+ gradleProperties["androidBuildToolsVersion"] = options.sdkBuildToolsVersion.toLocal8Bit();
+
+ if (!mergeGradleProperties(gradlePropertiesPath, gradleProperties))
+ return false;
+
+#if defined(Q_OS_WIN32)
+ QString gradlePath(options.outputDirectory + QLatin1String("gradlew.bat"));
+#else
+ QString gradlePath(options.outputDirectory + QLatin1String("gradlew"));
+#endif
+
+ QString oldPath = QDir::currentPath();
+ if (!QDir::setCurrent(options.outputDirectory)) {
+ fprintf(stderr, "Cannot current path to %s\n", qPrintable(options.outputDirectory));
+ return false;
+ }
+
+ QString commandLine = QString::fromLatin1("%1 --no-daemon %2").arg(shellQuote(gradlePath)).arg(options.releasePackage ? QLatin1String(" assembleRelease") : QLatin1String(" assembleDebug"));
+ if (options.verbose)
+ commandLine += QLatin1String(" --info");
+
+ FILE *gradleCommand = openProcess(commandLine);
+ if (gradleCommand == 0) {
+ fprintf(stderr, "Cannot run gradle command: %s\n.", qPrintable(commandLine));
+ return false;
+ }
+
+ char buffer[512];
+ while (fgets(buffer, sizeof(buffer), gradleCommand) != 0) {
+ fprintf(stdout, "%s", buffer);
+ fflush(stdout);
+ }
+
+ int errorCode = pclose(gradleCommand);
+ if (errorCode != 0) {
+ fprintf(stderr, "Building the android package failed!\n");
+ if (!options.verbose)
+ fprintf(stderr, " -- For more information, run this command with --verbose.\n");
+ return false;
+ }
+
+ if (!QDir::setCurrent(oldPath)) {
+ fprintf(stderr, "Cannot change back to old path: %s\n", qPrintable(oldPath));
+ return false;
+ }
+
+ return true;
+}
+
+bool buildAndroidProject(const Options &options)
+{
+ return options.gradle ? buildGradleProject(options)
+ : buildAntProject(options);
+}
+
bool uninstallApk(const Options &options)
{
if (options.verbose)
@@ -2173,18 +2445,35 @@ bool uninstallApk(const Options &options)
return true;
}
-QString apkName(const Options &options)
+enum PackageType {
+ UnsignedAPK,
+ SignedAPK
+};
+
+QString apkPath(const Options &options, PackageType pt)
{
- if (options.releasePackage && options.keyStore.isEmpty())
- return QLatin1String("QtApp-release-unsigned");
- else if (options.releasePackage)
- return QLatin1String("QtApp-release");
+ QString path(options.outputDirectory);
+ if (options.gradle)
+ path += QLatin1String("/build/outputs/apk/android-build-");
else
- return QLatin1String("QtApp-debug");
+ path += QLatin1String("/bin/QtApp-");
+ if (options.releasePackage) {
+ path += QLatin1String("release-");
+ if (pt == UnsignedAPK)
+ path += QLatin1String("un");
+ path += QLatin1String("signed.apk");
+ } else {
+ path += QLatin1String("debug");
+ if (pt == SignedAPK)
+ path += QLatin1String("-signed");
+ path += QLatin1String(".apk");
+ }
+ return shellQuote(path);
}
bool installApk(const Options &options)
{
+ fflush(stdout);
// Uninstall if necessary
if (options.uninstallApk)
uninstallApk(options);
@@ -2194,10 +2483,8 @@ bool installApk(const Options &options)
FILE *adbCommand = runAdb(options,
QLatin1String(" install -r ")
- + shellQuote(options.outputDirectory)
- + shellQuote(QLatin1String("/bin/")
- + apkName(options)
- + QLatin1String(".apk")));
+ + apkPath(options, options.keyStore.isEmpty() ? UnsignedAPK
+ : SignedAPK));
if (adbCommand == 0)
return false;
@@ -2314,10 +2601,7 @@ bool signPackage(const Options &options)
jarSignerTool += QLatin1String(" -protected");
jarSignerTool += QString::fromLatin1(" %1 %2")
- .arg(shellQuote(options.outputDirectory
- + QLatin1String("/bin/")
- + apkName(options)
- + QLatin1String("-unsigned.apk")))
+ .arg(apkPath(options, UnsignedAPK))
.arg(shellQuote(options.keyStoreAlias));
FILE *jarSignerCommand = openProcess(jarSignerTool);
@@ -2359,14 +2643,8 @@ bool signPackage(const Options &options)
zipAlignTool = QString::fromLatin1("%1%2 -f 4 %3 %4")
.arg(shellQuote(zipAlignTool))
.arg(options.verbose ? QString::fromLatin1(" -v") : QString())
- .arg(shellQuote(options.outputDirectory
- + QLatin1String("/bin/")
- + apkName(options)
- + QLatin1String("-unsigned.apk")))
- .arg(shellQuote(options.outputDirectory
- + QLatin1String("/bin/")
- + apkName(options)
- + QLatin1String(".apk")));
+ .arg(apkPath(options, UnsignedAPK))
+ .arg(apkPath(options, SignedAPK));
FILE *zipAlignCommand = openProcess(zipAlignTool);
if (zipAlignCommand == 0) {
@@ -2386,7 +2664,7 @@ bool signPackage(const Options &options)
return false;
}
- return true;
+ return QFile::remove(apkPath(options, UnsignedAPK));
}
bool copyGdbServer(const Options &options)
@@ -2413,7 +2691,7 @@ bool copyGdbServer(const Options &options)
options.outputDirectory
+ QLatin1String("/libs/")
+ options.architecture
- + QLatin1String("/gdbserver"),
+ + QLatin1String("/gdbserver.so"),
options.verbose)) {
return false;
}
@@ -2531,8 +2809,7 @@ int main(int argc, char *argv[])
return SyntaxErrorOrHelpRequested;
}
- if (Q_UNLIKELY(options.timing))
- options.timer.start();
+ options.timer.start();
if (!readInputFile(&options))
return CannotReadInputFile;
@@ -2558,6 +2835,11 @@ int main(int argc, char *argv[])
);
if (options.build) {
+ if (options.gradle)
+ cleanAndroidFiles(options);
+ if (Q_UNLIKELY(options.timing))
+ fprintf(stdout, "[TIMING] %d ms: Cleaned Android file\n", options.timer.elapsed());
+
if (!copyAndroidTemplate(options))
return CannotCopyAndroidTemplate;
@@ -2629,7 +2911,7 @@ int main(int argc, char *argv[])
if (Q_UNLIKELY(options.timing))
fprintf(stdout, "[TIMING] %d ms: Updated files\n", options.timer.elapsed());
- if (!createAndroidProject(options))
+ if (!options.gradle && !createAndroidProject(options))
return CannotCreateAndroidProject;
if (Q_UNLIKELY(options.timing))
@@ -2654,13 +2936,13 @@ int main(int argc, char *argv[])
if (Q_UNLIKELY(options.timing))
fprintf(stdout, "[TIMING] %d ms: Installed APK\n", options.timer.elapsed());
- fprintf(stdout, "Android package built successfully.\n");
+ fprintf(stdout, "Android package built successfully in %.3f ms.\n", options.timer.elapsed() / 1000.);
if (options.installApk)
fprintf(stdout, " -- It can now be run from the selected device/emulator.\n");
- QString outputFile = options.outputDirectory + QLatin1String("/bin/") + apkName(options);
- fprintf(stdout, " -- File: %s\n", qPrintable(outputFile));
-
+ fprintf(stdout, " -- File: %s\n", qPrintable(apkPath(options, options.keyStore.isEmpty() ? UnsignedAPK
+ : SignedAPK)));
+ fflush(stdout);
return 0;
}