`

使用AOP统一封装Android应用内的日志类

 
阅读更多

安卓的日志类(android.util.Log)只提供最基本的日志输出功能,并无提供日志过滤、文件记录等常用功能,所以很多库和应用都自行封装了自己的日志类。比如Volley库中的com.android.volley.VolleyLog类就封装了系统日志类并提供字符串格式化参数的功能,另外一些库一般提供了设置公共Tag或者日志输出Level的功能。

 

如果项目里面引用了多个库,每个库都使用了自己的日志类,那么控制日志输出就比较麻烦,一般有以下手段:

  1. 在应用初始化时调用各个日志类的设置Api设定到统一的环境
  2. 在release前,使用Proguard删除所有日志输出语句
  3. 直接修改开源库代码,将所有日志类的内容改为自己应用的日志类的封装

经过实践可以知道,无论采用哪种方法均不完美,最好的方案是可以像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”,可以看到已经变成调用类的名称,并且可以通过配置文件控制是否输出

分享到:
评论
1 楼 xzf_iflyTek 2015-03-04  
你好,请问有这块具体的工程代码吗。我正在为这样一个需求搞的头大,望赐教啊。谢谢

相关推荐

    Android-Jet-AOP一个AndroidAOP框架

    Android-Jet-AOP便是一个专为Android平台设计的AOP框架,它借助注解和AspectJ技术,使得在Android应用中实现AOP变得简单易行。 ### 一、面向切面编程(AOP) AOP的核心理念是将程序中的关注点分离,关注点可以理解...

    AOP在Android中的使用

    一个简单的AOP应用是在Android中实现日志记录。首先,创建一个自定义注解`@LogMethod`: ```java @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface LogMethod { String value...

    Realm + aspectj aop数据库封装

    通过这样的封装,开发者可以更专注于业务逻辑,而无需关心数据存取的细节,同时还能享受到AOP带来的便利,如统一的日志、异常处理和性能监控。这种结合 Realm 和 AOP 的方式,是提升 Android 应用开发效率和质量的...

    Android-AOP方式封装的6.0运行时申请权限的库

    本文将详细介绍一个基于AOP(面向切面编程)思想封装的Android运行时权限库——"Android-AOP方式封装的6.0运行时申请权限的库"。 首先,我们来理解一下AOP的概念。AOP是一种编程范式,它允许程序员定义“横切关注点...

    aop 面向切面编程 demo

    本示例"AopDemo"很可能是通过一个简单的应用来演示如何在Android项目中引入和使用AOP。 1. **概念理解**: - **切面(Aspect)**:切面是关注点的一个模块化,它封装了横切关注点,如日志、异常处理等。 - **连接...

    AOP的AspectJ实现方案来做语言切换

    在Spring框架中,AOP用于处理横切关注点,如日志、事务管理等,使得核心业务逻辑与这些通用功能得以解耦。在AOP的实现方式中,AspectJ是最强大且功能丰富的,尽管它的学习曲线相对陡峭,但其强大的编译时织入和运行...

    AOPDemo.rar

    面向切面编程(AOP,Aspect Oriented Programming)是一种编程范式,主要目的是解决软件系统..."AOPDemo.rar"项目可能包含了如何在Android中实现和使用AOP的实例,对于理解这一技术及其在实际项目中的应用非常有帮助。

    android的spring框架

    通过AOP,开发者可以定义“切面”来封装关注点,如日志、事务管理等,从而将这些通用功能与业务逻辑分离,保持代码整洁。 6. **事件驱动编程** Spring框架支持事件驱动编程模型,通过`ApplicationEvent`和`...

    AOP编程之AspectJ实战

    1. **切面(Aspect)**:切面是AOP的核心,它封装了特定的关注点,如日志、事务等。一个切面通常包含一个或多个通知(Advices)和一个或多个切入点(Pointcuts)。 2. **通知(Advice)**:通知是在特定连接点...

    Android中AOP(面向切向编程)的深入讲解

    面向切面编程(AOP,Aspect Oriented Programming)在Android开发中主要用来解决代码的横切关注点,例如日志记录、性能监控、权限检查等,这些功能往往贯穿于多个类或方法之中,使得代码耦合度增加。AOP允许我们将...

    spring-android-1.0.0.RC1.zip

    Spring Android 1.0.0.RC1还包含了Spring Android Core,它提供了一些基础工具类和实用程序,如日期/时间转换器,还有对Android系统的Log类的扩展,使得日志输出更加方便。这些工具类可以帮助开发者更好地处理常见的...

    AopSample:面向切片AOP示例

    通过学习和研究"AopSample",开发者不仅可以了解AOP在Android中的应用,还能掌握如何使用注解处理器和AspectJ来提升应用的质量和效率。同时,这也有助于理解如何设计和实现自己的AOP库,以解决特定场景下的问题。

    spi,Android组件化的SPI。.zip

    2. **插件化加载**:Android应用可以利用类加载器(ClassLoader)的特性,动态加载实现指定接口的类。这样,新的功能或更新可以在不修改主应用的情况下,通过插件的形式添加进来。 3. **动态配置**:在Android中,...

    Android-Android中动态代理的使用

    5. **AOP(面向切面编程)**:动态代理可以作为实现AOP的一种方式,通过拦截关键方法的调用来实现横切关注点,如日志记录、性能监控等。 在`DynamicProxy-master`这个项目中,可能包含了实现上述功能的示例代码,...

    Android设计模式之代理模式(Proxy Pattern)

    在软件工程中,设计模式是一种解决常见问题的模板或最佳实践,它被广泛应用于各种编程语言,包括Android开发。代理模式是设计模式的一种,它的主要目的是在不改变原有对象的基础上,为一个对象提供额外的功能或者...

    Andorid AspectJ 的demo

    这个"Android AspectJ的demo"很可能是为了演示如何在Android应用中使用AspectJ实现AOP。 AOP的核心概念是切面(Aspect),它封装了横切关注点,这些关注点是在多个对象中分散的、与核心业务逻辑不直接相关的代码,...

    Aspect学习实例.zip

    在Android开发中,AspectJ的引入可以帮助我们解决一些跨组件的问题,例如,我们可以在不修改业务代码的情况下,统一地添加日志记录或异常处理。这使得代码更加整洁,降低了耦合度。 【标签】"aop"代表了面向切面...

    ssm服务二次运行 安卓课设代码

    Android应用通常通过HTTP或者HTTPS协议与服务器进行通信,可能使用像Retrofit或OkHttp这样的网络库来封装请求。 **Android应用与服务器交互**: 1. **API接口设计**:服务器端会定义一组RESTful API接口,每个接口...

    spring-activity

    Spring是Java领域广泛使用的轻量级框架,主要用于后端服务的开发,而Activity是Android应用中的核心组件,负责用户界面的管理。这里我们将探讨如何将Spring的强大功能引入到Android应用的Activity中,提升应用的可...

    面向切面编程--AspectJDemo

    在Android移动开发中,AspectJ的应用可以帮助开发者更有效地管理横切关注点,例如日志记录、性能监控、权限检查等,这些通常会分散在代码各处,导致耦合度增加。 AspectJ主要包含以下几个核心概念: 1. **切面...

Global site tag (gtag.js) - Google Analytics