aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaphaël Cotty <raphael.cotty@gmail.com>2020-05-20 11:48:46 +0200
committerRaphaël Cotty <raphael.cotty@gmail.com>2020-06-04 07:55:24 +0000
commit3e2b35f2f3d8c1e9ba3d8248033dcdcc90cf80fe (patch)
treeb881b8339ddc18fba81d37d793fa41810dfdb89a
parent5c0b5b590e83dd1fe0b8b381bb2c4b9e8e16d816 (diff)
Android: Add option to use aapt2 instead of aapt in Android.sdk module
aapt has been deprecated (https://developer.android.com/studio/command-line/aapt2) and replaced by aapt2. PropertyOption aaptFileName allows those value: "aapt" and "aapt2". Default value is set to "aapt" for the moment. Fixes: QBS-1562 Change-Id: I1970cafaa54a0e035c08ffe5f9967b712f5c5253 Reviewed-by: Denis Shienkov <denis.shienkov@gmail.com> Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
-rw-r--r--doc/reference/modules/android-sdk-module.qdoc8
-rw-r--r--share/qbs/modules/Android/sdk/sdk.qbs75
-rw-r--r--share/qbs/modules/Android/sdk/utils.js149
-rw-r--r--tests/auto/blackbox/tst_blackboxandroid.cpp175
4 files changed, 374 insertions, 33 deletions
diff --git a/doc/reference/modules/android-sdk-module.qdoc b/doc/reference/modules/android-sdk-module.qdoc
index 2c2e43eab..74599d0ba 100644
--- a/doc/reference/modules/android-sdk-module.qdoc
+++ b/doc/reference/modules/android-sdk-module.qdoc
@@ -233,3 +233,11 @@
\qmlproperty stringList Android.sdk::aidlSearchPaths
Search paths for import statements to pass to the \c aidl tool via the \c{-I} option.
*/
+
+/*!
+ \qmlproperty string Android.sdk::aaptName
+
+ Name of the aapt binary. Allowed options: "aapt" and "aapt2".
+
+ \defaultvalue \c "aapt"
+*/
diff --git a/share/qbs/modules/Android/sdk/sdk.qbs b/share/qbs/modules/Android/sdk/sdk.qbs
index 84492a869..681b3da94 100644
--- a/share/qbs/modules/Android/sdk/sdk.qbs
+++ b/share/qbs/modules/Android/sdk/sdk.qbs
@@ -139,7 +139,14 @@ Module {
}
property path buildToolsDir: FileInfo.joinPaths(sdkDir, "build-tools", buildToolsVersion)
- property path aaptFilePath: FileInfo.joinPaths(buildToolsDir, "aapt")
+ property string aaptName: "aapt"
+ PropertyOptions {
+ name: "aaptName"
+ allowedValues: ["aapt", "aapt2"]
+ }
+ property path aaptFilePath: FileInfo.joinPaths(buildToolsDir, aaptName)
+ readonly property bool _enableAapt2: aaptName === "aapt2"
+
property path apksignerFilePath: FileInfo.joinPaths(buildToolsDir, "apksigner")
property path aidlFilePath: FileInfo.joinPaths(buildToolsDir, "aidl")
property path dxFilePath: FileInfo.joinPaths(buildToolsDir, "dx")
@@ -151,6 +158,8 @@ Module {
property path generatedJavaFilesBaseDir: FileInfo.joinPaths(product.buildDirectory, "gen")
property path generatedJavaFilesDir: FileInfo.joinPaths(generatedJavaFilesBaseDir,
(packageName || "").split('.').join('/'))
+ property path compiledResourcesDir: FileInfo.joinPaths(product.buildDirectory,
+ "compiled_resources")
property string apkContentsDir: FileInfo.joinPaths(product.buildDirectory, "bin")
property string debugKeyStorePath: FileInfo.joinPaths(
Environment.getEnv(qbs.hostOS.contains("windows")
@@ -311,7 +320,7 @@ Module {
}
Rule {
- condition: _enableRules
+ condition: _enableRules && !_enableAapt2
multiplex: true
inputs: ["android.resources", "android.assets", "android.manifest_final"]
@@ -334,6 +343,51 @@ Module {
}
Rule {
+ condition: _enableRules && _enableAapt2
+ inputs: ["android.resources"]
+ outputArtifacts: {
+ var outputs = [];
+ var resources = inputs["android.resources"];
+ for (var i = 0; i < resources.length; ++i) {
+ var filePath = resources[i].filePath;
+ var resourceFileName = SdkUtils.generateAapt2ResourceFileName(filePath);
+ var compiledName = FileInfo.joinPaths(product.Android.sdk.compiledResourcesDir,
+ resourceFileName);
+ outputs.push({filePath: compiledName, fileTags: "android.resources_compiled"});
+ }
+ return outputs;
+ }
+ outputFileTags: ["android.resources_compiled"]
+
+ prepare: SdkUtils.prepareAapt2CompileResource.apply(SdkUtils, arguments)
+ }
+
+ Rule {
+ condition: _enableRules && _enableAapt2
+ multiplex: true
+ inputs: ["android.resources_compiled", "android.assets", "android.manifest_final"]
+ outputFileTags: ["java.java", "android.apk_base"]
+ outputArtifacts: {
+ var artifacts = [];
+ artifacts.push({
+ filePath: product.Android.sdk.apkBaseName + ".apk_base",
+ fileTags: ["android.apk_base"]
+ });
+ var resources = inputs["android.resources_compiled"];
+ if (resources && resources.length) {
+ artifacts.push({
+ filePath: FileInfo.joinPaths(product.Android.sdk.generatedJavaFilesDir,
+ "R.java"),
+ fileTags: ["java.java"]
+ });
+ }
+
+ return artifacts;
+ }
+ prepare: SdkUtils.prepareAapt2Link.apply(SdkUtils, arguments)
+ }
+
+ Rule {
condition: _enableRules
multiplex: true
@@ -421,7 +475,7 @@ Module {
}
Rule {
- condition: _enableRules
+ condition: _enableRules && !_enableAapt2
multiplex: true
inputs: [
"android.resources", "android.assets", "android.manifest_final",
@@ -434,4 +488,19 @@ Module {
}
prepare: SdkUtils.prepareAaptPackage.apply(SdkUtils, arguments)
}
+
+ Rule {
+ condition: _enableRules && _enableAapt2
+ multiplex: true
+ inputs: [
+ "android.apk_base", "android.manifest_final",
+ "android.dex", "android.stl_deployed",
+ "android.nativelibrary_deployed", "android.keystore"
+ ]
+ Artifact {
+ filePath: product.Android.sdk.apkBaseName + ".apk"
+ fileTags: "android.apk"
+ }
+ prepare: SdkUtils.prepareApkPackage.apply(SdkUtils, arguments)
+ }
}
diff --git a/share/qbs/modules/Android/sdk/utils.js b/share/qbs/modules/Android/sdk/utils.js
index 4ee9bd3b5..b1c929e68 100644
--- a/share/qbs/modules/Android/sdk/utils.js
+++ b/share/qbs/modules/Android/sdk/utils.js
@@ -136,6 +136,96 @@ function commonAaptPackageArgs(project, product, inputs, outputs, input, output,
return args;
}
+// Rules: from https://developer.android.com/studio/command-line/aapt2
+// Input Output
+// XML resource files, such as Resource table with *.arsc.flat as its extension.
+// String and Style, which are
+// located in the res/values/
+// directory.
+
+// All other resource files. All files other than the files under res/values/ directory are
+// converted to binary XML files with *.flat extensions.
+// Additionally all PNG files are crunched by default and adopt
+// *.png.flat extensions.
+function generateAapt2ResourceFileName(filePath) {
+ var suffix = FileInfo.suffix(filePath);
+ if (suffix === "xml") {
+ var data = new Xml.DomDocument();
+ data.load(filePath);
+ var rootElem = data.documentElement();
+ if (rootElem && rootElem.isElement() && rootElem.tagName() === "resources")
+ // This is a valid XML resource file
+ suffix = "arsc";
+ // If the xml file is not a "resources" one then it's treated like any other resource file.
+ }
+ var dir = FileInfo.path(filePath);
+ var baseName = FileInfo.completeBaseName(filePath)
+ return FileInfo.fileName(dir) + "_" + baseName + "." + suffix + ".flat";
+}
+
+function prepareAapt2CompileResource(project, product, inputs, outputs, input, output,
+ explicitlyDependsOn) {
+ var cmds = [];
+ var resources = inputs["android.resources"];
+ var compilesResourcesDir = product.Android.sdk.compiledResourcesDir;
+ if (!File.makePath(compilesResourcesDir)) {
+ throw "Cannot create directory '" + FileInfo.toNativeSeparators(compilesResourcesDir) +
+ "'.";
+ }
+ var args = ["compile", input.filePath, "-o", compilesResourcesDir];
+ var cmd = new Command(product.Android.sdk.aaptFilePath, args);
+ var outputFileName = generateAapt2ResourceFileName(input.filePath);
+ cmd.description = "compiling resource " + input.fileName + " into " + outputFileName;
+ cmds.push(cmd);
+
+ return cmds;
+}
+
+function prepareAapt2Link(project, product, inputs, outputs, input, output, explicitlyDependsOn) {
+ var cmds = [];
+ var manifestFilePath = inputs["android.manifest_final"][0].filePath;
+ var compilesResourcesDir = product.Android.sdk.compiledResourcesDir;
+ var apkOutputFilePath = outputs["android.apk_base"][0].filePath;
+ var compiledResources = inputs["android.resources_compiled"];
+
+ var args = ["link", "-o", apkOutputFilePath, "-I", product.Android.sdk.androidJarFilePath];
+ //For aab: args.push("link", "--proto-format");
+ var i = 0;
+ if (compiledResources) {
+ for (i = 0; i < compiledResources.length; ++i)
+ args.push(compiledResources[i].filePath);
+ }
+ args.push("--no-auto-version");
+ args.push("--auto-add-overlay");
+ args.push("--manifest", manifestFilePath);
+ args.push("--java", product.Android.sdk.generatedJavaFilesBaseDir);
+
+ var assets = inputs["android.assets"];
+ var assetDirs = [];
+ if (assets) {
+ for (i = 0; i < assets.length; ++i) {
+ var assetDir = findParentDir(assets[i].filePath, "assets");
+ if (!assetDir) {
+ throw "File '" + assets[i].filePath + "' is tagged as an Android asset, "
+ + "but is not located under a directory called 'assets'.";
+ }
+ if (!assetDirs.contains(assetDir))
+ assetDirs.push(assetDir);
+ }
+ }
+ for (i = 0; i < assetDirs.length; ++i)
+ args.push("-A", assetDirs[i]);
+ if (product.qbs.buildVariant === "debug")
+ args.push("-v");
+
+ var cmd = new Command(product.Android.sdk.aaptFilePath, args);
+ cmd.description = "Linking resources";
+ cmd.workingDirectory = product.buildDirectory;
+ cmds.push(cmd);
+
+ return cmds;
+}
+
function prepareAaptGenerate(project, product, inputs, outputs, input, output,
explicitlyDependsOn) {
var args = commonAaptPackageArgs.apply(this, arguments);
@@ -194,6 +284,65 @@ function prepareAaptPackage(project, product, inputs, outputs, input, output, ex
return cmds;
}
+function prepareApkPackage(project, product, inputs, outputs, input, output, explicitlyDependsOn) {
+ var cmds = [];
+ var apkInputFilePath = inputs["android.apk_base"][0].filePath;
+ var apkOutput = outputs["android.apk"][0];
+ var apkOutputFilePathUnaligned = outputs["android.apk"][0].filePath + ".unaligned";
+ var dexFilePath = inputs["android.dex"][0].filePath;
+
+ var copyCmd = new JavaScriptCommand();
+ copyCmd.description = "copying apk";
+ copyCmd.source = apkInputFilePath;
+ copyCmd.target = apkOutputFilePathUnaligned;
+ copyCmd.sourceCode = function() {
+ File.copy(source, target);
+ }
+ cmds.push(copyCmd);
+
+ var jarArgs = ["-uvf", apkOutputFilePathUnaligned, "."];
+ var libPath = FileInfo.joinPaths(product.Android.sdk.apkContentsDir);
+ var jarCmd = new Command(product.java.jarFilePath, jarArgs);
+ jarCmd.description = "packaging files";
+ jarCmd.workingDirectory = libPath;
+ cmds.push(jarCmd);
+
+ if (!product.Android.sdk.useApksigner) {
+ args = ["-sigalg", "SHA1withRSA", "-digestalg", "SHA1",
+ "-keystore", inputs["android.keystore"][0].filePath,
+ "-storepass", "android",
+ apkOutputFilePathUnaligned,
+ "androiddebugkey"];
+ cmd = new Command(product.java.jarsignerFilePath, args);
+ cmd.description = "Signing " + apkOutput.fileName;
+ cmds.push(cmd);
+ }
+
+ cmd = new Command(product.Android.sdk.zipalignFilePath,
+ ["-f", "4", apkOutputFilePathUnaligned, apkOutput.filePath]);
+ cmd.silent = true;
+ cmds.push(cmd);
+
+ cmd = new JavaScriptCommand();
+ cmd.silent = true;
+ cmd.unalignedApk = apkOutputFilePathUnaligned;
+ cmd.sourceCode = function() { File.remove(unalignedApk); };
+ cmds.push(cmd);
+
+ if (product.Android.sdk.useApksigner) {
+ // TODO: Implement full signing support, not just using the debug keystore
+ args = ["sign",
+ "--ks", inputs["android.keystore"][0].filePath,
+ "--ks-pass", "pass:android",
+ apkOutput.filePath];
+ cmd = new Command(product.Android.sdk.apksignerFilePath, args);
+ cmd.description = "Signing " + apkOutput.fileName;
+ cmds.push(cmd);
+ }
+
+ return cmds;
+}
+
function createDebugKeyStoreCommandString(keytoolFilePath, keystoreFilePath) {
var args = ["-genkey", "-keystore", keystoreFilePath, "-alias", "androiddebugkey",
"-storepass", "android", "-keypass", "android", "-keyalg", "RSA",
diff --git a/tests/auto/blackbox/tst_blackboxandroid.cpp b/tests/auto/blackbox/tst_blackboxandroid.cpp
index 040a1a6e2..e8d44188c 100644
--- a/tests/auto/blackbox/tst_blackboxandroid.cpp
+++ b/tests/auto/blackbox/tst_blackboxandroid.cpp
@@ -80,6 +80,7 @@ void TestBlackboxAndroid::android()
QFETCH(QStringList, productNames);
QFETCH(QList<QByteArrayList>, expectedFilesLists);
QFETCH(QStringList, qmlAppCustomProperties);
+ QFETCH(bool, enableAapt2);
const SettingsPtr s = settings();
Profile p(theProfileName(projectDir == "qml-app"), s.get());
@@ -103,6 +104,7 @@ void TestBlackboxAndroid::android()
&& ndkSamplesDirs.contains(projectDir))
QSKIP("NDK samples directory not present");
+ const QString aaptVersion = enableAapt2 ? "aapt2" : "aapt";
QDir::setCurrent(testDataDir + "/" + projectDir);
static const QStringList configNames { "debug", "release" };
@@ -110,11 +112,13 @@ void TestBlackboxAndroid::android()
auto currentExpectedFilesLists = expectedFilesLists;
const QString configArgument = "config:" + configName;
QbsRunParameters resolveParams("resolve");
+ resolveParams.buildDirectory = aaptVersion;
resolveParams.arguments << configArgument << qmlAppCustomProperties;
resolveParams.profile = p.name();
QCOMPARE(runQbs(resolveParams), 0);
QbsRunParameters buildParams(QStringList{"--command-echo-mode", "command-line",
configArgument});
+ buildParams.buildDirectory = aaptVersion;
buildParams.profile = p.name();
QCOMPARE(runQbs(buildParams), 0);
for (const QString &productName : qAsConst(productNames)) {
@@ -123,7 +127,8 @@ void TestBlackboxAndroid::android()
QCOMPARE(m_qbsStdout.count("Generating BuildConfig.java"),
isIncrementalBuild ? 0 : productNames.size());
QVERIFY(m_qbsStdout.contains(productName.toLocal8Bit() + ".apk"));
- const QString apkFilePath = relativeProductBuildDir(productName, configName)
+ const QString apkFilePath = aaptVersion + "/" + relativeProductBuildDir(productName,
+ configName)
+ '/' + productName + ".apk";
QVERIFY2(regularFileExists(apkFilePath), qPrintable(apkFilePath));
const QString jarFilePath = androidPaths["jar"];
@@ -206,7 +211,6 @@ void TestBlackboxAndroid::android_data()
.toString() == "clang";
return QByteArray("lib/${ARCH}/") + (usesClang ? "libc++_shared.so" : oldcxxLib);
};
-
bool usingOldQt = true;
QStringList qmakeFilePaths = pQt.value(QStringLiteral("moduleProviders.Qt.qmakeFilePaths")).
toStringList();
@@ -265,24 +269,56 @@ void TestBlackboxAndroid::android_data()
QTest::addColumn<QStringList>("productNames");
QTest::addColumn<QList<QByteArrayList>>("expectedFilesLists");
QTest::addColumn<QStringList>("qmlAppCustomProperties");
+ QTest::addColumn<bool>("enableAapt2");
+
+ const auto aaptVersion = [](bool enableAapt2) {
+ return QString("modules.Android.sdk.aaptName:") + (enableAapt2 ? "aapt2" : "aapt");
+ };
+ bool enableAapt2 = false;
+ QByteArrayList teaPotAppExpectedFiles;
+ teaPotAppExpectedFiles << commonFiles + expandArchs(archs, {
+ "resources.arsc",
+ "assets/Shaders/ShaderPlain.fsh",
+ "assets/Shaders/VS_ShaderPlain.vsh",
+ cxxLibPath("libgnustl_shared.so", false),
+ "lib/${ARCH}/libTeapotNativeActivity.so",
+ "res/layout/widgets.xml",
+ "res/mipmap-hdpi-v4/ic_launcher.png",
+ "res/mipmap-mdpi-v4/ic_launcher.png",
+ "res/mipmap-xhdpi-v4/ic_launcher.png",
+ "res/mipmap-xxhdpi-v4/ic_launcher.png"});
QTest::newRow("teapot")
<< "teapot" << QStringList("TeapotNativeActivity")
- << (QList<QByteArrayList>() << commonFiles + expandArchs(archs, {
- "resources.arsc",
- "assets/Shaders/ShaderPlain.fsh",
- "assets/Shaders/VS_ShaderPlain.vsh",
- cxxLibPath("libgnustl_shared.so", false),
- "lib/${ARCH}/libTeapotNativeActivity.so",
- "res/layout/widgets.xml"}))
- << QStringList();
+ << (QList<QByteArrayList>() << teaPotAppExpectedFiles)
+ << QStringList{aaptVersion(enableAapt2)} << enableAapt2;
+ enableAapt2 = true;
+ QTest::newRow("teapot")
+ << "teapot" << QStringList("TeapotNativeActivity")
+ << (QList<QByteArrayList>() << teaPotAppExpectedFiles)
+ << QStringList{aaptVersion(enableAapt2)} << enableAapt2;
+ enableAapt2 = false;
+ QTest::newRow("minimal-native")
+ << "minimal-native" << QStringList("minimalnative")
+ << (QList<QByteArrayList>() << commonFiles + expandArchs({archs.first()}, {
+ "lib/${ARCH}/libminimalnative.so",
+ cxxLibPath("libstlport_shared.so", false),
+ "lib/${ARCH}/libdependency.so"}))
+ << QStringList{"products.minimalnative.multiplexByQbsProperties:[]",
+ "modules.qbs.architecture:" + archsStringList.first(),
+ aaptVersion(enableAapt2)}
+ << enableAapt2;
+ enableAapt2 = true;
QTest::newRow("minimal-native")
<< "minimal-native" << QStringList("minimalnative")
<< (QList<QByteArrayList>() << commonFiles + expandArchs({archs.first()}, {
+ "resources.arsc",
"lib/${ARCH}/libminimalnative.so",
cxxLibPath("libstlport_shared.so", false),
"lib/${ARCH}/libdependency.so"}))
<< QStringList{"products.minimalnative.multiplexByQbsProperties:[]",
- "modules.qbs.architecture:" + archsStringList.first()};
+ "modules.qbs.architecture:" + archsStringList.first(),
+ aaptVersion(enableAapt2)}
+ << enableAapt2;
QByteArrayList qmlAppExpectedFiles;
QByteArrayList qmlAppMinistroExpectedFiles;
QByteArrayList qmlAppCustomMetaDataExpectedFiles;
@@ -325,14 +361,12 @@ void TestBlackboxAndroid::android_data()
"lib/${ARCH}/libQt5Qml.so",
"lib/${ARCH}/libQt5QuickParticles.so",
"lib/${ARCH}/libQt5Quick.so",
- "lib/${ARCH}/libqmlapp.so",
- "res/layout/splash.xml"});
+ "lib/${ARCH}/libqmlapp.so"});
qmlAppMinistroExpectedFiles << commonFiles + expandArchs(ndkArchsForQt, {
"resources.arsc",
"assets/--Added-by-androiddeployqt--/qt_cache_pregenerated_file_list",
cxxLibPath("libgnustl_shared.so", true),
- "lib/${ARCH}/libqmlapp.so",
- "res/layout/splash.xml"});
+ "lib/${ARCH}/libqmlapp.so"});
qmlAppCustomMetaDataExpectedFiles << commonFiles + expandArchs(ndkArchsForQt, {
"resources.arsc",
"assets/--Added-by-androiddeployqt--/qml/QtQuick.2/plugins.qmltypes",
@@ -371,8 +405,7 @@ void TestBlackboxAndroid::android_data()
"lib/${ARCH}/libQt5Qml.so",
"lib/${ARCH}/libQt5QuickParticles.so",
"lib/${ARCH}/libQt5Quick.so",
- "lib/${ARCH}/libqmlapp.so",
- "res/layout/splash.xml"});
+ "lib/${ARCH}/libqmlapp.so"});
qmlAppCustomProperties = QStringList{"modules.Android.sdk.automaticSources:false",
"modules.qbs.architecture:" + archsForQt.first()};
} else {
@@ -411,14 +444,12 @@ void TestBlackboxAndroid::android_data()
"lib/${ARCH}/libQt5Quick_${ARCH}.so",
"lib/${ARCH}/libQt5QmlModels_${ARCH}.so",
"lib/${ARCH}/libQt5QmlWorkerScript_${ARCH}.so",
- "lib/${ARCH}/libqmlapp_${ARCH}.so",
- "res/layout/splash.xml"});
+ "lib/${ARCH}/libqmlapp_${ARCH}.so"});
qmlAppMinistroExpectedFiles << commonFiles + expandArchs(ndkArchsForQt, {
"resources.arsc",
"assets/android_rcc_bundle.rcc",
cxxLibPath("libgnustl_shared.so", true),
- "lib/${ARCH}/libqmlapp_${ARCH}.so",
- "res/layout/splash.xml"});
+ "lib/${ARCH}/libqmlapp_${ARCH}.so"});
qmlAppCustomMetaDataExpectedFiles << commonFiles + expandArchs(ndkArchsForQt, {
"resources.arsc",
"assets/android_rcc_bundle.rcc",
@@ -455,23 +486,57 @@ void TestBlackboxAndroid::android_data()
"lib/${ARCH}/libQt5Quick_${ARCH}.so",
"lib/${ARCH}/libQt5QmlModels_${ARCH}.so",
"lib/${ARCH}/libQt5QmlWorkerScript_${ARCH}.so",
- "lib/${ARCH}/libqmlapp_${ARCH}.so",
- "res/layout/splash.xml"});
+ "lib/${ARCH}/libqmlapp_${ARCH}.so"});
qmlAppCustomProperties = QStringList{"modules.Android.sdk.automaticSources:false"};
}
+ // aapt tool for the resources works with a directory option pointing to the parent directory
+ // of the resources (res).
+ // The Qt.android_support module adds res/values/libs.xml (from Qt install dir). So the res from
+ // Qt install res directory is added to aapt. This results in adding res/layout/splash.xml to
+ // the package eventhough the file is not needed.
+ // On the other hand aapt2 requires giving all the resources files.
+ // Also when enabling aapt2 the resources.arsc is always created, eventhough no resources is
+ // declared.
+ enableAapt2 = false;
+ QTest::newRow("qml app")
+ << "qml-app" << QStringList("qmlapp")
+ << (QList<QByteArrayList>() << (QByteArrayList() << qmlAppExpectedFiles
+ << "res/layout/splash.xml"))
+ << (QStringList() << qmlAppCustomProperties << aaptVersion(enableAapt2)) << enableAapt2;
+ enableAapt2 = true;
QTest::newRow("qml app")
<< "qml-app" << QStringList("qmlapp")
<< (QList<QByteArrayList>() << qmlAppExpectedFiles)
- << qmlAppCustomProperties;
+ << (QStringList() << qmlAppCustomProperties << aaptVersion(enableAapt2)) << enableAapt2;
+ enableAapt2 = false;
+ QTest::newRow("qml app using Ministro")
+ << "qml-app" << QStringList("qmlapp")
+ << (QList<QByteArrayList>() << (QByteArrayList() << qmlAppMinistroExpectedFiles
+ << "res/layout/splash.xml"))
+ << QStringList{"modules.Qt.android_support.useMinistro:true",
+ "modules.Android.sdk.automaticSources:false",
+ aaptVersion(enableAapt2)} << enableAapt2;
+ enableAapt2 = true;
QTest::newRow("qml app using Ministro")
<< "qml-app" << QStringList("qmlapp")
<< (QList<QByteArrayList>() << qmlAppMinistroExpectedFiles)
<< QStringList{"modules.Qt.android_support.useMinistro:true",
- "modules.Android.sdk.automaticSources:false"};
+ "modules.Android.sdk.automaticSources:false",
+ aaptVersion(enableAapt2)} << enableAapt2;
+ enableAapt2 = false;
+ QTest::newRow("qml app with custom metadata")
+ << "qml-app" << QStringList("qmlapp")
+ << (QList<QByteArrayList>() << (QByteArrayList() << qmlAppCustomMetaDataExpectedFiles
+ << "res/layout/splash.xml"))
+ << QStringList{"modules.Android.sdk.automaticSources:true",
+ aaptVersion(enableAapt2)} << enableAapt2;
+ enableAapt2 = true;
QTest::newRow("qml app with custom metadata")
<< "qml-app" << QStringList("qmlapp")
<< (QList<QByteArrayList>() << qmlAppCustomMetaDataExpectedFiles)
- << QStringList("modules.Android.sdk.automaticSources:true");
+ << QStringList{"modules.Android.sdk.automaticSources:true",
+ aaptVersion(enableAapt2)} << enableAapt2;
+ enableAapt2 = false;
QTest::newRow("no native")
<< "no-native"
<< QStringList("com.example.android.basicmediadecoder")
@@ -493,9 +558,41 @@ void TestBlackboxAndroid::android_data()
"res/menu/action_menu.xml",
"res/menu-v11/action_menu.xml",
"res/raw/vid_bigbuckbunny.mp4"}))
- << QStringList();
+ << QStringList(aaptVersion(enableAapt2)) << enableAapt2;
+ enableAapt2 = true;
+ QTest::newRow("no native")
+ << "no-native"
+ << QStringList("com.example.android.basicmediadecoder")
+ << (QList<QByteArrayList>() << commonFiles + expandArchs(archs, {
+ "resources.arsc",
+ "res/drawable-hdpi-v4/ic_action_play_disabled.png",
+ "res/drawable-hdpi-v4/ic_action_play.png",
+ "res/drawable-hdpi-v4/ic_launcher.png",
+ "res/drawable-hdpi-v4/tile.9.png",
+ "res/drawable-mdpi-v4/ic_action_play_disabled.png",
+ "res/drawable-mdpi-v4/ic_action_play.png",
+ "res/drawable-mdpi-v4/ic_launcher.png",
+ "res/drawable/selector_play.xml",
+ "res/drawable-xhdpi-v4/ic_action_play_disabled.png",
+ "res/drawable-xhdpi-v4/ic_action_play.png",
+ "res/drawable-xhdpi-v4/ic_launcher.png",
+ "res/drawable-xxhdpi-v4/ic_launcher.png",
+ "res/layout/sample_main.xml",
+ "res/menu/action_menu.xml",
+ // I have no idea why this file is generated with aapt and not with aapt2
+ //"res/menu-v11/action_menu.xml",
+ "res/raw/vid_bigbuckbunny.mp4"}))
+ << QStringList(aaptVersion(enableAapt2)) << enableAapt2;
+ enableAapt2 = false;
QTest::newRow("aidl") << "aidl" << QStringList("io.qbs.aidltest")
- << QList<QByteArrayList>{commonFiles} << QStringList();
+ << (QList<QByteArrayList>() << (QByteArrayList() << commonFiles))
+ << QStringList(aaptVersion(enableAapt2)) << enableAapt2;
+ enableAapt2 = true;
+ QTest::newRow("aidl") << "aidl" << QStringList("io.qbs.aidltest")
+ << (QList<QByteArrayList>() << (QByteArrayList() << commonFiles
+ << "resources.arsc"))
+ << QStringList(aaptVersion(enableAapt2)) << enableAapt2;
+ enableAapt2 = false;
QTest::newRow("multiple libs")
<< "multiple-libs-per-apk"
<< QStringList("twolibs")
@@ -504,7 +601,17 @@ void TestBlackboxAndroid::android_data()
"lib/${ARCH}/liblib1.so",
"lib/${ARCH}/liblib2.so",
cxxLibPath("libstlport_shared.so", false)}))
- << QStringList();
+ << QStringList(aaptVersion(enableAapt2)) << enableAapt2;
+ enableAapt2 = true;
+ QTest::newRow("multiple libs")
+ << "multiple-libs-per-apk"
+ << QStringList("twolibs")
+ << (QList<QByteArrayList>() << commonFiles + expandArchs(archs, {
+ "resources.arsc",
+ "lib/${ARCH}/liblib1.so",
+ "lib/${ARCH}/liblib2.so",
+ cxxLibPath("libstlport_shared.so", false)}))
+ << QStringList(aaptVersion(enableAapt2)) << enableAapt2;
QByteArrayList expectedFiles1 = qbs::toList(qbs::toSet(commonFiles
+ expandArchs(QByteArrayList{"armeabi-v7a", "x86"}, {
"resources.arsc",
@@ -518,11 +625,19 @@ void TestBlackboxAndroid::android_data()
"lib/${ARCH}/libp2lib1.so",
"lib/${ARCH}/libp2lib2.so",
cxxLibPath("libstlport_shared.so", false)});
+ enableAapt2 = false;
+ QTest::newRow("multiple apks")
+ << "multiple-apks-per-project"
+ << (QStringList() << "twolibs1" << "twolibs2")
+ << QList<QByteArrayList>{expectedFiles1, expectedFiles2}
+ << QStringList(aaptVersion(enableAapt2)) << enableAapt2;
+ enableAapt2 = true;
+ expectedFiles2 << "resources.arsc";
QTest::newRow("multiple apks")
<< "multiple-apks-per-project"
<< (QStringList() << "twolibs1" << "twolibs2")
<< QList<QByteArrayList>{expectedFiles1, expectedFiles2}
- << QStringList();
+ << QStringList(aaptVersion(enableAapt2)) << enableAapt2;
}
QTEST_MAIN(TestBlackboxAndroid)