安卓的日志类(android.util.Log)只提供最基本的日志输出功能,并无提供日志过滤、文件记录等常用功能,所以很多库和应用都自行封装了自己的日志类。比如Volley库中的com.android.volley.VolleyLog类就封装了系统日志类并提供字符串格式化参数的功能,另外一些库一般提供了设置公共Tag或者日志输出Level的功能。
如果项目里面引用了多个库,每个库都使用了自己的日志类,那么控制日志输出就比较麻烦,一般有以下手段:
- 在应用初始化时调用各个日志类的设置Api设定到统一的环境
- 在release前,使用Proguard删除所有日志输出语句
- 直接修改开源库代码,将所有日志类的内容改为自己应用的日志类的封装
经过实践可以知道,无论采用哪种方法均不完美,最好的方案是可以像j2ee开发那样使用slf4j公共日志接口将不同的日志库输出到一个统一的后端(比如log4j和logback),并通过该后端提供日志过滤和文件记录功能。slf4j是通过直接替换日志类的方式实现的(比如使用log4j-over-slf4j.jar直接替换log4j.jar),我们可以在android上使用aspectj在编译期更改日志类的字节码达到相似目的,好处是不需要手动更改开源库的源代码,方便保持更新。
下面以在ADT环境下使用android-maven-plugin和aspectj-maven-plugin修改VolleyLog为例进行说明。
统一的后端:https://github.com/allenz8512/zlog,笔者开发的类似log4j的日志库,提供日志过滤配置、自动使用类名作为Tag和日志文件输出功能。
pom.xml片段:
<build> <finalName>${project.artifactId}</finalName> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>aspectj-maven-plugin</artifactId> <version>1.7</version> <configuration> <complianceLevel>1.6</complianceLevel><!-- 编译版本为1.6,如果使用aspectj注解必须配置 --> <source>1.6</source> <target>1.6</target> <weaveDependencies><!-- 织入已经打包成jar的类,指定依赖包的坐标 --> <weaveDependency> <groupId>com.android</groupId> <artifactId>volley</artifactId> </weaveDependency> </weaveDependencies> </configuration> <executions> <execution> <goals> <goal>compile</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>com.jayway.maven.plugins.android.generation2</groupId> <artifactId>android-maven-plugin</artifactId> </plugin> <plugin> <groupId>org.eclipse.m2e</groupId> <artifactId>lifecycle-mapping</artifactId> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>me.allenz</groupId> <artifactId>zlog</artifactId> <version>0.4.0</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.8.2</version> </dependency> <dependency> <groupId>com.android</groupId> <artifactId>volley</artifactId> <version>1.0.0</version> <!-- 必须将scope配置为provided,避免android-maven-plugin重复将jar包内的类转为dex导致构建失败 --> <!-- 因为上面织入时已经将jar下所有的类添加过了 --> <scope>provided</scope> </dependency> </dependencies>
Aspectj代码:
@Aspect public class OtherLoggerAspect { @Pointcut("execution(public void com.android.volley.VolleyLog.*(..))") public void pointcut() { } @Around("pointcut()")//使用Around Advise但不调用原方法,等同于覆盖 public void weaveJointPoint(final ProceedingJoinPoint joinPoint) { final String method = joinPoint.getSignature().getName(); final Object[] args = joinPoint.getArgs(); final String caller = Utils.getCallerClassName( VolleyLog.class.getName(), 2);//通过调用堆栈获取VolleyLog调用者的类名 final Logger logger = LoggerFactory.getLogger(caller);//获取该类的Logger if (method.equals("d")) {//覆盖VolleyLog.d(String,Object...)输出,重定向到zlog final String message = (String) args[0]; final Object[] messageArgs = (Object[]) args[1]; if (messageArgs == null || messageArgs.length == 0) { logger.debug(message); } else { logger.debug(message, messageArgs); } } } }
测试代码:
VolleyLog.d("Hello World!");//调用类为HelloAndroidActivity VolleyLog.d("Number is %d", 123);
执行以下maven命令打包编译apk并安装运行:
mvn package android:deploy android:run
logcat输出为:
10-09 11:19:07.320: D/HelloAndroidActivity(1524): Hello World! 10-09 11:19:07.330: D/HelloAndroidActivity(1524): Number is 123
默认的VolleyLog的Tag应该为“Volley”,可以看到已经变成调用类的名称,并且可以通过配置文件控制是否输出
相关推荐
Android-Jet-AOP便是一个专为Android平台设计的AOP框架,它借助注解和AspectJ技术,使得在Android应用中实现AOP变得简单易行。 ### 一、面向切面编程(AOP) AOP的核心理念是将程序中的关注点分离,关注点可以理解...
一个简单的AOP应用是在Android中实现日志记录。首先,创建一个自定义注解`@LogMethod`: ```java @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface LogMethod { String value...
通过这样的封装,开发者可以更专注于业务逻辑,而无需关心数据存取的细节,同时还能享受到AOP带来的便利,如统一的日志、异常处理和性能监控。这种结合 Realm 和 AOP 的方式,是提升 Android 应用开发效率和质量的...
本文将详细介绍一个基于AOP(面向切面编程)思想封装的Android运行时权限库——"Android-AOP方式封装的6.0运行时申请权限的库"。 首先,我们来理解一下AOP的概念。AOP是一种编程范式,它允许程序员定义“横切关注点...
本示例"AopDemo"很可能是通过一个简单的应用来演示如何在Android项目中引入和使用AOP。 1. **概念理解**: - **切面(Aspect)**:切面是关注点的一个模块化,它封装了横切关注点,如日志、异常处理等。 - **连接...
在Spring框架中,AOP用于处理横切关注点,如日志、事务管理等,使得核心业务逻辑与这些通用功能得以解耦。在AOP的实现方式中,AspectJ是最强大且功能丰富的,尽管它的学习曲线相对陡峭,但其强大的编译时织入和运行...
面向切面编程(AOP,Aspect Oriented Programming)是一种编程范式,主要目的是解决软件系统..."AOPDemo.rar"项目可能包含了如何在Android中实现和使用AOP的实例,对于理解这一技术及其在实际项目中的应用非常有帮助。
通过AOP,开发者可以定义“切面”来封装关注点,如日志、事务管理等,从而将这些通用功能与业务逻辑分离,保持代码整洁。 6. **事件驱动编程** Spring框架支持事件驱动编程模型,通过`ApplicationEvent`和`...
1. **切面(Aspect)**:切面是AOP的核心,它封装了特定的关注点,如日志、事务等。一个切面通常包含一个或多个通知(Advices)和一个或多个切入点(Pointcuts)。 2. **通知(Advice)**:通知是在特定连接点...
面向切面编程(AOP,Aspect Oriented Programming)在Android开发中主要用来解决代码的横切关注点,例如日志记录、性能监控、权限检查等,这些功能往往贯穿于多个类或方法之中,使得代码耦合度增加。AOP允许我们将...
Spring Android 1.0.0.RC1还包含了Spring Android Core,它提供了一些基础工具类和实用程序,如日期/时间转换器,还有对Android系统的Log类的扩展,使得日志输出更加方便。这些工具类可以帮助开发者更好地处理常见的...
通过学习和研究"AopSample",开发者不仅可以了解AOP在Android中的应用,还能掌握如何使用注解处理器和AspectJ来提升应用的质量和效率。同时,这也有助于理解如何设计和实现自己的AOP库,以解决特定场景下的问题。
2. **插件化加载**:Android应用可以利用类加载器(ClassLoader)的特性,动态加载实现指定接口的类。这样,新的功能或更新可以在不修改主应用的情况下,通过插件的形式添加进来。 3. **动态配置**:在Android中,...
5. **AOP(面向切面编程)**:动态代理可以作为实现AOP的一种方式,通过拦截关键方法的调用来实现横切关注点,如日志记录、性能监控等。 在`DynamicProxy-master`这个项目中,可能包含了实现上述功能的示例代码,...
在软件工程中,设计模式是一种解决常见问题的模板或最佳实践,它被广泛应用于各种编程语言,包括Android开发。代理模式是设计模式的一种,它的主要目的是在不改变原有对象的基础上,为一个对象提供额外的功能或者...
这个"Android AspectJ的demo"很可能是为了演示如何在Android应用中使用AspectJ实现AOP。 AOP的核心概念是切面(Aspect),它封装了横切关注点,这些关注点是在多个对象中分散的、与核心业务逻辑不直接相关的代码,...
在Android开发中,AspectJ的引入可以帮助我们解决一些跨组件的问题,例如,我们可以在不修改业务代码的情况下,统一地添加日志记录或异常处理。这使得代码更加整洁,降低了耦合度。 【标签】"aop"代表了面向切面...
Android应用通常通过HTTP或者HTTPS协议与服务器进行通信,可能使用像Retrofit或OkHttp这样的网络库来封装请求。 **Android应用与服务器交互**: 1. **API接口设计**:服务器端会定义一组RESTful API接口,每个接口...
Spring是Java领域广泛使用的轻量级框架,主要用于后端服务的开发,而Activity是Android应用中的核心组件,负责用户界面的管理。这里我们将探讨如何将Spring的强大功能引入到Android应用的Activity中,提升应用的可...
在Android移动开发中,AspectJ的应用可以帮助开发者更有效地管理横切关注点,例如日志记录、性能监控、权限检查等,这些通常会分散在代码各处,导致耦合度增加。 AspectJ主要包含以下几个核心概念: 1. **切面...