内容简介:今天老大跑过来说项目埋点了解一下!丢下了这句话之后,就没有之后了!剩下我一个人在风中凌乱!!!其实这个需求老大在很久之前就说要开发了,后来就搁置了!但是今天看老大的态度,应该排到日程了!所以没办法只有硬着头皮磕了!免得过一阵子加班到很晚,所以趁着时间宽松,先能把踩的坑踩踩!!!分享给大家,也让大家能避免一些不必要的时间浪费。更好的过个周末,陪陪女盆友!!!出于可读性考虑,我准备把这个系列分成几部分去写,因为这样才能充分利用你的碎片时间,能让你在碎片化中学习一个知识点。
今天老大跑过来说项目埋点了解一下!丢下了这句话之后,就没有之后了!剩下我一个人在风中凌乱!!!
其实这个需求老大在很久之前就说要开发了,后来就搁置了!但是今天看老大的态度,应该排到日程了!所以没办法只有硬着头皮磕了!免得过一阵子加班到很晚,所以趁着时间宽松,先能把踩的坑踩踩!!!分享给大家,也让大家能避免一些不必要的时间浪费。更好的过个周末,陪陪女盆友!!!
本系列文章知识点:
- 项目中埋点的需求分析
- AOP思想的应用
- AspectJ怎么集成到项目中(难点1)
- AspectJ中的一些知识点说明(难点2)
- AOP在项目中的应用等...
出于可读性考虑,我准备把这个系列分成几部分去写,因为这样才能充分利用你的碎片时间,能让你在碎片化中学习一个知识点。
第一篇文章主要讲解关于AOP中埋点的概念和相应的集成; 第二篇文章主要讲解关于AspectJ中用到的一些知识点; 第三篇文章主要讲解关于AspectJ在项目的其他一些应用。
1.项目中埋点的需求分析
1.1 首先先给菜鸟们科普一下什么叫做埋点
所谓埋点 ,百度百科是这么说的!其实说简单点,就是我在APP中都做了什么事情,让你们运营的知道,其实想想挺可怕的,这我要是出去浪,媳妇就知道了!!!明白了吧,你的一切行为都在掌控之中,用来生成人物画像什么的。。。一堆乱七八糟的!那么我们 程序员 要做什么呢?像什么统计时长了,点击了什么按钮了,常去什么页面了等...好吧!剩下的就看你们运营需要什么了,就科普到这里吧!
1.2 常见的埋点方案
我整理了相应内容,我发现其实埋点可以分为:
- 服务器层面的:主要是通过APP端的请求进行分析
- APP层面的:通过埋点进行相应的分析
作为一个移动端的猿,理所应当的从APP层面去分析相应的实现,现在在APP端的实现基本上分为以下几种
- 代码埋点 :在需要的地方添加相应的代码,可谓是那里需要写哪里!!!但是缺点同时体现出来了,那就是代码量会成吨的输出,如果有一天你们项目经理跑过来改了某一个需求,代码更是成吨的增长,那个时候你会像"平安的程序员一样"奋起反抗的!!!
- 自动化埋点 :通过一些特殊手段(相应的切面编程AOP思想,这个也是本文要说的重点!!!),对相应的方法进行统计!
- 第三方实现 现在很多第三方都有,百度、友盟等...只要按照说明文档就可以了!
其实从程序员角度分析的话,无非就是代码写得多少的事情吗?往往许多内容都这能用这个东西衡量的,所以没有实现不了的,大不了我就多写点代码呗!但是为了让你成为一名有逼格的程序猿,总是要学点什么的!!!
2. AOP思想的应用
百度百科是这么形容AOP的!面向切面编程。也就是说在某个切面,你可以做一些相应的操作!这么和你比喻吧,当你触发一个点击事件的时候,点击的一瞬间算是一个切面,你可以在这个切面的前后加上一些相应的内容,也就是相应的切面编程了!
能解决什么问题呢?往往很多人都会这么问?有这样一个需求,一些APP只有在登陆的情况下才能做一些事情,往往有很多按钮都需要判断登陆的情况,如果你每一个按钮都写一个判断方法,那代码就很多了,如果产品跑过来说在添加一个VIP的功能你怎么办?所有的地方都要改?我擦,毁灭性的啊!这个时候就可以使用AOP这种编程思想了!再点击之前做一些相应的处理,那么即便是你在改的话,也只需要改一个地方!
上面说了那么多都是废话,只是了解一下就可以了!我看Android中使用AOP基本上都是使用注解和一个叫 AspectJ 这么个东西,都说是非侵入式埋点,这个非侵入式是一个很好的东西,也就是不用更改之前代码的逻辑就可以实现相应的需求,所以我觉得埋点使用这个东西就非常好了!
3. AspectJ怎么集成到项目中(难点1)
关于AspectJ这个东西的集成,要用到一些gradle中的知识,其实对这里的知识我也不是很了解,也不再我们今天要讲的内容中,所以这里直接跳过了,感兴趣的同学可以自行百度,这个插一句(学习要有目的性,如果你要学某一个东西的话,其它的东西真的可以先放一放!!!)我就讲讲怎么集成就好了!!!
3.1 添加相应的依赖
首先说明一个事情,因为代码是非侵入性的,所以建议你把AspectJ集成在一个专门的Module中,这样在不改变原有的内容就能实现相应的方案。why?因为我就是这么做的。。。
3.1.1 首先在项目的build.gradle中添加相应的依赖
classpath 'org.aspectj:aspectjtools:1.8.9'
//虽然都说句要加,但是我没加程序还是正常运行的!
classpath 'org.aspectj:aspectjweaver:1.8.9'
复制代码
整段代码是这样滴!
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.4'
classpath 'org.aspectj:aspectjtools:1.8.9'
//我发现这个东西不加也是可以正常运行的
// classpath 'org.aspectj:aspectjweaver:1.8.9'
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
复制代码
3.1.2 其次在项目中添加依赖和一些必要的配置
在项目的build.gradle中添加相应的依赖 implementation 'org.aspectj:aspectjrt:1.8.9'
然后在 根路径 添加相应的配置
import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main
final def log = project.logger
android.applicationVariants.all{ variant ->
if (!variant.buildType.isDebuggable()) {
log.debug("Skipping non-debuggable build type '${variant.buildType.name}'.")
return
}
JavaCompile javaCompile = variant.javaCompiler
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)
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
}
}
}
}
复制代码
别问我为什么?我怎得不理解这段代码,反正我知道这段代码是必须的。
整段代码是这样滴!
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.jinlong.aspectjdemo"
minSdkVersion 14
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:28.0.0-rc01'
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation project(':aspectmodule')
implementation 'org.aspectj:aspectjrt:1.8.9'
}
import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main
final def log = project.logger
android.applicationVariants.all{ variant ->
if (!variant.buildType.isDebuggable()) {
log.debug("Skipping non-debuggable build type '${variant.buildType.name}'.")
return
}
JavaCompile javaCompile = variant.javaCompiler
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)
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
}
}
}
}
复制代码
在这里说明以下,如果你要是在Module中使用,那么在app的build.gradle中也要进行相应的配置!切记!!! 重要的事情说 " 三遍 "!!!这里直接贴一下相应Module中的配置!
apply plugin: 'com.android.library'
android {
compileSdkVersion 28
defaultConfig {
minSdkVersion 14
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0-rc01'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation 'org.aspectj:aspectjrt:1.8.9'
}
import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main
final def log = project.logger
android.libraryVariants.all{ variant ->
if (!variant.buildType.isDebuggable()) {
log.debug("Skipping non-debuggable build type '${variant.buildType.name}'.")
return
}
JavaCompile javaCompile = variant.javaCompiler
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)
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
}
}
}
}
复制代码
注意这里主项目和类库中是不一样的!!!以上可以保证你编译通过了,但是这才是开始的配置!!!
3.1.3 配置相应的类
这里先说以下相应的配置,具体为什么先不去说!!!下篇文章我会尽我所能给你讲解清楚的!!!相信我
@Aspect
public class TraceAspect {
private static final String TAG = "hjl";
@Before("execution(* android.app.Activity.on*(..))")
public void onActivityMethodBefore(JoinPoint joinPoint) throws Throwable {
String key = joinPoint.getSignature().toString();
Log.e(TAG, "onActivityMethodBefore: 切面的点执行了!" + key);
}
}
复制代码
首先说一下这段注意事项:
- 顶部的注解@Aspect是不能少的,如果没有它一切都是扯淡!!!
- @Before("execution(* android.app.Activity.on*(..))") 这段代码才是核心,先简单说一下,这段代码主要表述的内容是,检测所有activity中以on开头的方法,比如onCreate()然后前面的@Before说明的是在这个方法执行前执行里面的!这样你就可以运行程序,直接看LOG就可以了,
简单说明一下原理,通过上面这个类,主要是在方法中的最开始添加一个相应的方法,也就是把你写的这段代码以一个方法的形式添加到某个位置!这样就实现了通过切面进行相应的处理方案了!!!
想看源码吗?想看链接吗? 点这里
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Algorithms for Image Processing and Computer Vision
Parker, J. R. / 2010-12 / 687.00元
A cookbook of algorithms for common image processing applications Thanks to advances in computer hardware and software, algorithms have been developed that support sophisticated image processing with......一起来看看 《Algorithms for Image Processing and Computer Vision》 这本书的介绍吧!