ShadowPlugin

ShadowTransform类设计

gradle配置

//Sample-plugin-app中build.gradle中对应的配置,动态生成config.json的一些参数

packagePlugin {
   pluginTypes {
     debug {
       loaderApkConfig = new Tuple2('sample-loader-debug.apk', ':sample-loader:assembleDebug')
       runtimeApkConfig = new Tuple2('sample-runtime-debug.apk', ':sample-runtime:assembleDebug')
       pluginApks {
         pluginApk1 {
           businessName = 'sample-plugin-app'
           partKey = 'sample-plugin-app'
           buildTask = ':sample-plugin-app:assembleDebug'
           apkName = 'sample-plugin-app-debug.apk'
           apkPath = 'projects/sample/sample-plugin/sample-plugin-app/build/outputs/apk/debug/sample-plugin-app-debug.apk'
         }
       }
     }
 
     release {
   loaderApkConfig = new Tuple2('sample-loader-release.apk', ':sample-loader:assembleRelease')
   runtimeApkConfig = new Tuple2('sample-runtime-release.apk', ':sample-runtime:assembleRelease')
   pluginApks {
     pluginApk1 {
       businessName = 'sample-plugin-app'
       partKey = 'sample-plugin-app'
       buildTask = ':sample-plugin-app:assembleRelease'
       apkName = 'sample-plugin-app-release.apk'
       apkPath = 'projects/sample/sample-plugin/sample-plugin-app/build/outputs/apk/release/sample-plugin-app-release.apk'
     }
   }
 }

}
 
 loaderApkProjectPath = 'projects/sample/sample-plugin/sample-loader'
 
 runtimeApkProjectPath = 'projects/sample/sample-plugin/sample-runtime'
 
 version = 4
 compactVersion = [1, 2, 3]
 uuidNickName = "1.1.5"

ShadowPlugin

class ShadowPlugin : Plugin<Project> {
  override fun apply(project: Project) {

val plugin = project.plugins.getPlugin(AppPlugin::class.java)

val shadowExtension = project.extensions.create("shadow", ShadowExtension::class.java)
 if (!project.hasProperty("disable_shadow_transform")) {
   plugin.extension.registerTransform(ShadowTransform(
       project,
       classPoolBuilder,
       { shadowExtension.transformConfig.useHostContext }
   ))
 }

project.extensions.create("packagePlugin", PackagePluginExtension::class.java, project)
 
 project.afterEvaluate {
   val packagePlugin = project.extensions.findByName("packagePlugin")
   val extension = packagePlugin as PackagePluginExtension
   val buildTypes = extension.buildTypes

val tasks = mutableListOf<Task>()
 for (i in buildTypes) {
   println("buildTypes = " + i.name)
   val task = createPackagePluginTask(project, i)//main
   tasks.add(task)
 }
 if (tasks.isNotEmpty()) {
   project.tasks.create("packageAllPlugin") {
     it.group = "plugin"
     it.description = "打包所有插件"
   }.dependsOn(tasks)
 }
}

CreatePackagePluginTask

internal fun createPackagePluginTask(project: Project, buildType: PluginBuildType): Task {
   return project.tasks.create("package${buildType.name.capitalize()}Plugin", Zip::class.java) {

 it.from(pluginFiles, targetConfigFile)
 val suffix: String? = System.getenv("PluginSuffix")
 if (suffix == null) {
   it.archiveName = "plugin-${buildType.name}.zip"
 } else {
   it.archiveName = "plugin-${buildType.name}-$suffix.zip"
 }
 it.destinationDir = File("${project.rootDir}/build")
}
private fun createGenerateConfigTask(project: Project, buildType: PluginBuildType): Task {
val task = project.tasks.create("generate${buildType.name.capitalize()}Config") {
   it.group = "plugin"
   it.description = "生成插件配置文件"
   it.outputs.file(targetConfigFile)
   it.outputs.upToDateWhen { false }
 }
     .dependsOn(pluginApkTasks)
     .doLast {
 
       println("generateConfig task begin")
       val json = extension.toJson(project, loaderApkName, runtimeApkName, buildType)
 
       val bizWriter = BufferedWriter(FileWriter(targetConfigFile))
       bizWriter.write(json.toJSONString())
       bizWriter.newLine()
       bizWriter.flush()
       bizWriter.close()
 
       println("generateConfig task done")
     }

Extension

PackagePluginExtension

var loaderApkProjectPath = ""
 var runtimeApkProjectPath = ""

 var uuid = ""
 var version: Int = 0
 var uuidNickName = ""
 var compactVersion: Array<Int> = emptyArray()

 var buildTypes: NamedDomainObjectContainer<PluginBuildType>
   
 constructor(project: Project) {
   buildTypes = project.container(PluginBuildType::class.java)
   buildTypes.all {
     it.pluginApks = project.container(PluginApkConfig::class.java)
   }
 }

fun pluginTypes(closure: Closure<PluginBuildType>) {
   buildTypes.configure(closure)
 }  

PluginBuildType

var name = ""

 var loaderApkConfig: Tuple2<String, String> = Tuple2("", "")
 var runtimeApkConfig: Tuple2<String, String> = Tuple2("", "")
 lateinit var pluginApks: NamedDomainObjectContainer<PluginApkConfig>

constructor(name: String) {
   this.name = name
 }

fun pluginApks(closure: Closure<PluginApkConfig>) {
   pluginApks.configure(closure)
 }

PluginApkConfig

var name = ""

 var partKey = ""

 /**
 \* 业务名(空字符串表示同宿主相同业务)
 */
 var businessName = ""

 var apkName = ""
 var apkPath = ""
 var buildTask = ""
 var dependsOn: Array<String> = emptyArray()
 var hostWhiteList: Array<String> = emptyArray()

ShadowExtension

shadow {
   transform {
 //    useHostContext = ['abc']
   }
var transformConfig = TransformConfig()

fun transform(action: Action<in TransformConfig>) {
   action.execute(transformConfig)
 }

TransformConfig

var useHostContext: Array<String> = emptyArray()