diff --git a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/beans/WovenResult.kt b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/beans/WovenResult.kt new file mode 100644 index 00000000..8e64c5a8 --- /dev/null +++ b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/beans/WovenResult.kt @@ -0,0 +1,3 @@ +package com.flyjingfish.android_aop_plugin.beans + +class WovenResult(val byteArray: ByteArray,val modified: Boolean) \ No newline at end of file diff --git a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/config/RootBooleanConfig.kt b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/config/RootBooleanConfig.kt index 0a7de205..e9679ff2 100644 --- a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/config/RootBooleanConfig.kt +++ b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/config/RootBooleanConfig.kt @@ -5,7 +5,8 @@ enum class RootBooleanConfig( val defaultValue: Boolean, ) { DEBUG_MODE("androidAop.debugMode", false), - REFLECT_INVOKE_METHOD("androidAop.reflectInvokeMethod", false), ONLY_DEBUG("androidAop.debugMode.variantOnlyDebug", true), - INCREMENTAL("androidAop.debugMode.isIncremental", true); + INCREMENTAL("androidAop.debugMode.isIncremental", true), + REFLECT_INVOKE_METHOD("androidAop.reflectInvokeMethod", false), + REFLECT_INVOKE_METHOD_ONLY_DEBUG("androidAop.reflectInvokeMethod.variantOnlyDebug", false); } \ No newline at end of file diff --git a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/plugin/BasePlugin.kt b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/plugin/BasePlugin.kt index f82a0d7e..8fbc1af8 100644 --- a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/plugin/BasePlugin.kt +++ b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/plugin/BasePlugin.kt @@ -5,7 +5,8 @@ import org.gradle.api.Plugin import org.gradle.api.Project abstract class BasePlugin :Plugin { - var reflectInvokeMethod = false + private var reflectInvokeMethod = false + private var reflectInvokeMethodOnlyDebug = false private var debugMode = false private var onlyDebug = false private var isIncremental = true @@ -14,10 +15,12 @@ abstract class BasePlugin :Plugin { val debugModeStr = project.properties[RootBooleanConfig.DEBUG_MODE.propertyName]?:"${RootBooleanConfig.DEBUG_MODE.defaultValue}" val onlyModeStr = project.properties[RootBooleanConfig.ONLY_DEBUG.propertyName]?:"${RootBooleanConfig.ONLY_DEBUG.defaultValue}" val isIncrementalStr = project.properties[RootBooleanConfig.INCREMENTAL.propertyName]?:"${RootBooleanConfig.INCREMENTAL.defaultValue}" + val reflectInvokeMethodDebugStr = project.properties[RootBooleanConfig.REFLECT_INVOKE_METHOD_ONLY_DEBUG.propertyName]?:"${RootBooleanConfig.REFLECT_INVOKE_METHOD_ONLY_DEBUG.defaultValue}" debugMode = debugModeStr.toString() == "true" reflectInvokeMethod = reflectInvokeMethodStr.toString() == "true" onlyDebug = onlyModeStr.toString() == "true" isIncremental = isIncrementalStr.toString() == "true" + reflectInvokeMethodOnlyDebug = reflectInvokeMethodDebugStr.toString() == "true" } fun isIncremental():Boolean{ @@ -43,4 +46,20 @@ abstract class BasePlugin :Plugin { false } } + + fun isReflectInvokeMethod(buildTypeName :String?,variantName :String):Boolean{ + return if (reflectInvokeMethod){ + if (reflectInvokeMethodOnlyDebug){ + if (buildTypeName != null){ + buildTypeName.lowercase() == "debug" + }else{ + variantName.lowercase().contains("debug") + } + }else{ + true + } + }else{ + false + } + } } \ No newline at end of file diff --git a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/plugin/CompilePlugin.kt b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/plugin/CompilePlugin.kt index b896bdbf..8985d8d0 100644 --- a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/plugin/CompilePlugin.kt +++ b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/plugin/CompilePlugin.kt @@ -137,7 +137,7 @@ class CompilePlugin(private val root:Boolean): BasePlugin() { } } if (localInput.isNotEmpty()){ - ClassFileUtils.reflectInvokeMethod = reflectInvokeMethod + ClassFileUtils.reflectInvokeMethod = isReflectInvokeMethod(buildTypeName,variantName) val output = File(javaCompile.destinationDirectory.asFile.orNull.toString()) val task = CompileAndroidAopTask(jarInput,localInput,output,project,isApp, File(Utils.aopCompileTempDir(project,variantName)), diff --git a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/plugin/TransformPlugin.kt b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/plugin/TransformPlugin.kt index 522031a9..2fa3ce9f 100644 --- a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/plugin/TransformPlugin.kt +++ b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/plugin/TransformPlugin.kt @@ -29,7 +29,7 @@ object TransformPlugin : BasePlugin() { // println("TransformPlugin=variant=${variant.name}, variant.buildType=${variant.buildType},isDebug=${isDebugMode(buildTypeName,variant.name)}") if (androidAopConfig.enabled && !isDebugMode(buildTypeName,variant.name)){ ClassFileUtils.debugMode = false - ClassFileUtils.reflectInvokeMethod = reflectInvokeMethod + ClassFileUtils.reflectInvokeMethod = isReflectInvokeMethod(buildTypeName,variant.name) val task = project.tasks.register("${variant.name}AssembleAndroidAopTask", AssembleAndroidAopTask::class.java){ it.variant = variant.name } diff --git a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/MethodReplaceInvokeAdapter.kt b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/MethodReplaceInvokeAdapter.kt index beacb9c4..ebef8285 100644 --- a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/MethodReplaceInvokeAdapter.kt +++ b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/MethodReplaceInvokeAdapter.kt @@ -10,6 +10,11 @@ import org.objectweb.asm.Opcodes class MethodReplaceInvokeAdapter(private val className:String, private val methodNameDesc:String, methodVisitor: MethodVisitor?) : MethodVisitor(Opcodes.ASM9, methodVisitor) { + + interface OnResultListener{ + fun onBack() + } + var onResultListener : OnResultListener ?= null override fun visitMethodInsn( opcode: Int, owner: String, @@ -47,6 +52,7 @@ class MethodReplaceInvokeAdapter(private val className:String, replaceMethodInfo.newMethodDesc, false ) + onResultListener?.onBack() } else { super.visitMethodInsn(opcode, owner, name, descriptor, isInterface) } diff --git a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/MethodReplaceInvokeVisitor.kt b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/MethodReplaceInvokeVisitor.kt index c4a26a18..e4d816db 100644 --- a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/MethodReplaceInvokeVisitor.kt +++ b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/MethodReplaceInvokeVisitor.kt @@ -9,6 +9,7 @@ open class MethodReplaceInvokeVisitor( classVisitor: ClassVisitor ) : ReplaceBaseClassVisitor(classVisitor) { lateinit var className: String + var replaced = false override fun visit( version: Int, access: Int, @@ -31,6 +32,11 @@ open class MethodReplaceInvokeVisitor( if (mv != null && Utils.isHasMethodBody(access)) { mv = MethodReplaceInvokeAdapter(className,"$name$descriptor",mv) + mv.onResultListener = object : MethodReplaceInvokeAdapter.OnResultListener{ + override fun onBack() { + replaced = true + } + } } return mv } diff --git a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/ReplaceBaseClassVisitor.kt b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/ReplaceBaseClassVisitor.kt index f1d84721..e27e173a 100644 --- a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/ReplaceBaseClassVisitor.kt +++ b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/scanner_visitor/ReplaceBaseClassVisitor.kt @@ -17,7 +17,7 @@ open class ReplaceBaseClassVisitor( ) : ClassVisitor(Opcodes.ASM9, classVisitor) { lateinit var thisClassName:String private var oldSuperName:String?=null - private var modifyExtendsClassName:String?=null + var modifyExtendsClassName:String?=null var isHasStaticClock = false var hasCollect = false override fun visit( diff --git a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/tasks/AssembleAndroidAopTask.kt b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/tasks/AssembleAndroidAopTask.kt index 5ef39c68..456babaa 100644 --- a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/tasks/AssembleAndroidAopTask.kt +++ b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/tasks/AssembleAndroidAopTask.kt @@ -234,7 +234,7 @@ abstract class AssembleAndroidAopTask : DefaultTask() { if (byteArray.isNotEmpty()){ try { val newByteArray = AopTaskUtils.wovenIntoCodeForReplace(byteArray) - ByteArrayInputStream(newByteArray).use { + ByteArrayInputStream(newByteArray.byteArray).use { jarOutput.saveEntry(jarEntryName,it) } // newClasses.add(newByteArray) @@ -254,7 +254,7 @@ abstract class AssembleAndroidAopTask : DefaultTask() { if (byteArray.isNotEmpty()){ try { val newByteArray = AopTaskUtils.wovenIntoCodeForExtendsClass(byteArray) - ByteArrayInputStream(newByteArray).use { + ByteArrayInputStream(newByteArray.byteArray).use { jarOutput.saveEntry(jarEntryName,it) } // newClasses.add(newByteArray) @@ -387,7 +387,7 @@ abstract class AssembleAndroidAopTask : DefaultTask() { if (byteArray.isNotEmpty()){ try { val newByteArray = AopTaskUtils.wovenIntoCodeForReplace(byteArray) - ByteArrayInputStream(newByteArray).use { + ByteArrayInputStream(newByteArray.byteArray).use { jarOutput.saveEntry(entryName,it) } // newClasses.add(newByteArray) @@ -407,7 +407,7 @@ abstract class AssembleAndroidAopTask : DefaultTask() { if (byteArray.isNotEmpty()){ try { val newByteArray = AopTaskUtils.wovenIntoCodeForExtendsClass(byteArray) - ByteArrayInputStream(newByteArray).use { + ByteArrayInputStream(newByteArray.byteArray).use { jarOutput.saveEntry(entryName,it) } // newClasses.add(newByteArray) diff --git a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/tasks/CompileAndroidAopTask.kt b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/tasks/CompileAndroidAopTask.kt index 895d3a05..43e8db02 100644 --- a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/tasks/CompileAndroidAopTask.kt +++ b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/tasks/CompileAndroidAopTask.kt @@ -109,19 +109,23 @@ class CompileAndroidAopTask( } val relativePath = directory.toURI().relativize(file.toURI()).path - val outFile = File(tmpCompileDir.absolutePath+"/"+relativePath) - if (!outFile.parentFile.exists()){ - outFile.parentFile.mkdirs() - } - if (!outFile.exists()){ - outFile.createNewFile() - } - val tmpFile = TmpFile(file,outFile) - tempFiles.add(tmpFile) + val methodsRecord: HashMap? = WovenInfoUtils.getClassMethodRecord(file.absolutePath) val thisClassName = Utils.slashToDotClassName(entryName).replace(_CLASS,"") val hasCollect = WovenInfoUtils.aopCollectClassMap[thisClassName] != null + val outFile = File(tmpCompileDir.absolutePath+"/"+relativePath) + fun mkOutFile(){ + if (!outFile.parentFile.exists()){ + outFile.parentFile.mkdirs() + } + if (!outFile.exists()){ + outFile.createNewFile() + } + val tmpFile = TmpFile(file,outFile) + tempFiles.add(tmpFile) + } if (methodsRecord != null){ + mkOutFile() FileInputStream(file).use { inputs -> val byteArray = WovenIntoCode.modifyClass(inputs.readAllBytes(),methodsRecord,hasReplace) ByteArrayInputStream(byteArray).use { @@ -131,9 +135,9 @@ class CompileAndroidAopTask( } }else{ fun copy(){ - file.inputStream().use { - outFile.saveEntry(it) - } +// file.inputStream().use { +// outFile.saveEntry(it) +// } } val isClassFile = file.name.endsWith(_CLASS) val tranEntryName = file.absolutePath.replace("/", ".") @@ -146,8 +150,11 @@ class CompileAndroidAopTask( if (byteArray.isNotEmpty()){ try { val newByteArray = AopTaskUtils.wovenIntoCodeForReplace(byteArray) - ByteArrayInputStream(newByteArray).use { - outFile.saveEntry(it) + if (newByteArray.modified){ + mkOutFile() + ByteArrayInputStream(newByteArray.byteArray).use { + outFile.saveEntry(it) + } } } catch (e: Exception) { copy() @@ -165,8 +172,11 @@ class CompileAndroidAopTask( if (byteArray.isNotEmpty()){ try { val newByteArray = AopTaskUtils.wovenIntoCodeForExtendsClass(byteArray) - ByteArrayInputStream(newByteArray).use { - outFile.saveEntry(it) + if (newByteArray.modified){ + mkOutFile() + ByteArrayInputStream(newByteArray.byteArray).use { + outFile.saveEntry(it) + } } } catch (e: Exception) { copy() @@ -211,6 +221,7 @@ class CompileAndroidAopTask( WovenIntoCode.wovenStaticCode(cw, thisClassName) } + mkOutFile() val newByteArray = cw.toByteArray() ByteArrayInputStream(newByteArray).use { outFile.saveEntry(it) diff --git a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/utils/AopTaskUtils.kt b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/utils/AopTaskUtils.kt index 047001e5..32b4b8e2 100644 --- a/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/utils/AopTaskUtils.kt +++ b/android-aop-plugin/src/main/kotlin/com/flyjingfish/android_aop_plugin/utils/AopTaskUtils.kt @@ -3,6 +3,7 @@ package com.flyjingfish.android_aop_plugin.utils import com.flyjingfish.android_aop_plugin.beans.ClassMethodRecord import com.flyjingfish.android_aop_plugin.beans.MethodRecord import com.flyjingfish.android_aop_plugin.beans.ReplaceMethodInfo +import com.flyjingfish.android_aop_plugin.beans.WovenResult import com.flyjingfish.android_aop_plugin.config.AndroidAopConfig import com.flyjingfish.android_aop_plugin.scanner_visitor.ClassSuperScanner import com.flyjingfish.android_aop_plugin.scanner_visitor.MethodReplaceInvokeVisitor @@ -256,12 +257,13 @@ object AopTaskUtils { } - fun wovenIntoCodeForReplace(byteArray: ByteArray): ByteArray { + fun wovenIntoCodeForReplace(byteArray: ByteArray): WovenResult { val cr = ClassReader(byteArray) val cw = ClassWriter(ClassWriter.COMPUTE_FRAMES) var thisHasCollect = false var thisHasStaticClock = false var thisCollectClassName :String ?= null + var replaceResult = false val cv = object : MethodReplaceInvokeVisitor(cw){ override fun visit( version: Int, @@ -292,22 +294,29 @@ object AopTaskUtils { thisHasStaticClock = isHasStaticClock return mv } + + override fun visitEnd() { + super.visitEnd() + replaceResult = replaced + } } thisCollectClassName?.let { if (thisHasCollect && !thisHasStaticClock){ WovenIntoCode.wovenStaticCode(cw, it) + replaceResult = true } } cr.accept(cv, ClassReader.SKIP_DEBUG or ClassReader.SKIP_FRAMES) - return cw.toByteArray() + return WovenResult(cw.toByteArray(),replaceResult) } - fun wovenIntoCodeForExtendsClass(byteArray:ByteArray):ByteArray{ + fun wovenIntoCodeForExtendsClass(byteArray:ByteArray): WovenResult { val cr = ClassReader(byteArray) val cw = ClassWriter(ClassWriter.COMPUTE_FRAMES) var thisHasCollect = false var thisHasStaticClock = false var thisCollectClassName :String ?= null + var replaceResult = false val cv = object : ReplaceBaseClassVisitor(cw){ override fun visit( version: Int, @@ -320,6 +329,7 @@ object AopTaskUtils { super.visit(version, access, name, signature, superName, interfaces) thisHasCollect = hasCollect thisCollectClassName = thisClassName + replaceResult = modifyExtendsClassName != null } override fun visitMethod( access: Int, @@ -342,10 +352,12 @@ object AopTaskUtils { thisCollectClassName?.let { if (thisHasCollect && !thisHasStaticClock){ WovenIntoCode.wovenStaticCode(cw, it) + replaceResult = true } } cr.accept(cv, ClassReader.SKIP_DEBUG or ClassReader.SKIP_FRAMES) - return cw.toByteArray() + + return WovenResult(cw.toByteArray(),replaceResult) } } \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 598b0baa..1a6be15e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -45,8 +45,9 @@ TestVersion = 1.8.3 SonatypeTestCode = 1395 TestType = 0 androidAop.debugMode = true -androidAop.reflectInvokeMethod = false androidAop.debugMode.variantOnlyDebug = true +androidAop.reflectInvokeMethod = false +androidAop.reflectInvokeMethod.variantOnlyDebug = false # 0 mavenLocal 1 SonatypeCache 2 mavenCentral