Skip to content

FAQ

1. What to do when there are multiple annotations or matching aspects on the same method

  • When multiple aspects are superimposed on a method, annotations take precedence over matching aspects, and annotation aspects are executed from top to bottom
  • The next aspect will be executed only after * proceed* is called, and the code in the aspect method will be called only after * proceed* is executed on the last aspect among multiple aspects
  • Calling proceed(args) in the previous aspect can update the parameters passed in the method, and the updated parameters of the previous layer will also be obtained in the next aspect
  • When there is an asynchronous call proceed, the return value of the first asynchronous call proceed (that is, the return value of invoke) is the return value of the cut-in method; otherwise, if there is no asynchronous call proceed, the return value is the return value of the last cut-in method

2. Error "ZipFile invalid LOC header (bad signature)" when building

  • Please restart Android Studio and then clean the project

3. Memory leak occurs in the cut-in processing class?

  • This situation is usually because you have made a strong reference in the aspect processing class

4. Want to see all the locations where the aspect code is added

plugins {
...
}
androidAopConfig {
  //Closed by default, enabled after build or packaging, a cut information json file will be generated in app/build/tmp/cutInfo.json
  cutInfoJson true
}
android {
...
}

5. Want to insert code before and after the method

  • Matching aspect
@AndroidAopMatchClassMethod(
    targetClassName = "com.flyjingfish.test_lib.TestMatch",
    methodName = ["test2"],
    type = MatchType.SELF
)
class MatchTestMatchMethod : MatchClassMethod {
    override fun invoke(joinPoint: ProceedJoinPoint, methodName: String): Any? {
        //Insert code before the method
        val value = joinPoint.proceed()
        //Insert code after the method
        return value
    }
}
Click here for more details
  • Annotation aspect
  • class CustomInterceptCut : BasePointCut<CustomIntercept> {
        override fun invoke(
            joinPoint: ProceedJoinPoint,
            annotation: CustomIntercept //annotation is the annotation you add to the method
        ): Any? {
            //Insert code before the method
            val value = joinPoint.proceed()
            //Insert code after the method
            return value
        }
    }
    
  • Replace the aspect
  • @AndroidAopReplaceClass("android.util.Log")
    object ReplaceLog {
        @AndroidAopReplaceMethod("int e(java.lang.String,java.lang.String)")
        @JvmStatic
        fun e(tag: String, msg: String): Int {
            //Insert code before the method
            val log = Log.e(tag, "ReplaceLog-$msg")
            //Insert code after the method
            return log
        }
    }
    
  • AspectJ's @AfterReturning and @AfterThrowing
  • We will match the aspect Let's take an example
    @AndroidAopMatchClassMethod(
        targetClassName = "com.flyjingfish.test_lib.TestMatch",
        methodName = ["test2"],
        type = MatchType.SELF
    )
    class MatchTestMatchMethod : MatchClassMethod {
        override fun invoke(joinPoint: ProceedJoinPoint, anno: TryCatch): Any? {
            return try {
                val value = joinPoint.proceed()
                // Here is @AfterReturning
                value
            } catch (e: Throwable) {
                // Here is @AfterThrowing
                throw RuntimeException(e)
            }
        }
    }
    

    6. What is the life cycle of the aspect processing class of the matching aspect and the annotation aspect?

    The aspect processing class is bound to the corresponding method of the class, which can be divided into two cases

    • a. If the pointcut method is not static
    • The aspect processing class will be recycled as the object where the method is located is recycled, but this is not timely; the recycling time is when any other aspect is processed.
    • And each object's pointcut method corresponds to an object of the aspect processing class, that is, there are as many objects as the class where the pointcut method is located creates.
    • b. If the pointcut method is static
    • Because the aspect method is static, the aspect processing class will always exist once it is created.
    • And a class method only corresponds to one aspect processing class

    No matter which type a or b is, the aspect processing class object will only be created when the method is executed.

    In short, the object of the aspect processing class is bound to the class or the object of the class, and its life cycle is slightly longer than the object of the class of the pointcut non-static method.

    This is different from Aspectj, because we often want to set some member variables in the aspect processing class to facilitate the use of the next aspect processing; if you want to do this in Aspectj, you need to save the "member variable" as a "static variable", and you also need to distinguish what object executes the pointcut method. You need to write a lot of code. AndroidAOP just optimizes and solves this problem.

    7. Compilation error or file usage on Windows computer

    • Try upgrading Gradle to 8.7 or above to see if it can be solved

    image

    • Then make sure that this library is the latest version, and then make sure that id 'android.aop' is in the last line of build.gradle of the app module

    image

    • Otherwise, please try the following steps (⚠️⚠️⚠️Please note that the following is only for Windows computers, and Mac computers should not have this problem)
    Click here to expand and view details
  • First, make sure that running ./gradlew --stop directly can succeed. If it fails, please check it online and then proceed to the following steps
  • image
  • Click on the run configuration
  • image
  • Add the Run External tool task type based on the original one
  • image
  • Configure as follows
  • image > Parameters:
    > Program: ```The absolute path of the project\gradlew.bat```
    > Arguments: ```./gradlew --stop```
    > Working directory: ```The absolute path of the project\```
  • Adjust the order to the top
  • image
  • Click OK to complete
  • image
  • Run the project directly. If the following situation occurs, it means that the configuration is successful
  • image
  • In addition, some netizens mentioned that changing ksp to kapt can also solve the problem
  • Click here to expand and view details The jar package you added contains the following files, please delete them and import the jar package locally instead
    show
    Operation steps
  • Open the directory where the jar package is locatedcd /Users/a111/Downloads/ida-android-new/app/libs
  • Unzip the jar package jar -xvf bcprov-jdk15on-1.69.jar
  • show
  • After unzipping
  • show
  • Open META-INF and delete the following files
  • show
  • Packaging, you can use it laterjar -cfm0 bcprov-jdk15on-1.69.jar META-INF/MANIFEST.MF org
  • show

    9. Why do I still feel that the package compilation is slow even though I have enabled androidAop.debugMode = true?

    The main reason for this is that you may have used some Router libraries or other plugins that change the packaging method. You can refer to here to transform your project click here, here is how to remove the plugin part of these libraries and use AndroidAOP to complete its plugin work, so you can delete these plugins to speed up packaging

    10. How to match variable parameters?

    vararg str : String in Kotlin is equivalent to String... in Java. In this matching, no matter what kind of code is represented by String[] (String is used as an example here, and other types are the same)

    11. After adding this library, it prompts that the file cannot be found when installing the app

    Check whether the configuration in your build.gradle contains Chinese. If there is Chinese, please try to change it to English and install it again

    12. Will calling the original method in the method annotated with @AndroidAopReplaceMethod cause recursion?

    • If it is a direct call, it will not cause recursion, and the framework has already handled it

    • If it is an indirect call, it will cause recursion, such as calling methods of other classes that contain the original method. The framework does not handle this. If you need to do this, you can combine exclude To use Homepage access, step 4 is introduced, use exclude to exclude the indirect call class

    13. What should I do if I don’t want to introduce the built-in annotation aspect?

    Please upgrade to version 2.1.5 or later, and check the access step 3

    14. Different modules of componentized projects use products such as aar for compilation. How to speed up the packaging speed?

    • The answer is still to use debugMode. This homepage accesses step 5 has been explained. For this situation, you should configure it as follows
    //👇This item is undoubtedly, it must be turned on! !
    androidAop.debugMode=true
    //👇This item needs to be turned off when you release the aar package. You can't turn it on again, because the release of aar is actually the release of the release package, don't you think?
    androidAop.debugMode.variantOnlyDebug=false
    
    • As for whether to use reflection, it depends on the person. It depends on your choice
    //👇Turn it on to use reflection
    androidAop.reflectInvokeMethod=true
    //👇This item is similar to androidAop.debugMode.variantOnlyDebug. If you use reflection in the release package, turn this item off! !
    androidAop.reflectInvokeMethod.variantOnlyDebug=false
    

    In summary, releasing aar is actually the same as releasing apk, and the understanding of the above configurations is actually the same

    Some people may still have questions, how should they be used in the final packaging?

    • In fact, it is okay to continue using debugMode, and the configuration is basically the same as above.
    • If you do not use debugMode, the aar packages of your different modules have actually been processed by AOP according to the above steps. You do not need to do it again when packaging. You can remove it under the app module, for example:
    androidAopConfig {
        //👇 Exclude the aar packages that have been processed by AOP, and you can still read the aspect configuration of these packages
        exclude 'aar package name 1', 'aar package name 2'
        //❗️❗️❗️It is worth mentioning that when you publish aar, do not configure the package name of the aar you want to publish here, otherwise the aar will not be processed by AOP
    }