Skip to content

Commit

Permalink
refactor(core.gradle-plugin): 将不同AGP版本兼容代码重构到AGPCompat接口中
Browse files Browse the repository at this point in the history
  • Loading branch information
shifujun committed Jan 7, 2022
1 parent c2aa507 commit 8c366d2
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 55 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Tencent is pleased to support the open source community by making Tencent Shadow available.
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License"); you may not use
* this file except in compliance with the License. You may obtain a copy of
* the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package com.tencent.shadow.core.gradle

import com.android.build.gradle.BaseExtension
import com.android.build.gradle.tasks.ManifestProcessorTask
import org.gradle.api.Project
import java.io.File

/**
* 不同版本AGP的兼容层
*/
internal interface AGPCompat {
fun getBaseExtension(project: Project): BaseExtension
fun getManifestFile(processManifestTask: ManifestProcessorTask): File
fun getPackageForR(project: Project, variantName: String): String
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.tencent.shadow.core.gradle

import com.android.SdkConstants
import com.android.build.gradle.AppPlugin
import com.android.build.gradle.BaseExtension
import com.android.build.gradle.tasks.ManifestProcessorTask
import com.android.build.gradle.tasks.ProcessApplicationManifest
import com.android.build.gradle.tasks.ProcessMultiApkApplicationManifest
import org.gradle.api.Project
import org.gradle.api.plugins.BasePlugin
import org.gradle.api.provider.Property
import java.io.File
import kotlin.reflect.full.declaredFunctions
import kotlin.reflect.jvm.isAccessible

internal class AGPCompatImpl : AGPCompat {
override fun getBaseExtension(project: Project): BaseExtension {
val plugin = project.plugins.getPlugin(AppPlugin::class.java)
if (com.android.builder.model.Version.ANDROID_GRADLE_PLUGIN_VERSION == "3.0.0") {
val method = BasePlugin::class.declaredFunctions.first { it.name == "getExtension" }
method.isAccessible = true
return method.call(plugin) as BaseExtension
} else {
return project.extensions.getByName("android") as BaseExtension
}
}

override fun getManifestFile(processManifestTask: ManifestProcessorTask) =
when (processManifestTask) {
is ProcessMultiApkApplicationManifest -> {
processManifestTask.mainMergedManifest.get().asFile
}
is ProcessApplicationManifest -> {
try {
processManifestTask.mergedManifest.get().asFile
} catch (e: NoSuchMethodError) {
//AGP小于4.1.0
val dir =
processManifestTask.outputs.files.files
.first { it.path.contains("merged_manifests") }
File(dir, SdkConstants.ANDROID_MANIFEST_XML)
}
}
else -> throw IllegalStateException("不支持的Task类型:${processManifestTask.javaClass}")
}

override fun getPackageForR(project: Project, variantName: String): String {
val linkApplicationAndroidResourcesTask =
project.tasks.getByName("process${variantName.capitalize()}Resources")
return (when {

linkApplicationAndroidResourcesTask.hasProperty("namespace") -> {
linkApplicationAndroidResourcesTask.property("namespace")
}
linkApplicationAndroidResourcesTask.hasProperty("originalApplicationId") -> {
linkApplicationAndroidResourcesTask.property("originalApplicationId")
}
else -> throw IllegalStateException("不支持的AGP版本")
} as Property<String>).get()
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -18,32 +18,25 @@

package com.tencent.shadow.core.gradle

import com.android.SdkConstants.ANDROID_MANIFEST_XML
import com.android.build.gradle.AppExtension
import com.android.build.gradle.AppPlugin
import com.android.build.gradle.BaseExtension
import com.android.build.gradle.tasks.ManifestProcessorTask
import com.android.build.gradle.tasks.ProcessApplicationManifest
import com.android.build.gradle.tasks.ProcessMultiApkApplicationManifest
import com.tencent.shadow.core.gradle.extensions.PackagePluginExtension
import com.tencent.shadow.core.manifest_parser.generatePluginManifest
import com.tencent.shadow.core.transform.ShadowTransform
import com.tencent.shadow.core.transform_kit.AndroidClassPoolBuilder
import com.tencent.shadow.core.transform_kit.ClassPoolBuilder
import org.gradle.api.*
import org.gradle.api.plugins.BasePlugin
import org.gradle.api.provider.Property
import java.io.File
import kotlin.reflect.full.declaredFunctions
import kotlin.reflect.jvm.isAccessible

class ShadowPlugin : Plugin<Project> {

private lateinit var androidClassPoolBuilder: ClassPoolBuilder
private lateinit var contextClassLoader: ClassLoader
private lateinit var agpCompat: AGPCompat

override fun apply(project: Project) {
val baseExtension = getBaseExtension(project)
agpCompat = buildAgpCompat(project)
val baseExtension = agpCompat.getBaseExtension(project)

//在这里取到的contextClassLoader包含运行时库(classpath方式引入的)shadow-runtime
contextClassLoader = Thread.currentThread().contextClassLoader
Expand Down Expand Up @@ -115,7 +108,7 @@ class ShadowPlugin : Plugin<Project> {
}.forEach { pluginVariant ->
val output = pluginVariant.outputs.first()
val processManifestTask = output.processManifestProvider.get()
val manifestFile = getManifestFile(processManifestTask)
val manifestFile = agpCompat.getManifestFile(processManifestTask)
val variantName = manifestFile.parentFile.name
val outputDir = File(project.buildDir, "generated/source/pluginManifest/$variantName")

Expand All @@ -125,7 +118,7 @@ class ShadowPlugin : Plugin<Project> {
it.inputs.file(manifestFile)
it.outputs.dir(outputDir).withPropertyName("outputDir")

val packageForR = getPackageForR(project, variantName)
val packageForR = agpCompat.getPackageForR(project, variantName)

it.doLast {
generatePluginManifest(
Expand Down Expand Up @@ -183,50 +176,9 @@ class ShadowPlugin : Plugin<Project> {
var useHostContext: Array<String> = emptyArray()
}

fun getBaseExtension(project: Project): BaseExtension {
val plugin = project.plugins.getPlugin(AppPlugin::class.java)
if (com.android.builder.model.Version.ANDROID_GRADLE_PLUGIN_VERSION == "3.0.0") {
val method = BasePlugin::class.declaredFunctions.first { it.name == "getExtension" }
method.isAccessible = true
return method.call(plugin) as BaseExtension
} else {
return project.extensions.getByName("android") as BaseExtension
}
}

companion object {
private fun getManifestFile(processManifestTask: ManifestProcessorTask) =
when (processManifestTask) {
is ProcessMultiApkApplicationManifest -> {
processManifestTask.mainMergedManifest.get().asFile
}
is ProcessApplicationManifest -> {
try {
processManifestTask.mergedManifest.get().asFile
} catch (e: NoSuchMethodError) {
//AGP小于4.1.0
val dir =
processManifestTask.outputs.files.files
.first { it.path.contains("merged_manifests") }
File(dir, ANDROID_MANIFEST_XML)
}
}
else -> throw IllegalStateException("不支持的Task类型:${processManifestTask.javaClass}")
}

private fun getPackageForR(project: Project, variantName: String): String {
val linkApplicationAndroidResourcesTask =
project.tasks.getByName("process${variantName.capitalize()}Resources")
return (when {

linkApplicationAndroidResourcesTask.hasProperty("namespace") -> {
linkApplicationAndroidResourcesTask.property("namespace")
}
linkApplicationAndroidResourcesTask.hasProperty("originalApplicationId") -> {
linkApplicationAndroidResourcesTask.property("originalApplicationId")
}
else -> throw IllegalStateException("不支持的AGP版本")
} as Property<String>).get()
private fun buildAgpCompat(project: Project): AGPCompat {
return AGPCompatImpl()
}
}

Expand Down

0 comments on commit 8c366d2

Please sign in to comment.