Last active
March 9, 2025 09:01
-
-
Save autonomousapps/09b4737e5bb860d9388976354bf54673 to your computer and use it in GitHub Desktop.
Provider for single APK using latest AGP APIs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.gradle.api.file.Directory | |
import org.gradle.api.provider.Property | |
import org.gradle.api.provider.Provider | |
import org.gradle.api.tasks.InputFiles | |
import java.io.File | |
import javax.inject.Inject | |
/** | |
* This essentially encapsulates the pattern described in | |
* [ExamplePlugin in AGP's "Gradle Recipes" repo](https://github.com/android/gradle-recipes/blob/agp-7.0/BuildSrc/getApksTest/buildSrc/src/main/kotlin/ExamplePlugin.kt#L45-L48). | |
* | |
* Instances should be created with the [ObjectFactory][org.gradle.api.model.ObjectFactory]. See | |
* `Artifacts.findApk()`. nb: We cannot encapsulate the construction of this type here because this module | |
* _shall not_ have any Android dependencies, by design. | |
* | |
* This should be injected into tasks like so: | |
* ``` | |
* @get:Nested | |
* abstract val androidApks: Property<AndroidApks> | |
* ``` | |
*/ | |
abstract class AndroidApks @Inject constructor( | |
@get:InputFiles val apkDirectory: Provider<Directory>, | |
private val loader: Property<FileSystemLoader> | |
) { | |
/** | |
* Causes the [loader] to load the APKs from the [apkDirectory] provider, returning a provider to the | |
* list of APKs. In principle, there can be zero, one, or multiple APKs, but in practice there should | |
* always be exactly one. At the time of writing, the task that produces the primary production APK | |
* is named `package<<variant>>` (e.g., `packageDebug`). | |
*/ | |
fun load(): Provider<List<File>> = loader.flatMap { it.load(apkDirectory) } | |
/** | |
* Resolves the provider chain immediately and returns the single APK it resolves to. Throws if the | |
* underlying collection is empty or has more than one element. | |
*/ | |
fun singleFile(): File = load().get().single() | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import com.android.build.api.artifact.Artifacts | |
import com.android.build.api.artifact.SingleArtifact.APK | |
class AndroidGradlePlugin7_0( | |
private val project: Project | |
) : AndroidGradlePlugin { | |
fun Artifacts.findApk(): AndroidApks = project.objects.newInstanceOf( | |
get(APK), | |
project.objects.property(FileSystemLoader::class.java).apply { | |
set(project.objects.newInstanceOf<FileSystemLoader7_0>(getBuiltArtifactsLoader())) | |
disallowChanges() | |
} | |
) | |
} | |
inline fun <reified T> ObjectFactory.newInstanceOf(vararg arguments: Any?): T { | |
return newInstance(T::class.java, *arguments) | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import com.android.build.api.variant.BuiltArtifactsLoader | |
import org.gradle.api.file.Directory | |
import org.gradle.api.provider.Provider | |
import java.io.File | |
import javax.inject.Inject | |
interface FileSystemLoader { | |
fun load(directory: Provider<Directory>): Provider<List<File>> | |
} | |
abstract class FileSystemLoader7_0 @Inject constructor( | |
private val delegate: BuiltArtifactsLoader | |
) : FileSystemLoader { | |
override fun load(directory: Provider<Directory>): Provider<List<File>> { | |
return directory.map { dir -> | |
delegate.load(dir) ?: error("Expected built artifacts in ${dir.asFile.absolutePath}") | |
}.map { builtArtifacts -> | |
builtArtifacts.elements.map { builtArtifact -> | |
File(builtArtifact.outputFile) | |
} | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
abstract class MyTask : DefaultTask() { | |
@get:Nested | |
abstract val androidApks: Property<AndroidApks> | |
@TaskAction fun action() { | |
val apk = androidApks.get().singleFile() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment