Skip to content

Commit 7058457

Browse files
committed
Release 3.0.0
1 parent 386f3f2 commit 7058457

13 files changed

+513
-174
lines changed

aop/ext.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
project.ext {
2-
pluginVersion = '2.2.4'
2+
pluginVersion = '3.0.0'
33
Properties properties = new Properties()
44
if (project.file('local.properties').exists()) {
55
properties.load(project.file('local.properties').newDataInputStream())
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package com.sensorsdata.analytics.android.plugin
2+
3+
class ClassNameAnalytics {
4+
5+
public String className
6+
7+
boolean isShouldModify = false
8+
9+
boolean isSensorsDataAPI = false
10+
11+
boolean isSensorsDataUtils = false
12+
13+
boolean isSALog = false
14+
15+
def methodCells = new ArrayList<SensorsAnalyticsMethodCell>()
16+
17+
ClassNameAnalytics (String className) {
18+
this.className = className
19+
isSensorsDataAPI = (className == 'com.sensorsdata.analytics.android.sdk.SensorsDataAPI')
20+
isSensorsDataUtils = (className == 'com.sensorsdata.analytics.android.sdk.util.SensorsDataUtils')
21+
isSALog = (className == 'com.sensorsdata.analytics.android.sdk.SALog')
22+
}
23+
24+
boolean isSDKFile() {
25+
return isSALog || isSensorsDataAPI || isSensorsDataUtils
26+
}
27+
28+
boolean isViewPager() {
29+
return className == 'android.support.v4.view.ViewPager' || className == 'androidx.viewpager.widget.ViewPager'
30+
}
31+
32+
boolean isAndroidGenerated() {
33+
return className.contains('R$') ||
34+
className.contains('R2$') ||
35+
className.contains('R.class') ||
36+
className.contains('R2.class') ||
37+
className.contains('BuildConfig.class')
38+
}
39+
40+
}

aop/src/main/groovy/com/sensorsdata/analytics/android/plugin/Logger.groovy

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package com.sensorsdata.analytics.android.plugin
22

33
import java.lang.reflect.Array
44

5-
public class Logger {
5+
class Logger {
66
private static boolean debug = false
77
public static HashMap<Integer, String> accCodeMap = new HashMap<>()
88
public static HashMap<Integer, String> opCodeMap = new HashMap<>()
@@ -18,6 +18,14 @@ public class Logger {
1818
return debug
1919
}
2020

21+
def static error(Object msg) {
22+
try {
23+
println("\033[40;31m" + "[SensorsAnalytics]: ${msg}" + "\033[0m")
24+
} catch (Exception e) {
25+
e.printStackTrace()
26+
}
27+
}
28+
2129
/**
2230
* 打印日志
2331
*/

aop/src/main/groovy/com/sensorsdata/analytics/android/plugin/SensorsAnalyticsClassVisitor.groovy

Lines changed: 124 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.sensorsdata.analytics.android.plugin
22

33
import org.objectweb.asm.AnnotationVisitor
44
import org.objectweb.asm.ClassVisitor
5+
import org.objectweb.asm.FieldVisitor
56
import org.objectweb.asm.MethodVisitor
67
import org.objectweb.asm.Opcodes
78

@@ -12,14 +13,22 @@ class SensorsAnalyticsClassVisitor extends ClassVisitor implements Opcodes {
1213
private HashSet<String> visitedFragMethods = new HashSet<>()// 无需判空
1314
private ClassVisitor classVisitor
1415

16+
private SensorsAnalyticsTransformHelper transformHelper
17+
18+
private ClassNameAnalytics classNameAnalytics
19+
20+
private ArrayList<SensorsAnalyticsMethodCell> methodCells = new ArrayList<>()
21+
1522
@Override
1623
protected Object clone() throws CloneNotSupportedException {
1724
return super.clone()
1825
}
1926

20-
SensorsAnalyticsClassVisitor(final ClassVisitor classVisitor) {
27+
SensorsAnalyticsClassVisitor(final ClassVisitor classVisitor,ClassNameAnalytics classNameAnalytics,SensorsAnalyticsTransformHelper transformHelper) {
2128
super(Opcodes.ASM6, classVisitor)
2229
this.classVisitor = classVisitor
30+
this.classNameAnalytics = classNameAnalytics
31+
this.transformHelper = transformHelper
2332
}
2433

2534
private
@@ -85,10 +94,38 @@ class SensorsAnalyticsClassVisitor extends ClassVisitor implements Opcodes {
8594
}
8695
}
8796

97+
for (cell in methodCells) {
98+
transformHelper.sensorsAnalyticsHookConfig."${cell.agentName}"(classVisitor,cell)
99+
}
100+
88101
Logger.info("结束扫描类:${mClassName}\n")
89102
}
90103

91-
/**
104+
105+
@Override
106+
FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) {
107+
if (classNameAnalytics.isSensorsDataAPI) {
108+
if ('VERSION' == name) {
109+
String version = (String)value
110+
if (SensorsAnalyticsTransform.MIN_SDK_VERSION > version) {
111+
String errMessage = "你目前集成的神策埋点 SDK 版本号为 v${version},请升级到 v${SensorsAnalyticsTransform.MIN_SDK_VERSION} 及以上的版本。详情请参考:https://github.com/sensorsdata/sa-sdk-android"
112+
Logger.error(errMessage)
113+
throw new UnsupportedOperationException(errMessage)
114+
}
115+
} else if ('MIN_PLUGIN_VERSION' == name) {
116+
String minPluginVersion = (String)value
117+
if (minPluginVersion != "" && minPluginVersion != null) {
118+
if (SensorsAnalyticsTransform.VERSION < minPluginVersion) {
119+
String errMessage = "你目前集成的神策插件版本号为 v${SensorsAnalyticsTransform.VERSION},请升级到 v${minPluginVersion} 及以上的版本。详情请参考:https://github.com/sensorsdata/sa-sdk-android-plugin2"
120+
Logger.error(errMessage)
121+
throw new UnsupportedOperationException(errMessage)
122+
}
123+
}
124+
}
125+
}
126+
return super.visitField(access, name, descriptor, signature, value)
127+
}
128+
/**
92129
* 该方法是当扫描器扫描到类的方法时进行调用
93130
* @param access 表示方法的修饰符
94131
* @param name 表示方法名,在 ASM 中 “visitMethod” 方法会处理(构造方法、静态代码块、私有方法、受保护的方法、共有方法、native类型方法)。
@@ -100,11 +137,20 @@ class SensorsAnalyticsClassVisitor extends ClassVisitor implements Opcodes {
100137
*/
101138
@Override
102139
MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
140+
for (methodCell in classNameAnalytics.methodCells) {
141+
if (methodCell.name == name && methodCell.desc == desc) {
142+
methodCells.add(methodCell)
143+
return null
144+
}
145+
}
146+
103147
MethodVisitor methodVisitor = cv.visitMethod(access, name, desc, signature, exceptions)
104148

105149
methodVisitor = new SensorsAnalyticsDefaultMethodVisitor(methodVisitor, access, name, desc) {
106150
boolean isSensorsDataTrackViewOnClickAnnotation = false
107151
boolean isSensorsDataIgnoreTrackOnClick = false
152+
String eventName = null
153+
String eventProperties = null
108154
boolean isHasInstrumented = false
109155
boolean isHasTracked = false
110156

@@ -119,8 +165,12 @@ class SensorsAnalyticsClassVisitor extends ClassVisitor implements Opcodes {
119165
}
120166

121167
@Override
122-
protected void onMethodEnter() {
123-
super.onMethodEnter()
168+
protected void onMethodExit(int opcode) {
169+
if (classNameAnalytics.isSensorsDataAPI) {
170+
return
171+
}
172+
173+
super.onMethodExit(opcode)
124174

125175
if (isSensorsDataIgnoreTrackOnClick) {
126176
return
@@ -129,16 +179,46 @@ class SensorsAnalyticsClassVisitor extends ClassVisitor implements Opcodes {
129179
/**
130180
* 在 android.gradle 的 3.2.1 版本中,针对 view 的 setOnClickListener 方法 的 lambda 表达式做特殊处理。
131181
*/
132-
if (name.trim().startsWith('lambda$') && SensorsAnalyticsUtil.isPrivate(access) && SensorsAnalyticsUtil.isSynthetic(access)) {
133-
SensorsAnalyticsMethodCell sensorsAnalyticsMethodCell = SensorsAnalyticsHookConfig.sLambdaMethods.get(desc)
134-
if (sensorsAnalyticsMethodCell != null) {
135-
int paramStart = sensorsAnalyticsMethodCell.paramsStart
136-
if (SensorsAnalyticsUtil.isStatic(access)) {
137-
paramStart = paramStart - 1
182+
if (transformHelper.lambdaEnabled) {
183+
if (name.trim().startsWith('lambda$') && SensorsAnalyticsUtil.isPrivate(access) && SensorsAnalyticsUtil.isSynthetic(access)) {
184+
if (desc == '(Landroid/view/MenuItem;)Z' && SensorsAnalyticsUtil.isStatic(access)) {
185+
SensorsAnalyticsMethodCell sensorsAnalyticsMethodCell = SensorsAnalyticsHookConfig.sLambdaMethods.get(desc + '2')
186+
if (sensorsAnalyticsMethodCell != null) {
187+
visitMethodWithLoadedParams(methodVisitor, Opcodes.INVOKESTATIC, SensorsAnalyticsHookConfig.sSensorsAnalyticsAPI,
188+
sensorsAnalyticsMethodCell.agentName, sensorsAnalyticsMethodCell.agentDesc,
189+
sensorsAnalyticsMethodCell.paramsStart, sensorsAnalyticsMethodCell.paramsCount, sensorsAnalyticsMethodCell.opcodes)
190+
isHasTracked = true
191+
return
192+
}
193+
} else {
194+
SensorsAnalyticsMethodCell sensorsAnalyticsMethodCell = SensorsAnalyticsHookConfig.sLambdaMethods.get(desc)
195+
if (sensorsAnalyticsMethodCell != null) {
196+
int paramStart = sensorsAnalyticsMethodCell.paramsStart
197+
if (SensorsAnalyticsUtil.isStatic(access)) {
198+
paramStart = paramStart - 1
199+
}
200+
visitMethodWithLoadedParams(methodVisitor, Opcodes.INVOKESTATIC, SensorsAnalyticsHookConfig.sSensorsAnalyticsAPI,
201+
sensorsAnalyticsMethodCell.agentName, sensorsAnalyticsMethodCell.agentDesc,
202+
paramStart, sensorsAnalyticsMethodCell.paramsCount, sensorsAnalyticsMethodCell.opcodes)
203+
isHasTracked = true
204+
return
205+
}
138206
}
139-
visitMethodWithLoadedParams(methodVisitor, Opcodes.INVOKESTATIC, SensorsAnalyticsHookConfig.sSensorsAnalyticsAPI,
140-
sensorsAnalyticsMethodCell.agentName, sensorsAnalyticsMethodCell.agentDesc,
141-
paramStart, sensorsAnalyticsMethodCell.paramsCount, sensorsAnalyticsMethodCell.opcodes)
207+
}
208+
}
209+
210+
/**
211+
* Method 描述信息
212+
*/
213+
String nameDesc = name + desc
214+
215+
/**
216+
* 处理 ViewPager
217+
*/
218+
if (mClassName == 'android/support/v4/view/ViewPager' || mClassName == 'androidx/viewpager/widget/ViewPager') {
219+
if (nameDesc == 'dispatchOnPageSelected(I)V') {
220+
methodVisitor.visitVarInsn(ALOAD, 0)
221+
methodVisitor.visitMethodInsn(INVOKESTATIC, SensorsAnalyticsHookConfig.sSensorsAnalyticsAPI, "trackViewOnClick", "(Landroid/view/View;)V", false)
142222
isHasTracked = true
143223
return
144224
}
@@ -155,11 +235,6 @@ class SensorsAnalyticsClassVisitor extends ClassVisitor implements Opcodes {
155235
return
156236
}
157237

158-
/**
159-
* Method 描述信息
160-
*/
161-
String nameDesc = name + desc
162-
163238
/**
164239
* React Native
165240
*/
@@ -200,9 +275,14 @@ class SensorsAnalyticsClassVisitor extends ClassVisitor implements Opcodes {
200275
* 目前支持 onContextItemSelected(MenuItem item)、onOptionsItemSelected(MenuItem item)
201276
*/
202277
if (SensorsAnalyticsUtil.isTargetMenuMethodDesc(nameDesc)) {
203-
methodVisitor.visitVarInsn(ALOAD, 0)
204-
methodVisitor.visitVarInsn(ALOAD, 1)
205-
methodVisitor.visitMethodInsn(INVOKESTATIC, SensorsAnalyticsHookConfig.sSensorsAnalyticsAPI, "trackMenuItem", "(Ljava/lang/Object;Landroid/view/MenuItem;)V", false)
278+
if (SensorsAnalyticsUtil.isStatic(access)) {
279+
methodVisitor.visitVarInsn(ALOAD, 1)
280+
methodVisitor.visitMethodInsn(INVOKESTATIC, SensorsAnalyticsHookConfig.sSensorsAnalyticsAPI, "trackMenuItem", "(Landroid/view/MenuItem;)V", false)
281+
} else {
282+
methodVisitor.visitVarInsn(ALOAD, 0)
283+
methodVisitor.visitVarInsn(ALOAD, 1)
284+
methodVisitor.visitMethodInsn(INVOKESTATIC, SensorsAnalyticsHookConfig.sSensorsAnalyticsAPI, "trackMenuItem", "(Ljava/lang/Object;Landroid/view/MenuItem;)V", false)
285+
}
206286
isHasTracked = true
207287
return
208288
}
@@ -250,6 +330,14 @@ class SensorsAnalyticsClassVisitor extends ClassVisitor implements Opcodes {
250330
}
251331
}
252332

333+
if (eventName != null && eventName.length() != 0) {
334+
methodVisitor.visitLdcInsn(eventName)
335+
methodVisitor.visitLdcInsn(eventProperties)
336+
methodVisitor.visitMethodInsn(INVOKESTATIC, SensorsAnalyticsHookConfig.sSensorsAnalyticsAPI, "track", "(Ljava/lang/String;Ljava/lang/String;)V", false)
337+
isHasTracked = true
338+
return
339+
}
340+
253341
if (mInterfaces != null && mInterfaces.length > 0) {
254342
SensorsAnalyticsMethodCell sensorsAnalyticsMethodCell = SensorsAnalyticsHookConfig.sInterfaceMethods.get(nameDesc)
255343
if (sensorsAnalyticsMethodCell != null && mInterfaces.contains(sensorsAnalyticsMethodCell.parent)) {
@@ -292,10 +380,25 @@ class SensorsAnalyticsClassVisitor extends ClassVisitor implements Opcodes {
292380
isHasInstrumented = true
293381
}
294382

383+
if (s == 'Lcom/sensorsdata/analytics/android/sdk/SensorsDataTrackEvent;') {
384+
return new AnnotationVisitor(Opcodes.ASM6) {
385+
@Override
386+
void visit(String key, Object value) {
387+
super.visit(key, value)
388+
if ("eventName" == key) {
389+
eventName = (String)value
390+
} else if ("properties" == key) {
391+
eventProperties = value.toString()
392+
}
393+
}
394+
}
395+
}
396+
295397
return super.visitAnnotation(s, b)
296398
}
297399
}
298400

299401
return methodVisitor
300402
}
403+
301404
}

0 commit comments

Comments
 (0)