Skip to content

Commit 5f0d3da

Browse files
committed
Release 2.2.0
1 parent 91e4e44 commit 5f0d3da

File tree

6 files changed

+216
-42
lines changed

6 files changed

+216
-42
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.1.2'
2+
pluginVersion = '2.2.0'
33
Properties properties = new Properties()
44
if (project.file('local.properties').exists()) {
55
properties.load(project.file('local.properties').newDataInputStream())

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,24 @@ class SensorsAnalyticsClassVisitor extends ClassVisitor implements Opcodes {
126126
return
127127
}
128128

129+
/**
130+
* 在 android.gradle 的 3.2.1 版本中,针对 view 的 setOnClickListener 方法 的 lambda 表达式做特殊处理。
131+
*/
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
138+
}
139+
visitMethodWithLoadedParams(methodVisitor, Opcodes.INVOKESTATIC, SensorsAnalyticsHookConfig.sSensorsAnalyticsAPI,
140+
sensorsAnalyticsMethodCell.agentName, sensorsAnalyticsMethodCell.agentDesc,
141+
paramStart, sensorsAnalyticsMethodCell.paramsCount, sensorsAnalyticsMethodCell.opcodes)
142+
isHasTracked = true
143+
return
144+
}
145+
}
146+
129147
if (!(SensorsAnalyticsUtil.isPublic(access) && !SensorsAnalyticsUtil.isStatic(access))) {
130148
return
131149
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package com.sensorsdata.analytics.android.plugin
33
class SensorsAnalyticsExtension {
44
boolean debug = false
55
boolean disableJar = false
6+
boolean useInclude = false
67
HashSet<String> exclude = []
78
HashSet<String> include = []
89
}

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

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,4 +159,122 @@ public class SensorsAnalyticsHookConfig {
159159
0, 3,
160160
[Opcodes.ALOAD, Opcodes.ALOAD, Opcodes.ALOAD]))
161161
}
162+
163+
/**
164+
* android.gradle 3.2.1 版本中,针对 Lambda 表达式处理
165+
*/
166+
167+
public final
168+
static HashMap<String, SensorsAnalyticsMethodCell> sLambdaMethods = new HashMap<>()
169+
170+
static {
171+
sLambdaMethods.put('(Landroid/view/View;)V', new SensorsAnalyticsMethodCell(
172+
'onClick',
173+
'(Landroid/view/View;)V',
174+
'android/view/View$OnClickListener',
175+
'trackViewOnClick',
176+
'(Landroid/view/View;)V',
177+
1, 1,
178+
[Opcodes.ALOAD]))
179+
sLambdaMethods.put('(Landroid/widget/CompoundButton;Z)V', new SensorsAnalyticsMethodCell(
180+
'onCheckedChanged',
181+
'(Landroid/widget/CompoundButton;Z)V',
182+
'android/widget/CompoundButton$OnCheckedChangeListener',
183+
'trackViewOnClick',
184+
'(Landroid/view/View;)V',
185+
1, 1,
186+
[Opcodes.ALOAD]))
187+
sLambdaMethods.put('(Landroid/widget/RatingBar;FZ)V', new SensorsAnalyticsMethodCell(
188+
'onRatingChanged',
189+
'(Landroid/widget/RatingBar;FZ)V',
190+
'android/widget/RatingBar$OnRatingBarChangeListener',
191+
'trackViewOnClick',
192+
'(Landroid/view/View;)V',
193+
1, 1,
194+
[Opcodes.ALOAD]))
195+
sLambdaMethods.put('(Landroid/widget/SeekBar;)V', new SensorsAnalyticsMethodCell(
196+
'onStopTrackingTouch',
197+
'(Landroid/widget/SeekBar;)V',
198+
'android/widget/SeekBar$OnSeekBarChangeListener',
199+
'trackViewOnClick',
200+
'(Landroid/view/View;)V',
201+
1, 1,
202+
[Opcodes.ALOAD]))
203+
sLambdaMethods.put('(Landroid/widget/RadioGroup;I)V', new SensorsAnalyticsMethodCell(
204+
'onCheckedChanged',
205+
'(Landroid/widget/RadioGroup;I)V',
206+
'android/widget/RadioGroup$OnCheckedChangeListener',
207+
'trackRadioGroup',
208+
'(Landroid/widget/RadioGroup;I)V',
209+
1, 2,
210+
[Opcodes.ALOAD, Opcodes.ILOAD]))
211+
sLambdaMethods.put('(Landroid/content/DialogInterface;I)V', new SensorsAnalyticsMethodCell(
212+
'onClick',
213+
'(Landroid/content/DialogInterface;I)V',
214+
'android/content/DialogInterface$OnClickListener',
215+
'trackDialog',
216+
'(Landroid/content/DialogInterface;I)V',
217+
1, 2,
218+
[Opcodes.ALOAD, Opcodes.ILOAD]))
219+
sLambdaMethods.put('(Landroid/widget/AdapterView;Landroid/view/View;IJ)V', new SensorsAnalyticsMethodCell(
220+
'onItemClick',
221+
'(Landroid/widget/AdapterView;Landroid/view/View;IJ)V',
222+
'android/widget/AdapterView$OnItemClickListener',
223+
'trackListView',
224+
'(Landroid/widget/AdapterView;Landroid/view/View;I)V',
225+
1, 3,
226+
[Opcodes.ALOAD, Opcodes.ALOAD, Opcodes.ILOAD]))
227+
sLambdaMethods.put('(Landroid/widget/AdapterView;Landroid/view/View;IJ)V', new SensorsAnalyticsMethodCell(
228+
'onItemSelected',
229+
'(Landroid/widget/AdapterView;Landroid/view/View;IJ)V',
230+
'android/widget/AdapterView$OnItemSelectedListener',
231+
'trackListView',
232+
'(Landroid/widget/AdapterView;Landroid/view/View;I)V',
233+
1, 3,
234+
[Opcodes.ALOAD, Opcodes.ALOAD, Opcodes.ILOAD]))
235+
sLambdaMethods.put('(Landroid/widget/ExpandableListView;Landroid/view/View;IJ)Z', new SensorsAnalyticsMethodCell(
236+
'onGroupClick',
237+
'(Landroid/widget/ExpandableListView;Landroid/view/View;IJ)Z',
238+
'android/widget/ExpandableListView$OnGroupClickListener',
239+
'trackExpandableListViewOnGroupClick',
240+
'(Landroid/widget/ExpandableListView;Landroid/view/View;I)V',
241+
1, 3,
242+
[Opcodes.ALOAD, Opcodes.ALOAD, Opcodes.ILOAD]))
243+
sLambdaMethods.put('(Landroid/widget/ExpandableListView;Landroid/view/View;IIJ)Z', new SensorsAnalyticsMethodCell(
244+
'onChildClick',
245+
'(Landroid/widget/ExpandableListView;Landroid/view/View;IIJ)Z',
246+
'android/widget/ExpandableListView$OnChildClickListener',
247+
'trackExpandableListViewOnChildClick',
248+
'(Landroid/widget/ExpandableListView;Landroid/view/View;II)V',
249+
1, 4,
250+
[Opcodes.ALOAD, Opcodes.ALOAD, Opcodes.ILOAD, Opcodes.ILOAD]))
251+
sLambdaMethods.put('(Ljava/lang/String;)V', new SensorsAnalyticsMethodCell(
252+
'onTabChanged',
253+
'(Ljava/lang/String;)V',
254+
'android/widget/TabHost$OnTabChangeListener',
255+
'trackTabHost',
256+
'(Ljava/lang/String;)V',
257+
1, 1,
258+
[Opcodes.ALOAD]))
259+
260+
sLambdaMethods.put('(Landroid/view/MenuItem;)Z', new SensorsAnalyticsMethodCell(
261+
'onNavigationItemSelected',
262+
'(Landroid/view/MenuItem;)Z',
263+
'android/support/design/widget/NavigationView$OnNavigationItemSelectedListener',
264+
'trackMenuItem',
265+
'(Ljava/lang/Object;Landroid/view/MenuItem;)V',
266+
0, 2,
267+
[Opcodes.ALOAD, Opcodes.ALOAD]))
268+
269+
sLambdaMethods.put('(Landroid/support/design/widget/TabLayout$Tab;)V', new SensorsAnalyticsMethodCell(
270+
'onTabSelected',
271+
'(Landroid/support/design/widget/TabLayout$Tab;)V',
272+
'android/support/design/widget/TabLayout$OnTabSelectedListener',
273+
'trackTabLayoutSelected',
274+
'(Ljava/lang/Object;Ljava/lang/Object;)V',
275+
0, 2,
276+
[Opcodes.ALOAD, Opcodes.ALOAD]))
277+
278+
// Todo: 扩展
279+
}
162280
}

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

Lines changed: 74 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,11 @@ import java.util.zip.ZipEntry
2727
class SensorsAnalyticsTransform extends Transform {
2828
private static Project project
2929
private static HashSet<String> exclude = ['com.sensorsdata.analytics.android.sdk', 'android.support']
30-
private static HashSet<String> include = []
30+
private static HashSet<String> include = ['butterknife.internal.DebouncingOnClickListener',
31+
'com.jakewharton.rxbinding.view.ViewClickOnSubscribe',
32+
'com.facebook.react.uimanager.NativeViewHierarchyManager']
3133
protected static boolean disableJar
34+
private static final String VERSION = "v2.2.0"
3235

3336
SensorsAnalyticsTransform(Project project) {
3437
this.project = project
@@ -62,7 +65,7 @@ class SensorsAnalyticsTransform extends Transform {
6265
println("####################################################################")
6366
println("######## ########")
6467
println("######## ########")
65-
println("######## 欢迎使用 SensorsAnalytics® 编译插件 ########")
68+
println("######## 欢迎使用 SensorsAnalytics® (" + VERSION + ")编译插件 ########")
6669
println("######## 使用过程中碰到任何问题请联系我们 ########")
6770
println("######## ########")
6871
println("######## ########")
@@ -101,8 +104,6 @@ class SensorsAnalyticsTransform extends Transform {
101104
*/
102105
input.jarInputs.each { JarInput jarInput ->
103106
String destName = jarInput.file.name
104-
Logger.info("开始遍历 jar:" + jarInput.file.absolutePath)
105-
106107
/**
107108
* 截取文件路径的md5值重命名输出文件,因为可能同名,会覆盖
108109
*/
@@ -114,15 +115,17 @@ class SensorsAnalyticsTransform extends Transform {
114115
File dest = outputProvider.getContentLocation(destName + "_" + hexName, jarInput.contentTypes, jarInput.scopes, Format.JAR)
115116

116117
def modifiedJar = null
117-
//if (!project.sensorsAnalytics.disableJar) {
118-
modifiedJar = modifyJarFile(jarInput.file, context.getTemporaryDir())
119-
//}
118+
if (!project.sensorsAnalytics.disableJar) {
119+
if (isShouldModifyJar(jarInput.file.absolutePath)) {
120+
Logger.info("开始遍历 jar:" + jarInput.file.absolutePath)
121+
modifiedJar = modifyJarFile(jarInput.file, context.getTemporaryDir())
122+
Logger.info("结束遍历 jar:" + jarInput.file.absolutePath)
123+
}
124+
}
120125
if (modifiedJar == null) {
121126
modifiedJar = jarInput.file
122127
}
123128
FileUtils.copyFile(modifiedJar, dest)
124-
125-
Logger.info("结束遍历 jar:" + jarInput.file.absolutePath)
126129
}
127130

128131
/**
@@ -157,36 +160,59 @@ class SensorsAnalyticsTransform extends Transform {
157160
}
158161
}
159162

160-
private static boolean isShouldModifyJar(String jarName) {
161-
Iterator<String> iterator = exclude.iterator()
162-
while (iterator.hasNext()) {
163-
String packageName = iterator.next()
164-
if (packageName == jarName) {
165-
return false
163+
private static boolean isShouldModifyJar(String jarFileName) {
164+
return true
165+
/*
166+
if (project.sensorsAnalytics.useInclude) {
167+
Iterator<String> iterator = include.iterator()
168+
while (iterator.hasNext()) {
169+
String jarName = iterator.next()
170+
if (jarFileName.contains(jarName)) {
171+
return true
172+
}
166173
}
174+
return false
175+
} else {
176+
Iterator<String> iterator = exclude.iterator()
177+
while (iterator.hasNext()) {
178+
String jarName = iterator.next()
179+
if (jarFileName.contains(jarName)) {
180+
return false
181+
}
182+
}
183+
return true
167184
}
168-
return true
185+
*/
169186
}
170187

171188
private static boolean isShouldModifyClass(String className) {
172-
if (!disableJar) {
173-
Iterator<String> iterator = exclude.iterator()
189+
if (className.contains('R$') ||
190+
className.contains('R2$') ||
191+
className.contains('R.class') ||
192+
className.contains('R2.class') ||
193+
className.contains('BuildConfig.class')) {
194+
return false
195+
}
196+
197+
if (project.sensorsAnalytics.useInclude) {
198+
Iterator<String> iterator = include.iterator()
174199
while (iterator.hasNext()) {
175200
String packageName = iterator.next()
201+
176202
if (className.startsWith(packageName)) {
177-
return false
203+
return true
178204
}
179205
}
180-
return true
206+
return false
181207
} else {
182-
Iterator<String> iterator = include.iterator()
208+
Iterator<String> iterator = exclude.iterator()
183209
while (iterator.hasNext()) {
184210
String packageName = iterator.next()
185211
if (className.startsWith(packageName)) {
186-
return true
212+
return false
187213
}
188214
}
189-
return false
215+
return true
190216
}
191217
}
192218

@@ -195,9 +221,7 @@ class SensorsAnalyticsTransform extends Transform {
195221
*/
196222
private static File modifyJarFile(File jarFile, File tempDir) {
197223
if (jarFile) {
198-
//if (isShouldModifyJar(jarFile.getName())) {
199-
return modifyJar(jarFile, tempDir, true)
200-
//}
224+
return modifyJar(jarFile, tempDir, true)
201225

202226
}
203227
return null
@@ -225,26 +249,35 @@ class SensorsAnalyticsTransform extends Transform {
225249
InputStream inputStream = file.getInputStream(jarEntry)
226250

227251
String entryName = jarEntry.getName()
228-
String className
252+
if (entryName.endsWith(".DSA") || entryName.endsWith(".SF")) {
253+
//ignore
254+
} else {
255+
String className
229256

230-
ZipEntry zipEntry = new ZipEntry(entryName)
257+
ZipEntry zipEntry = new ZipEntry(entryName)
231258

232-
jarOutputStream.putNextEntry(zipEntry)
259+
jarOutputStream.putNextEntry(zipEntry)
233260

234-
byte[] modifiedClassBytes = null
235-
byte[] sourceClassBytes = IOUtils.toByteArray(inputStream)
236-
if (entryName.endsWith(".class")) {
237-
className = entryName.replace("/", ".").replace(".class", "")
238-
if (isShouldModifyClass(className)) {
239-
modifiedClassBytes = modifyClasses(className, sourceClassBytes)
261+
byte[] modifiedClassBytes = null
262+
byte[] sourceClassBytes = null
263+
try {
264+
sourceClassBytes = IOUtils.toByteArray(inputStream)
265+
} catch (Exception e) {
266+
return null
240267
}
268+
if (entryName.endsWith(".class")) {
269+
className = entryName.replace("/", ".").replace(".class", "")
270+
if (isShouldModifyClass(className)) {
271+
modifiedClassBytes = modifyClasses(className, sourceClassBytes)
272+
}
273+
}
274+
if (modifiedClassBytes == null) {
275+
jarOutputStream.write(sourceClassBytes)
276+
} else {
277+
jarOutputStream.write(modifiedClassBytes)
278+
}
279+
jarOutputStream.closeEntry()
241280
}
242-
if (modifiedClassBytes == null) {
243-
jarOutputStream.write(sourceClassBytes)
244-
} else {
245-
jarOutputStream.write(modifiedClassBytes)
246-
}
247-
jarOutputStream.closeEntry()
248281
}
249282
jarOutputStream.close()
250283
file.close()

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ class SensorsAnalyticsUtil implements Opcodes {
2222
targetFragmentClass.add('android/support/v4/app/DialogFragment')
2323
}
2424

25+
static boolean isSynthetic(int access) {
26+
return (access & ACC_SYNTHETIC) != 0
27+
}
28+
2529
static boolean isPrivate(int access) {
2630
return (access & ACC_PRIVATE) != 0
2731
}

0 commit comments

Comments
 (0)