[Qbs] building android aab package help

Raphael Cotty raphael.cotty at gmail.com
Tue Apr 14 21:27:18 CEST 2020


Hi all,
I am struggling to find a way to build the aab package (non runnable
package required by google store) on the android platform.
For this platform the default qbs product type is changed from application
to android.apk (runnable package).
What I am trying to achieve is allowing the user to just set a property in
his project to enable the build of the aab package:
QtQuiApplication {
    name: "myApp"
    buildAab: true
    ...
}

Building an aab is similar to building apk. They both take the same inputs
(including java files) and generate a java file (R.java) but in a different
way.

I first tried to add the android.aab type to the product type property in
order to build both types.
But I can't find a way to redirect all java files + the R.java apk to the
next apk rule and all the java files + R.java aab to the next aab rule
(without changing the java module).

It looks like I need to multiplex over the product type...
This simple project summaries the issue (assuming product type multiplexing
exists):
Project {
    Product {
        multiplexByType: ["android.apk", "android.aab"]
        name: "android"

        files: [
            "a.java",
            "b.java"
        ]

        Group {
            files: "AndroidManifest.xml"
            fileTags: "android.manifest_final"
        }

        FileTagger {
            patterns: "*.java"
            fileTags: ["java.java"]
        }

        // Generate the R.java in a different way according to the product
type
        Rule {
            inputs: "android.manifest_final"
            Artifact {
                filePath: FileInfo.joinPaths(product.buildDirectory,
"R.java")
                fileTags: ["java.java"]
            }
            prepare: {
                var cmd = new JavaScriptCommand();
                cmd.description = "generating R.java";
                cmd.sourceCode = function() {
                    var readFile = TextFile(input.filePath,
TextFile.ReadOnly);
                    var writeFile = TextFile(output.filePath,
TextFile.WriteOnly)
                    writeFile.write(readFile.readAll());
                    if (product.type === "android.apk")
                        writeFile.write("This is the R.java for apk");
                    else
                        writeFile.write("This is the R.java for aab");
                    writeFile.close();
                };
                return [cmd];
            }
        }

        // This rule can't be changed as it comes from the java module
        Rule {
            multiplex: true
            inputs: ["java.java"]
            outputFileTags: ["java.class"]
            outputArtifacts: {
                var artifacts = [];
                for (var i = 0; i < inputs["java.java"].length; ++i) {
                    artifacts.push({
                                       fileTags: "java.class",
                                       filePath:
FileInfo.joinPaths(product.buildDirectory,

inputs["java.java"][i].baseName + ".class")});
                }
                return artifacts;
            }
            prepare: {
                var cmd = new JavaScriptCommand();
                cmd.description = "compiling java files";
                cmd.sourceCode = function() {
                    for (var i = 0; i < inputs["java.java"].length; ++i) {
                        File.copy(inputs["java.java"][i].filePath,
                                  outputs["java.class"][i].filePath);
                    }
                };
                return [cmd];
            }
        }

        // Let's gather all compiled java classes and generate the
classes.dex
        // If running in the apk context then we have all project java
classes and the
        // R.java generated in the apk context
        // If running in the aab context then we have all project java
classes and the
        // R.java generated in the aab context
        Rule {
            multiplex: true
            inputs: ["java.class"]
            Artifact {
                filePath: "classes.dex"
                fileTags: ["android.dex"]
            }
            prepare: {
                var cmd = new JavaScriptCommand();
                cmd.description = "generating classes.dex";
                cmd.sourceCode = function() {
                    var writeFile = TextFile(output.filePath,
TextFile.WriteOnly)
                    for (var i = 0; i < inputs["java.class"].length; ++i) {
                        var readFile =
TextFile(inputs["java.class"][i].filePath, TextFile.ReadOnly);
                        writeFile.write(readFile.readAll());
                    }
                    writeFile.close();
                };
                return [cmd];
            }
        }

        // Generate the apk package
        Rule {
            multiplex: true
            inputs: ["android.dex"]
            Artifact {
                filePath: product.name + ".apk"
                fileTags: "android.apk"
            }
            prepare: {
                var cmd = new JavaScriptCommand();
                cmd.description = "generating apk";
                cmd.sourceCode = function() {
                    File.copy(inputs["android.dex"][0].filePath,
output.filePath);
                };
                return [cmd];
            }
        }

        // Generate the aab package
        Rule {
            multiplex: true
            inputs: ["android.dex"]
            Artifact {
                filePath: product.name + ".aab"
                fileTags: "android.aab"
            }
            prepare: {
                var cmd = new JavaScriptCommand();
                cmd.description = "generating aab";
                cmd.sourceCode = function() {
                    File.copy(inputs["android.dex"][0].filePath,
output.filePath);
                };
                return [cmd];
            }
        }
    }
}

As a fall back solution I can create a new AndroidAab Product that will
depend on the android application and implement all rules using
inputsFromDependencies property
*.*

So let me know if you have any idea.
Thanks
Raph
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/qbs/attachments/20200414/47e0ed36/attachment.html>


More information about the Qbs mailing list