Skip to content

Commit

Permalink
Refactor to flavorBuildType based tasks
Browse files Browse the repository at this point in the history
  • Loading branch information
tabere-ubique committed Sep 6, 2024
1 parent c3faac5 commit a09b5ed
Show file tree
Hide file tree
Showing 7 changed files with 198 additions and 241 deletions.
1 change: 0 additions & 1 deletion appexample/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ dependencies {

linthPlugin {
uploadKey = "f1c8846e-0c3a-44ac-b56a-53feb91d6383"
flavors = "dev"

// proxy = "192.168.8.167:8888"
}
162 changes: 82 additions & 80 deletions plugin-build/plugin/src/main/java/ch/ubique/linth/IconTask.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ abstract class IconTask : DefaultTask() {
}

@get:Input
abstract var flavorAndBuildType: Set<Pair<String, String>>
abstract var flavor: String

@get:Input
abstract var buildType: String

@get:InputFile
@get:Optional
Expand All @@ -38,94 +41,93 @@ abstract class IconTask : DefaultTask() {
)

val generatedResDir = File("$buildDir/generated/res/launcher-icon/")

// get banner label
val defaultLabelEnabled = false//android.defaultConfig.launcherIconLabelEnabled
val flavorLabelEnabled = true//flavor.launcherIconLabelEnabled

val bannerLabel = if (flavorLabelEnabled) {
flavor
} else {
null
}

flavorAndBuildType.forEach { (flavor, buildType) ->
// get banner label
val defaultLabelEnabled = false//android.defaultConfig.launcherIconLabelEnabled
val flavorLabelEnabled = true//flavor.launcherIconLabelEnabled

val bannerLabel = if (flavorLabelEnabled) {
flavor
val manifestFile = project.getMergedManifestFile(flavor, buildType)

val androidModules: List<BaseExtension> = project.configurations
.asSequence()
.flatMap { it.dependencies }
.filterIsInstance<ProjectDependency>()
.map { it.dependencyProject }
.distinct()
.mapNotNull { it.extensions.findByType(BaseExtension::class.java) }
.toList()

val resDirs: List<File> = androidModules
.flatMap {
listOfNotNull(
it.sourceSets.findByName(flavor),
it.sourceSets.findByName("main")
)
}
.flatMap { it.res.srcDirs }
.filter { !it.path.contains("generated") }

val allIcons = IconUtils.findIcons(resDirs, manifestFile)

if (targetWebIcon != null) {
targetWebIcon.delete()

// Search for web icon source
val webIconSource = (
(File(moduleDir, "src/${flavor.lowercase()}").listFiles() ?: arrayOf()) +
(File(moduleDir, "src/main").listFiles() ?: arrayOf()) +
(moduleDir.listFiles() ?: arrayOf())
).find { it.name.matches(Regex(".*(web|playstore|512)\\.(png|webp)")) }
?: IconUtils.findLargestIcon(allIcons) // Fallback if not found

if (webIconSource == null) {
println("$name: web icon source not found")
} else if (bannerLabel.isNullOrEmpty()) {
// No label, so we only copy the sourceIcon
println("$name: web icon: $webIconSource")
webIconSource.copyTo(targetWebIcon, overwrite = true)
} else {
null
println("$name: web icon: $webIconSource")
IconUtils.drawLabel(webIconSource, targetWebIcon, bannerLabel, adaptive = false)
}
}

val manifestFile = project.getMergedManifestFile(flavor, buildType)

val androidModules: List<BaseExtension> = project.configurations
.asSequence()
.flatMap { it.dependencies }
.filterIsInstance<ProjectDependency>()
.map { it.dependencyProject }
.distinct()
.mapNotNull { it.extensions.findByType(BaseExtension::class.java) }
.toList()

val resDirs: List<File> = androidModules
.flatMap {
listOfNotNull(
it.sourceSets.findByName(flavor),
it.sourceSets.findByName("main")
)
}
.flatMap { it.res.srcDirs }
.filter { !it.path.contains("generated") }

val allIcons = IconUtils.findIcons(resDirs, manifestFile)

if (targetWebIcon != null) {
targetWebIcon.delete()

// Search for web icon source
val webIconSource = (
(File(moduleDir, "src/${flavor.lowercase()}").listFiles() ?: arrayOf()) +
(File(moduleDir, "src/main").listFiles() ?: arrayOf()) +
(moduleDir.listFiles() ?: arrayOf())
).find { it.name.matches(Regex(".*(web|playstore|512)\\.(png|webp)")) }
?: IconUtils.findLargestIcon(allIcons) // Fallback if not found

if (webIconSource == null) {
println("$name: web icon source not found")
} else if (bannerLabel.isNullOrEmpty()) {
// No label, so we only copy the sourceIcon
println("$name: web icon: $webIconSource")
webIconSource.copyTo(targetWebIcon, overwrite = true)
} else {
println("$name: web icon: $webIconSource")
IconUtils.drawLabel(webIconSource, targetWebIcon, bannerLabel, adaptive = false)
}
}
if (bannerLabel.isNullOrEmpty()) {
// No label
println("$name: skipped icon labelling")
return
}

if (bannerLabel.isNullOrEmpty()) {
// No label
println("$name: skipped icon labelling")
return
}
allIcons.forEach iconsForEach@{ original ->
val resTypeName = original.parentFile.name
val originalBaseName = original.name.substringBefore(".")
val targetDir = File("${generatedResDir}/${flavor.lowercase()}/$resTypeName")

allIcons.forEach iconsForEach@{ original ->
val resTypeName = original.parentFile.name
val originalBaseName = original.name.substringBefore(".")
val targetDir = File("${generatedResDir}/${flavor.lowercase()}/$resTypeName")

val modified = targetDir.listFiles { file ->
file.name.matches(Regex("$originalBaseName\\.[^.]+"))
}?.firstOrNull()

if (modified != null
&& original.lastModified() <= modified.lastModified()
&& gradleLastModified <= modified.lastModified()
) {
return@iconsForEach
} else {
println("bannerlabel is $bannerLabel")
val target = File(targetDir, original.name)
targetDir.mkdirs()
original.copyTo(target, overwrite = true)
IconUtils.createLayeredLabel(target, bannerLabel, originalBaseName.endsWith("_foreground"))
}
val modified = targetDir.listFiles { file ->
file.name.matches(Regex("$originalBaseName\\.[^.]+"))
}?.firstOrNull()

if (modified != null
&& original.lastModified() <= modified.lastModified()
&& gradleLastModified <= modified.lastModified()
) {
return@iconsForEach
} else {
println("bannerlabel is $bannerLabel")
val target = File(targetDir, original.name)
targetDir.mkdirs()
original.copyTo(target, overwrite = true)
IconUtils.createLayeredLabel(target, bannerLabel, originalBaseName.endsWith("_foreground"))
}

}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,21 @@ abstract class InjectMetaIntoManifestTask : DefaultTask() {
}

@get:Input
abstract var flavorAndBuildType: Set<Pair<String, String>>
abstract var flavor: String

@get:Input
abstract var buildType: String

@TaskAction
fun injectMetadataIntoManifest() {
flavorAndBuildType.forEach { (flavor, buildType) ->
val manifestFile = project.getMergedManifestFile(flavor, buildType)
if (manifestFile.exists()) {
manipulateManifestFile(manifestFile)
} else {
println("Manifest file not found for flavor: $flavor and buildType: $buildType")
}
val manifestFile = project.getMergedManifestFile(flavor, buildType)
if (manifestFile.exists()) {
manipulateManifestFile(manifestFile)
} else {
println("Manifest file not found for flavor: $flavor and buildType: $buildType")
}
}


/**
* Add custom meta data to manifest.
* @param manifestFile
Expand Down
122 changes: 57 additions & 65 deletions plugin-build/plugin/src/main/java/ch/ubique/linth/LinthPlugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,47 +14,33 @@ abstract class LinthPlugin : Plugin<Project> {

val androidExtension = getAndroidExtension(project)

//hook manifestTask into android build process
val injectMetaTask = project.tasks.register("injectMetaDataIntoManifest", InjectMetaIntoManifestTask::class.java) { manifestTask ->

val flavorAndBuildType = mutableSetOf<Pair<String, String>>()

//hook injectMetaTask into android build process
project.afterEvaluate {
androidExtension.applicationVariants.forEach { variant ->
val flavor = variant.flavorName.capitalize()
val buildType = variant.buildType.name.capitalize()
flavorAndBuildType.add(flavor to buildType)
}
manifestTask.flavorAndBuildType = flavorAndBuildType
}
val flavorBuild = flavor + buildType

val injectMetaTask = project.tasks.register(
"injectMetaDataIntoManifest$flavorBuild",
InjectMetaIntoManifestTask::class.java
) { manifestTask ->
manifestTask.flavor = flavor
manifestTask.buildType = buildType
}

//hook injectMetaTask into android build process
project.afterEvaluate {
androidExtension.applicationVariants.forEach { variant ->
variant.outputs.forEach { output ->
output.processManifestProvider.get().finalizedBy(injectMetaTask)
}
}
}

val iconTask = project.tasks.register("generateAppIcon", IconTask::class.java) { iconTask ->

val flavorAndBuildType = mutableSetOf<Pair<String, String>>()

androidExtension.applicationVariants.forEach { variant ->
val flavor = variant.flavorName.capitalize()
val buildType = variant.buildType.name.capitalize()
flavorAndBuildType.add(flavor to buildType)
}

iconTask.flavorAndBuildType = flavorAndBuildType
iconTask.targetWebIcon = null
}

//hook iconTask into android build process
project.afterEvaluate {

val buildDir = project.layout.buildDirectory.asFile.get()

//make sure generated sources are used by build process
androidExtension.productFlavors.configureEach { flavor ->
// Add the property 'launcherIconLabel' to each product flavor and set the default value to its name
//flavor.set("launcherIconLabel", flavor.name)
Expand All @@ -69,60 +55,66 @@ abstract class LinthPlugin : Plugin<Project> {

androidExtension.applicationVariants.forEach { variant ->
val variantName = variant.name.capitalize()
val flavor = variant.flavorName.capitalize()
val buildType = variant.buildType.name.capitalize()
val flavorBuild = flavor + buildType

val iconTask = project.tasks.register("generateAppIcon$flavorBuild", IconTask::class.java) { iconTask ->
iconTask.flavor = flavor
iconTask.buildType = buildType
iconTask.targetWebIcon = null
}

variant.outputs.forEach { output ->
iconTask.dependsOn(output.processManifestProvider)
project.tasks.named("generate${variantName}Resources") {
it.dependsOn(iconTask)
}
}

}
}

project.tasks.register("uploadToUbDiag", UploadToUbDiagTask::class.java) { uploadTask ->

uploadTask.uploadKey = extension.uploadKey.get()
uploadTask.proxy = extension.proxy.orNull

// setup upload task
val uploadRequests = mutableListOf<UploadRequest>()
val uploadFlavors = extension.flavors.orNull?.split(",")?.map { it.trim() }

val minSdk = requireNotNull(androidExtension.defaultConfig.minSdk)
val targetSdk = requireNotNull(androidExtension.defaultConfig.targetSdk)
val versionName = requireNotNull(androidExtension.defaultConfig.versionName)
//hook uploadTask into android build process
project.afterEvaluate {

androidExtension.applicationVariants.forEach { variant ->
val flavor = variant.flavorName.capitalize()
val buildType = variant.buildType.name.capitalize()
val flavorBuild = flavor + buildType
if (buildType != "Release") return@forEach

val packageName = variant.applicationId
if (uploadFlavors == null || uploadFlavors.contains(variant.flavorName)) {
uploadTask.dependsOn(project.tasks.named("assemble${flavor}Release"))

variant.outputs.forEach {
if (it.outputFile.parentFile.name == "release") {
val uploadRequest = UploadRequest(
apk = it.outputFile,
appIcon = it.outputFile,
appName = "some fancy name",
packageName = packageName,
flavor = flavor,
branch = "someFancyBranch",
minSdk = minSdk,
targetSdk = targetSdk,
usesFeature = emptyList(),
buildNumber = 0L,
buildTime = 0L,
buildBatch = "buildBatch",
changelog = "Some fancy changelog",
signature = "someFancySignature",
version = versionName,
)
uploadRequests.add(uploadRequest)
}
}
val minSdk = requireNotNull(androidExtension.defaultConfig.minSdk)
val targetSdk = requireNotNull(androidExtension.defaultConfig.targetSdk)
val versionName = requireNotNull(androidExtension.defaultConfig.versionName)

val uploadRequest = variant.outputs.first().let {
UploadRequest(
apk = it.outputFile,
appIcon = it.outputFile,
appName = "some fancy name",
packageName = packageName,
flavor = flavor,
branch = "someFancyBranch",
minSdk = minSdk,
targetSdk = targetSdk,
usesFeature = emptyList(),
buildNumber = 0L,
buildTime = 0L,
buildBatch = "buildBatch",
changelog = "Some fancy changelog",
signature = "someFancySignature",
version = versionName,
)
}
}

uploadTask.uploadRequests = uploadRequests.toList()
project.tasks.register("uploadToLinth$flavorBuild", UploadToLinthBackend::class.java) { uploadTask ->
uploadTask.uploadKey = extension.uploadKey.get()
uploadTask.proxy = extension.proxy.orNull
uploadTask.uploadRequest = uploadRequest
}
}
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ abstract class LinthPluginConfig
constructor(project: Project) {
private val objects = project.objects

val flavors: Property<String> = objects.property(String::class.java)
val uploadKey: Property<String> = objects.property(String::class.java)

val proxy: Property<String> = objects.property(String::class.java)
Expand Down
Loading

0 comments on commit a09b5ed

Please sign in to comment.