[SOLVED] I'm trying to use the `Variant API`, e.g....
# android
l
[SOLVED] I'm trying to use the
Variant API
, e.g. iterating over build variants but it does not call the proper all function:
Copy code
applicationVariants.all { variant ->
        println(variant.name)
    }
It uses the all function from
Iterable
which expects a boolean return type. I would like to change the
outputFileName
of all variants. Any ideas how to specify the correct function in this case? EDIT: upsi, I have to remove the
variant ->
d
In your
android
block:
Copy code
androidComponents {
  onVariants(selector().all(), { variant ->
    def targetDirectory = "outputs/apk/"
    def copy = tasks.register("copy${variant.getName().capitalize()}Apks", Copy) {
      from { variant.artifacts.get(SingleArtifact.APK.INSTANCE) }
      include "*.apk"
      into project.layout.buildDirectory.dir(targetDirectory)
    }

    afterEvaluate {
      tasks.named("create${variant.getName().capitalize()}ApkListingFileRedirect").configure( {
        it.dependsOn(copy)
      })
      tasks.withType(PackageApplication.class).named("package${variant.getName().capitalize()}").configure {
        finalizedBy(copy)
        copy.get().dependsOn(it)
      }
    }
  })
}
l
Thanks @Daniel B Duval Unfortunately it does not generate the apk file. Am I missing something? Kotlin DSL:
Copy code
androidComponents {
        onVariants { variant ->
            val targetDirectory = "outputs2/apk/"
            val copyTask = tasks.register<Copy>("copy${variant.name.capitalize()}Apks") {
                // Get apk folder
                println("apkArtifact: ${variant.artifacts.get(SingleArtifact.APK)}.")
                from(variant.artifacts.get(SingleArtifact.APK))
                include("lachen.apk")
                into(project.layout.buildDirectory.dir(targetDirectory))
            }


            afterEvaluate {
                tasks.named("create${variant.name.capitalize()}ApkListingFileRedirect").configure {
                    dependsOn(copyTask)
                }

                tasks.named("package${variant.name.capitalize()}").configure {
                    finalizedBy(copyTask)
                    copyTask.get().dependsOn(this)
                }
            }

        }
d
2 questions: • is
build/outputs2/apk/
there? In my example, I was putting into the normal
build/outtputs/apk
folder, so I’m not sure if the folder will be created • Under
/build/apk/${valriant}/${buildType}
what are the APK names. We have multiple flavors and build types, but only build one at a time, thus we use
include  "*.apk"
as we just copy the apk that is there up to outputs/apk
l
I tried both but "lachen.apk" wasn't there
d
the include is only going to look into the apk output folder and include only what is specified. normally you’d have something like
${App}-${variant}-${buildType}.apk
l
When running build task, the last tasks are:
Copy code
> Task :dcintern:packageDebug
> Task :dcintern:copyDebugApks NO-SOURCE
> Task :dcintern:createDebugApkListingFileRedirect
> Task :dcintern:assembleDebug
Maybe NO-SOURCE is here a problem.
We have multiple flavors and build types
I have only debug and release.
• Under
/build/apk/${valriant}/${buildType}
what are the APK names.
after running build task I have the following files there: outputs/apk/debug/dcintern-debug.apk
Copy code
targetDirectory = "outputs/apk/"
d
the include is the format of what you are looking for. You’re specifying
lachen.apk
as the file pattern to match to copy.
*.apk
should take any file in the format of
*apk
and move it to
outputs/apk
l
ahh ok and where do I rename the apk file to match pattern
${App}-${variant}-${buildType}.apk
d
AGP puts it in the output directory already. if you do not have multiple variants, it’s just.
{app}-{buildtype}.apk
l
Ah sorry, I would like to append the versionCode, like
${App}-${variant}-${buildType}-v${versionCode}.apk
Tbh I don't see the purpose of the code snippet. Why do I even copy anything when it currently matches the default behavior.
d
aye, I follow now. Sorry. In our case, build number is never anything known to our build but is really an artifact of the CI’s environment variables. In. that case, I’d just add a task after the build completes to rename the file as desired on the CI. The reason being is that you’d also start doing this with local and Android Studio builds and may find yourself having to deal with side effects of renaming a file by a task added to the graph that may not be accounted for. For example, AS expects the APK to be output to a certain folder and the adb command to execute the install may be reliant on the AGP defined location.
l
ok if I get you right, I shouldn't rename it in this early phase because the convention expects a specific apk output and other tasks like installing this apk on the device depend on this specific file name. But a solution would be to rename the apk at the end of the task chain? Is that correct? Btw. I'm not using any CLI, I only work locally, it's all really simple at the moment. Just want to have the final apk renamed to xy-whatever.apk so I do not have to rename it manually when sharing it. I guess I will have to copy it to another location otherwise I would break the up-to-date status right?
d
The include would just be *.apk as that is the file to find. You can use rename to specify the name when the copy executes
x
Note that SingleArtifact.APK is a folder that can contain more than one APK in some (rare) cases. You need special handling to look at the folder content. See this example task (and the rest of this recipe.)