折腾了几天,网上的一些文章会有点old,大部分是不能用的,比如hujiang,及其issue中的维护版本也是不行,编译会报错。
已验证可行的流程如下
// 首先在根工程下的
dependencies {
classpath 'org.aspectj:aspectjtools:1.9.7'
classpath 'org.aspectj:aspectjweaver:1.9.7'
...
}
// 在app的build.gradle
android {
...
}
dependencies {
implementation( 'org.aspectj:aspectjrt:1.9.7' )
...
}
AOP生效,与android同级
//使得aop生效
import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main
// 获取log打印工具和构建配置
final def log = project.logger
final def variants = project.android.applicationVariants
variants.all { variant ->
if (!variant.buildType.isDebuggable()) {
// 判断是否debug,如果打release把return去掉就可以
log.debug("Skipping non-debuggable build type '${variant.buildType.name}'.")
// return;
}
// 使aspectj配置生效
JavaCompile javaCompile = variant.javaCompile
javaCompile.doLast {
String[] args = ["-showWeaveInfo",
"-1.8",
"-inpath", javaCompile.destinationDir.toString(),
"-aspectpath", javaCompile.classpath.asPath,
"-d", javaCompile.destinationDir.toString(),
"-classpath", javaCompile.classpath.asPath,
"-bootclasspath", project.android.bootClasspath.join(File.pathSeparator)]
log.debug "ajc args: " + Arrays.toString(args)
MessageHandler handler = new MessageHandler(true);
new Main().run(args, handler);
//在编译时打印信息如警告、error等等
for (IMessage message : handler.getMessages(null, true)) {
switch (message.getKind()) {
case IMessage.ABORT:
case IMessage.ERROR:
case IMessage.FAIL:
log.error message.message, message.thrown
break;
case IMessage.WARNING:
log.warn message.message, message.thrown
break;
case IMessage.INFO:
log.info message.message, message.thrown
break;
case IMessage.DEBUG:
log.debug message.message, message.thrown
break;
}
}
}
}
测试验证
package com.ilifesmart.mslict.aop;
import android.util.Log;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
/* *
* 用于校验隐私合规,查询某些项被调用时的调用栈,确定何处引发的调用
* */
@Aspect
public class AspectJTest {
public static final String TAG = "AspectTest";
@Around("call(* android.provider.Settings.Secure.getString(.., java.lang.String))")
public Object getSecureString(ProceedingJoinPoint joinPoint) throws Throwable {
String method = joinPoint.getSignature().toString();
Log.d("4B", "getSystemString: method " + method + " throwable " + Log.getStackTraceString(new Throwable()));
Object[] objs = joinPoint.getArgs();
String[] argNames = ((MethodSignature) joinPoint.getSignature()).getParameterNames();
Log.d("4B", "getSysString: args[1] " + (String) objs[1]);
Object object = joinPoint.proceed();
Log.d("4B", "getSysString: result " + ((String)object) );
return object;
}
@Around("call(* android.provider.Settings.Setting.getString(.., java.lang.String))")
public Object getSystemString(ProceedingJoinPoint joinPoint) throws Throwable {
String method = joinPoint.getSignature().toString();
Log.d("4B", "getSystemString: method " + method + " throwable " + Log.getStackTraceString(new Throwable()));
Object[] objs = joinPoint.getArgs();
String[] argNames = ((MethodSignature) joinPoint.getSignature()).getParameterNames();
// 获取函数调用参数 android_id
Log.d("4B", "getSysString: args[1] " + (String) objs[1]);
Object object = joinPoint.proceed();
// 获取函数调用返回值
Log.d("4B", "getSysString: result " + ((String)object) );
return object;
}
}