All Downloads are FREE. Search and download functionalities are using the official Maven repository.

butterknife.plugin.ButterKnifePlugin.kt Maven / Gradle / Ivy

There is a newer version: 10.2.3
Show newest version
package butterknife.plugin

import com.android.build.gradle.AppExtension
import com.android.build.gradle.AppPlugin
import com.android.build.gradle.FeatureExtension
import com.android.build.gradle.FeaturePlugin
import com.android.build.gradle.LibraryExtension
import com.android.build.gradle.LibraryPlugin
import com.android.build.gradle.api.BaseVariant
import com.android.build.gradle.internal.res.GenerateLibraryRFileTask
import com.android.build.gradle.internal.res.LinkApplicationAndroidResourcesTask
import groovy.util.XmlSlurper
import org.gradle.api.DomainObjectSet
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.plugins.ExtensionContainer
import java.util.concurrent.atomic.AtomicBoolean
import kotlin.reflect.KClass

class ButterKnifePlugin : Plugin {
  override fun apply(project: Project) {
    project.plugins.all {
      when (it) {
        is FeaturePlugin -> {
          project.extensions[FeatureExtension::class].run {
            configureR2Generation(project, featureVariants)
            configureR2Generation(project, libraryVariants)
          }
        }
        is LibraryPlugin -> {
          project.extensions[LibraryExtension::class].run {
            configureR2Generation(project, libraryVariants)
          }
        }
        is AppPlugin -> {
          project.extensions[AppExtension::class].run {
            configureR2Generation(project, applicationVariants)
          }
        }
      }
    }
  }

  // Parse the variant's main manifest file in order to get the package id which is used to create
  // R.java in the right place.
  private fun getPackageName(variant : BaseVariant) : String {
    val slurper = XmlSlurper(false, false)
    val list = variant.sourceSets.map { it.manifestFile }

    // According to the documentation, the earlier files in the list are meant to be overridden by the later ones.
    // So the first file in the sourceSets list should be main.
    val result = slurper.parse(list[0])
    return result.getProperty("@package").toString()
  }

  private fun configureR2Generation(project: Project, variants: DomainObjectSet) {
    variants.all { variant ->
      val useAndroidX = (project.findProperty("android.useAndroidX") as String?)?.toBoolean() ?: false
      val outputDir = project.buildDir.resolve(
          "generated/source/r2/${variant.dirName}")

      val rPackage = getPackageName(variant)
      val once = AtomicBoolean()
      variant.outputs.all { output ->
        val processResources = output.processResources

        // Though there might be multiple outputs, their R files are all the same. Thus, we only
        // need to configure the task once with the R.java input and action.
        if (once.compareAndSet(false, true)) {
          // TODO: switch to better API once exists in AGP (https://issuetracker.google.com/118668005)
          val rFile =
              project.files(
                  when (processResources) {
                    is GenerateLibraryRFileTask -> processResources.textSymbolOutputFile
                    is LinkApplicationAndroidResourcesTask -> processResources.textSymbolOutputFile
                    else -> throw RuntimeException(
                        "Minimum supported Android Gradle Plugin is 3.1.0")
                  })
                  .builtBy(processResources)
          project.tasks.create("generate${variant.name.capitalize()}R2", R2Generator::class.java) {
            it.outputDir = outputDir
            it.rFile = rFile
            it.useAndroidX = useAndroidX
            it.packageName = rPackage
            it.className = "R2"
            variant.registerJavaGeneratingTask(it, outputDir)
          }
        }
      }
    }
  }

  private operator fun  ExtensionContainer.get(type: KClass): T {
    return getByType(type.java)!!
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy