Skip to content

Commit 4d26721

Browse files
author
weiqiangliu
committed
Release 3.4.0
1 parent b5c3da3 commit 4d26721

File tree

9 files changed

+385
-96
lines changed

9 files changed

+385
-96
lines changed

plugin/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 = '3.3.9'
2+
pluginVersion = '3.4.0'
33
Properties properties = new Properties()
44
if (project.file('local.properties').exists()) {
55
properties.load(project.file('local.properties').newDataInputStream())

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

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
*/
1717
package com.sensorsdata.analytics.android.plugin
1818

19-
import com.sensorsdata.analytics.android.plugin.hook.SensorsPushInjected
19+
import com.sensorsdata.analytics.android.plugin.push.SensorsAnalyticsPushMethodVisitor
20+
import com.sensorsdata.analytics.android.plugin.push.SensorsPushInjected
2021
import com.sensorsdata.analytics.android.plugin.hook.config.SensorsFragmentHookConfig
2122
import com.sensorsdata.analytics.android.plugin.utils.VersionUtils
2223
import org.objectweb.asm.AnnotationVisitor
@@ -32,6 +33,7 @@ class SensorsAnalyticsClassVisitor extends ClassVisitor {
3233
private String mSuperName
3334
private String[] mInterfaces
3435
private HashSet<String> visitedFragMethods = new HashSet<>()// 无需判空
36+
private Boolean isFoundOnNewIntent = null
3537
private ClassVisitor classVisitor
3638

3739
private SensorsAnalyticsTransformHelper transformHelper
@@ -104,6 +106,9 @@ class SensorsAnalyticsClassVisitor extends ClassVisitor {
104106
@Override
105107
void visitEnd() {
106108
super.visitEnd()
109+
if (!transformHelper.extension.disableTrackPush && isFoundOnNewIntent != null && !isFoundOnNewIntent && mSuperName == "android/app/Activity") {
110+
SensorsPushInjected.addOnNewIntent(classVisitor);
111+
}
107112

108113
if (SensorsAnalyticsUtil.isInstanceOfFragment(mSuperName)) {
109114
MethodVisitor mv
@@ -180,11 +185,22 @@ class SensorsAnalyticsClassVisitor extends ClassVisitor {
180185
return null
181186
}
182187
}
188+
if (mSuperName == "android/app/Activity") {
189+
isFoundOnNewIntent = false
190+
if (name == "onNewIntent" && desc == "(Landroid/content/Intent;)V") {
191+
isFoundOnNewIntent = true
192+
}
193+
}
183194

184195
MethodVisitor methodVisitor = cv.visitMethod(access, name, desc, signature, exceptions)
185196
if (transformHelper.extension != null && transformHelper.extension.autoHandleWebView && transformHelper.urlClassLoader != null) {
186197
methodVisitor = new SensorsAnalyticsWebViewMethodVisitor(methodVisitor, access, name, desc, transformHelper, mClassName, mSuperName)
187198
}
199+
200+
if (transformHelper.extension != null && !transformHelper.extension.disableTrackPush) {
201+
methodVisitor = new SensorsAnalyticsPushMethodVisitor(methodVisitor, access, name, desc)
202+
}
203+
188204
SensorsAnalyticsDefaultMethodVisitor sensorsAnalyticsDefaultMethodVisitor = new SensorsAnalyticsDefaultMethodVisitor(methodVisitor, access, name, desc) {
189205
boolean isSensorsDataTrackViewOnClickAnnotation = false
190206
boolean isSensorsDataIgnoreTrackOnClick = false
@@ -245,8 +261,7 @@ class SensorsAnalyticsClassVisitor extends ClassVisitor {
245261
nameDesc = name + desc
246262
// Hook Push
247263
if (!SensorsAnalyticsUtil.isStatic(access) && !transformHelper.extension.disableTrackPush) {
248-
SensorsPushInjected.handleJPush(methodVisitor, mSuperName, mClassName, nameDesc)
249-
SensorsPushInjected.handleMeizuPush(methodVisitor, mSuperName, mClassName, nameDesc)
264+
SensorsPushInjected.handlePush(methodVisitor, mSuperName, mClassName, nameDesc, transformHelper.urlClassLoader)
250265
}
251266

252267
pubAndNoStaticAccess = SensorsAnalyticsUtil.isPublic(access) && !SensorsAnalyticsUtil.isStatic(access)

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ import java.util.jar.JarOutputStream
4848

4949
class SensorsAnalyticsTransform extends Transform {
5050
private SensorsAnalyticsTransformHelper transformHelper
51-
public static final String VERSION = "3.3.9"
52-
public static final String MIN_SDK_VERSION = "5.4.2"
51+
public static final String VERSION = "3.4.0"
52+
public static final String MIN_SDK_VERSION = "5.4.3"
5353
private WaitableExecutor waitableExecutor
5454
private URLClassLoader urlClassLoader
5555
// “com.sensorsdata.analytics.android.sdk.SensorsDataAPI” 类所在路径

plugin/src/main/groovy/com/sensorsdata/analytics/android/plugin/SensorsAnalyticsTransformHelper.groovy

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,25 @@ class SensorsAnalyticsTransformHelper {
2828
boolean disableSensorsAnalyticsMultiThread
2929
boolean disableSensorsAnalyticsIncremental
3030
boolean isHookOnMethodEnter
31-
HashSet<String> exclude = new HashSet<>(['com.sensorsdata.analytics.android.sdk', 'android.support', 'androidx', 'com.qiyukf', 'android.arch',
32-
'com.google.android', "com.tencent.smtt", 'com.bumptech.glide'])
31+
HashSet<String> exclude = new HashSet<>(['com.sensorsdata.analytics.android.sdk',
32+
'android.support',
33+
'androidx',
34+
'com.qiyukf',
35+
'android.arch',
36+
'com.google.android',
37+
"com.tencent.smtt",
38+
"com.umeng.message",
39+
"com.xiaomi.push",
40+
"com.huawei.hms",
41+
"com.igexin.push",
42+
"cn.jpush.android",
43+
"cn.jiguang",
44+
"com.meizu.cloud.pushsdk",
45+
"com.vivo.push",
46+
"com.igexin.sdk",
47+
"com.xiaomi.mipush.sdk",
48+
"com.heytap.msp.push",
49+
'com.bumptech.glide'])
3350
HashSet<String> include = new HashSet<>(['butterknife.internal.DebouncingOnClickListener',
3451
'com.jakewharton.rxbinding.view.ViewClickOnSubscribe',
3552
'com.facebook.react.uimanager.NativeViewHierarchyManager'])
@@ -38,6 +55,12 @@ class SensorsAnalyticsTransformHelper {
3855
'com.google.android.material.tabs.TabLayout$ViewPagerOnTabSelectedListener',
3956
'android.support.v7.app.ActionBarDrawerToggle',
4057
'androidx.appcompat.app.ActionBarDrawerToggle',
58+
'androidx.fragment.app.FragmentActivity',
59+
'androidx.core.app.NotificationManagerCompat',
60+
'androidx.core.app.ComponentActivity',
61+
'android.support.v4.app.NotificationManagerCompat',
62+
'android.support.v4.app.SupportActivity',
63+
'cn.jpush.android.service.PluginMeizuPlatformsReceiver',
4164
'androidx.appcompat.widget.ActionMenuPresenter$OverflowMenuButton',
4265
'android.widget.ActionMenuPresenter$OverflowMenuButton',
4366
'android.support.v7.widget.ActionMenuPresenter$OverflowMenuButton']
@@ -130,7 +153,7 @@ class SensorsAnalyticsTransformHelper {
130153
return classNameAnalytics
131154
}
132155

133-
enum RN_STATE{
156+
enum RN_STATE {
134157
NOT_FOUND, NO_VERSION, HAS_VERSION
135158
}
136159
}

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import groovy.transform.CompileStatic
2020
import org.apache.commons.io.IOUtils
2121
import org.apache.commons.io.output.ByteArrayOutputStream
2222
import org.objectweb.asm.Opcodes
23+
import org.objectweb.asm.Type
2324

2425
@CompileStatic
2526
class SensorsAnalyticsUtil {
@@ -195,4 +196,8 @@ class SensorsAnalyticsUtil {
195196
static boolean isInstanceOfActivity(String superName) {
196197
return targetActivityClass.contains(superName)
197198
}
198-
}
199+
200+
static String appendDescBeforeGiven(String givenDesc, String appendDesc) {
201+
return givenDesc.replaceFirst("\\(", "(" + appendDesc);
202+
}
203+
}

plugin/src/main/groovy/com/sensorsdata/analytics/android/plugin/SensorsAnalyticsWebViewMethodVisitor.groovy

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ class SensorsAnalyticsWebViewMethodVisitor extends AdviceAdapter implements Opco
9898
positionList.reverseEach { tmp ->
9999
loadLocal(tmp)
100100
}
101-
desc = reStructureDesc(desc)
101+
desc = SensorsAnalyticsUtil.appendDescBeforeGiven(desc, VIEW_DESC)
102102
//为保持新 SDK 使用旧版插件问题,会使用新 SDK loadUrl + 2 后缀的方法
103103
mv.visitMethodInsn(INVOKESTATIC, SensorsAnalyticsHookConfig.SENSORS_ANALYTICS_API, name + "2", desc, false)
104104
}
@@ -129,7 +129,7 @@ class SensorsAnalyticsWebViewMethodVisitor extends AdviceAdapter implements Opco
129129
mv.visitTypeInsn(CHECKCAST, "android/view/View")
130130
}
131131
}
132-
desc = reStructureDesc(desc)
132+
desc = SensorsAnalyticsUtil.appendDescBeforeGiven(desc, VIEW_DESC)
133133
//为保持新 SDK 使用旧版插件问题,会使用新 SDK loadUrl + 2 后缀的方法
134134
mv.visitMethodInsn(INVOKESTATIC, SensorsAnalyticsHookConfig.SENSORS_ANALYTICS_API, name + "2", desc, false)
135135
mv.visitLabel(label)
@@ -192,10 +192,6 @@ class SensorsAnalyticsWebViewMethodVisitor extends AdviceAdapter implements Opco
192192
}
193193
}
194194

195-
private static String reStructureDesc(String desc) {
196-
return desc.replaceFirst("\\(", "(" + VIEW_DESC)
197-
}
198-
199195
private enum X5WebViewStatus {
200196
NOT_INITIAL, FOUND, NOT_FOUND
201197
}

plugin/src/main/groovy/com/sensorsdata/analytics/android/plugin/hook/SensorsPushInjected.java

Lines changed: 0 additions & 80 deletions
This file was deleted.
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
/*
2+
* Created by zhangwei on 2021/08/09.
3+
* Copyright 2015-2021 Sensors Data Inc.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package com.sensorsdata.analytics.android.plugin.push;
19+
20+
import com.sensorsdata.analytics.android.plugin.SensorsAnalyticsUtil;
21+
22+
import org.objectweb.asm.MethodVisitor;
23+
import org.objectweb.asm.Opcodes;
24+
import org.objectweb.asm.Type;
25+
import org.objectweb.asm.commons.AdviceAdapter;
26+
27+
import java.util.ArrayList;
28+
import java.util.List;
29+
30+
public class SensorsAnalyticsPushMethodVisitor extends AdviceAdapter {
31+
private static final String PENDING_INTENT_OWNER = "android/app/PendingIntent";
32+
33+
public SensorsAnalyticsPushMethodVisitor(MethodVisitor methodVisitor, int access, String name, String descriptor) {
34+
super(SensorsAnalyticsUtil.ASM_VERSION, methodVisitor, access, name, descriptor);
35+
}
36+
37+
@Override
38+
public void visitCode() {
39+
super.visitCode();
40+
}
41+
42+
@Override
43+
public void visitMethodInsn(int opcodeAndSource, String owner, String name, String descriptor, boolean isInterface) {
44+
//PendingIntent.getActivity() before and after
45+
if (opcodeAndSource == Opcodes.INVOKESTATIC && PENDING_INTENT_OWNER.equals(owner) && checkPendingIntentName(name)) {
46+
Type[] argTypes = Type.getArgumentTypes(descriptor);
47+
List<Integer> positionList = new ArrayList<>();
48+
for (int index = argTypes.length - 1; index >= 0; index--) {
49+
int position = newLocal(argTypes[index]);
50+
storeLocal(position, argTypes[index]);
51+
positionList.add(0, position);
52+
}
53+
positionList.forEach(this::loadLocal);
54+
mv.visitMethodInsn(Opcodes.INVOKESTATIC, SensorsPushInjected.PUSH_TRACK_OWNER, getIntentHookMethodName(argTypes.length, name),
55+
refactorHookBeforeMethodDescriptor(descriptor), false);
56+
positionList.forEach(this::loadLocal);
57+
super.visitMethodInsn(opcodeAndSource, owner, name, descriptor, isInterface);
58+
mv.visitInsn(Opcodes.DUP);
59+
positionList.forEach(this::loadLocal);
60+
mv.visitMethodInsn(Opcodes.INVOKESTATIC, SensorsPushInjected.PUSH_TRACK_OWNER, getPendingIntentHookMethodName(argTypes.length, name),
61+
refactorHookAfterMethodDescriptor(descriptor), false);
62+
return;
63+
}
64+
65+
//NotificationManager.notify()
66+
if (opcodeAndSource == Opcodes.INVOKEVIRTUAL && "android/app/NotificationManager".equals(owner) && "notify".equals(name)) {
67+
Type[] argTypes = Type.getArgumentTypes(descriptor);
68+
List<Integer> positionList = new ArrayList<>();
69+
for (int index = argTypes.length - 1; index >= 0; index--) {
70+
int position = newLocal(argTypes[index]);
71+
storeLocal(position, argTypes[index]);
72+
positionList.add(0, position);
73+
}
74+
mv.visitInsn(Opcodes.DUP);
75+
positionList.forEach(this::loadLocal);
76+
super.visitMethodInsn(opcodeAndSource, owner, name, descriptor, isInterface);
77+
positionList.forEach(this::loadLocal);
78+
mv.visitMethodInsn(Opcodes.INVOKESTATIC, SensorsPushInjected.PUSH_TRACK_OWNER, "onNotify",
79+
SensorsAnalyticsUtil.appendDescBeforeGiven(descriptor, "Landroid/app/NotificationManager;"), false);
80+
return;
81+
}
82+
83+
super.visitMethodInsn(opcodeAndSource, owner, name, descriptor, isInterface);
84+
}
85+
86+
private boolean checkPendingIntentName(String methodName) {
87+
return "getActivity".equals(methodName) || "getService".equals(methodName) || "getBroadcast".equals(methodName) || "getForegroundService".equals(methodName);
88+
}
89+
90+
private String refactorHookBeforeMethodDescriptor(String desc) {
91+
//change return type to void
92+
return desc.substring(0, desc.lastIndexOf(")") + 1) + "V";
93+
}
94+
95+
private String refactorHookAfterMethodDescriptor(String desc) {
96+
//change return type to void and add PendingIntent prefix
97+
return "(Landroid/app/PendingIntent;" + desc.substring(1, desc.lastIndexOf(")") + 1) + "V";
98+
}
99+
100+
private String getIntentHookMethodName(int argsLength, String name) {
101+
if ("getActivity".equals(name)) {
102+
return argsLength == 4 ? "hookIntentGetActivity" : "hookIntentGetActivityBundle";
103+
}
104+
return String.format("hookIntent%s", firstLetterUpper(name));
105+
}
106+
107+
private String getPendingIntentHookMethodName(int argsLength, String name) {
108+
if ("getActivity".equals(name)) {
109+
return argsLength == 4 ? "hookPendingIntentGetActivity" : "hookPendingIntentGetActivityBundle";
110+
}
111+
return String.format("hookPendingIntent%s", firstLetterUpper(name));
112+
}
113+
114+
private static String firstLetterUpper(String name) {
115+
char[] cs = name.toCharArray();
116+
cs[0] -= 32;
117+
return String.valueOf(cs);
118+
}
119+
}

0 commit comments

Comments
 (0)