Skip to content

Commit 337fcee

Browse files
author
weiqiangliu
committed
Release 2.1.0
1 parent 2dba525 commit 337fcee

File tree

11 files changed

+322
-62
lines changed

11 files changed

+322
-62
lines changed

RNSensorsAnalyticsModule.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
Pod::Spec.new do |s|
33
s.name = "RNSensorsAnalyticsModule"
4-
s.version = "2.0.9"
4+
s.version = "2.1.0"
55
s.summary = "The official React Native SDK of Sensors Analytics."
66
s.description = <<-DESC
77
神策分析 RN 组件

android/src/main/java/com/sensorsdata/analytics/RNAgent.java

Lines changed: 78 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -17,57 +17,86 @@
1717

1818
package com.sensorsdata.analytics;
1919

20+
import android.util.SparseArray;
2021
import android.view.MotionEvent;
21-
import android.view.MotionEvent.*;
2222
import android.view.View;
2323
import android.view.ViewGroup;
24-
import com.facebook.react.bridge.ReadableMap;
25-
import com.sensorsdata.analytics.RNSensorsAnalyticsModule;
26-
import com.sensorsdata.analytics.utils.RNViewUtils;
27-
import com.sensorsdata.analytics.data.SAViewProperties;
28-
import com.sensorsdata.analytics.property.RNPropertyManager;
2924

25+
import com.facebook.react.bridge.ReadableMap;
3026
import com.facebook.react.uimanager.JSTouchDispatcher;
3127
import com.facebook.react.uimanager.events.EventDispatcher;
3228
import com.sensorsdata.analytics.android.sdk.SALog;
3329
import com.sensorsdata.analytics.android.sdk.SensorsDataAPI;
3430
import com.sensorsdata.analytics.android.sdk.util.SensorsDataUtils;
35-
import com.sensorsdata.analytics.android.sdk.SensorsDataAutoTrackHelper;
31+
import com.sensorsdata.analytics.data.SAViewProperties;
32+
import com.sensorsdata.analytics.property.RNPropertyManager;
33+
import com.sensorsdata.analytics.utils.RNTouchTargetHelper;
34+
import com.sensorsdata.analytics.utils.RNViewUtils;
35+
36+
import org.json.JSONObject;
3637

3738
import java.lang.reflect.Field;
3839
import java.util.WeakHashMap;
39-
import java.util.HashMap;
40-
import org.json.JSONObject;
41-
import android.util.SparseArray;
4240

4341
public class RNAgent {
4442
private static final WeakHashMap jsTouchDispatcherViewGroupWeakHashMap = new WeakHashMap();
4543
private static SparseArray<SAViewProperties> viewPropertiesArray = new SparseArray();
4644

4745
public static void handleTouchEvent(
4846
JSTouchDispatcher jsTouchDispatcher, MotionEvent event, EventDispatcher eventDispatcher) {
47+
try {
48+
if (event.getAction() == MotionEvent.ACTION_DOWN) { // ActionDown
49+
ViewGroup viewGroup = (ViewGroup) jsTouchDispatcherViewGroupWeakHashMap.get(jsTouchDispatcher);
50+
if (viewGroup == null) {
51+
try {
52+
Field viewGroupField = jsTouchDispatcher.getClass().getDeclaredField("mRootViewGroup");
53+
viewGroupField.setAccessible(true);
54+
viewGroup = (ViewGroup) viewGroupField.get(jsTouchDispatcher);
55+
jsTouchDispatcherViewGroupWeakHashMap.put(jsTouchDispatcher, viewGroup);
56+
} catch (Exception e) {
57+
SALog.printStackTrace(e);
58+
}
59+
}
60+
if (viewGroup != null) {
61+
View nativeTargetView =
62+
RNTouchTargetHelper.findTouchTargetView(
63+
new float[]{event.getX(), event.getY()}, viewGroup);
64+
if (nativeTargetView != null) {
65+
View reactTargetView = RNTouchTargetHelper.findClosestReactAncestor(nativeTargetView);
66+
if (reactTargetView != null) {
67+
nativeTargetView = reactTargetView;
68+
}
69+
}
70+
if (nativeTargetView != null) {
71+
RNViewUtils.setOnTouchView(nativeTargetView);
72+
}
73+
}
74+
}
75+
} catch (Exception ignored) {
76+
77+
}
4978
}
5079

51-
public static void trackViewScreen(String url, JSONObject properties, boolean isAuto){
52-
try{
80+
static void trackViewScreen(String url, JSONObject properties, boolean isAuto) {
81+
try {
5382
String screenName = url;
54-
if(properties == null){
83+
if (properties == null) {
5584
properties = new JSONObject();
5685
}
57-
if(properties.has("$screen_name")){
86+
if (properties.has("$screen_name")) {
5887
screenName = properties.getString("$screen_name");
5988
}
6089
String title = screenName;
61-
if(properties.has("$title")){
90+
if (properties.has("$title")) {
6291
title = properties.getString("$title");
6392
}
64-
if(screenName != null){
65-
properties.put("$screen_name",screenName);
93+
if (screenName != null) {
94+
properties.put("$screen_name", screenName);
6695
}
67-
if(title != null){
68-
properties.put("$title",title);
96+
if (title != null) {
97+
properties.put("$title", title);
6998
}
70-
RNViewUtils.saveScreenAndTitle(screenName,title);
99+
RNViewUtils.saveScreenAndTitle(screenName, title);
71100
//关闭 AutoTrack
72101
if (isAuto && !SensorsDataAPI.sharedInstance().isAutoTrackEnabled()) {
73102
return;
@@ -77,12 +106,12 @@ public static void trackViewScreen(String url, JSONObject properties, boolean is
77106
return;
78107
}
79108
SensorsDataAPI.sharedInstance().trackViewScreen(url, RNPropertyManager.mergeProperty(properties, isAuto));
80-
}catch(Exception e){
109+
} catch (Exception e) {
81110
SALog.printStackTrace(e);
82111
}
83112
}
84113

85-
public static void trackViewClick(int viewId){
114+
static void trackViewClick(int viewId) {
86115
try {
87116
//关闭 AutoTrack
88117
if (!SensorsDataAPI.sharedInstance().isAutoTrackEnabled()) {
@@ -92,61 +121,66 @@ public static void trackViewClick(int viewId){
92121
if (SensorsDataAPI.sharedInstance().isAutoTrackEventTypeIgnored(SensorsDataAPI.AutoTrackEventType.APP_CLICK)) {
93122
return;
94123
}
95-
View clickView = RNViewUtils.getTouchViewByTag(viewId);
124+
View clickView = RNViewUtils.getViewByTag(viewId);
96125
if (clickView != null) {
97126
JSONObject properties = new JSONObject();
98-
if(RNViewUtils.getTitle() != null){
99-
properties.put("$title",RNViewUtils.getTitle());
127+
if (RNViewUtils.getTitle() != null) {
128+
properties.put("$title", RNViewUtils.getTitle());
100129
}
101-
if(RNViewUtils.getScreenName() != null){
102-
properties.put("$screen_name",RNViewUtils.getScreenName());
130+
if (RNViewUtils.getScreenName() != null) {
131+
properties.put("$screen_name", RNViewUtils.getScreenName());
103132
}
104133
SAViewProperties viewProperties = viewPropertiesArray.get(viewId);
105-
if(viewProperties != null && viewProperties.properties != null && viewProperties.properties.length() > 0){
106-
if(viewProperties.properties.optBoolean("ignore", false)){
134+
if (viewProperties != null && viewProperties.properties != null && viewProperties.properties.length() > 0) {
135+
if (viewProperties.properties.optBoolean("ignore", false)) {
107136
return;
108137
}
109138
viewProperties.properties.remove("ignore");
110139
SensorsDataUtils.mergeJSONObject(viewProperties.properties, properties);
111140
}
112-
SensorsDataAPI.sharedInstance().trackViewAppClick(clickView, RNPropertyManager.mergeProperty(properties ,true));
141+
SensorsDataAPI.sharedInstance().trackViewAppClick(clickView, RNPropertyManager.mergeProperty(properties, true));
113142
}
114143
} catch (Exception e) {
115144
SALog.printStackTrace(e);
116145
}
117146
}
118147

119-
public static void saveViewProperties(int viewId, boolean clickable, ReadableMap viewProperties) {
120-
if(clickable){
148+
static void saveViewProperties(int viewId, boolean clickable, ReadableMap viewProperties) {
149+
if (clickable) {
121150
viewPropertiesArray.put(viewId, new SAViewProperties(clickable, viewProperties));
122151
}
123152
}
124153

125-
public static void addView(View view,int index){
154+
/**
155+
* 添加 View 调用,Android 插件调用,勿删
156+
* @param view View
157+
* @param index index
158+
*/
159+
public static void addView(View view, int index) {
126160
SAViewProperties properties = viewPropertiesArray.get(view.getId());
127-
if(properties != null){
161+
if (properties != null) {
128162
properties.setViewClickable(view);
129163
}
130164
}
131165

132166
/**
133167
* 忽略 Slider、Switch Android SDK 的采集逻辑,统一通过 Recat Native 采集
134168
*/
135-
static void ignoreView(){
136-
try{
169+
static void ignoreView() {
170+
try {
137171
SensorsDataAPI.sharedInstance().ignoreViewType(Class.forName("com.facebook.react.views.switchview.ReactSwitch"));
138-
}catch (Exception e){
139-
172+
} catch (Exception e) {
173+
//ignored
140174
}
141-
try{
175+
try {
142176
SensorsDataAPI.sharedInstance().ignoreViewType(Class.forName("com.facebook.react.views.slider.ReactSlider"));
143-
}catch (Exception e){
144-
177+
} catch (Exception e) {
178+
//ignored
145179
}
146-
try{
180+
try {
147181
SensorsDataAPI.sharedInstance().ignoreViewType(Class.forName("com.reactnativecommunity.slider.ReactSlider"));
148-
}catch (Exception e){
149-
182+
} catch (Exception e) {
183+
//ignored
150184
}
151185
}
152186
}

android/src/main/java/com/sensorsdata/analytics/RNSensorsAnalyticsModule.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,4 +1007,17 @@ public void trackAppInstall(ReadableMap properties) {
10071007
Log.e(LOGTAG, e.toString() + "");
10081008
}
10091009
}
1010+
1011+
/**
1012+
* 开启数据采集
1013+
*/
1014+
@ReactMethod
1015+
public void enableDataCollect() {
1016+
try {
1017+
SensorsDataAPI.sharedInstance().enableDataCollect();
1018+
} catch (Exception e) {
1019+
e.printStackTrace();
1020+
Log.e(LOGTAG, e.toString() + "");
1021+
}
1022+
}
10101023
}

android/src/main/java/com/sensorsdata/analytics/RNSensorsAnalyticsPackage.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
import java.util.List;
2929

3030
public class RNSensorsAnalyticsPackage implements ReactPackage {
31-
public static final String VERSION = "2.0.9";
31+
public static final String VERSION = "2.1.0";
3232
@Override
3333
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
3434
List<NativeModule> modules = new ArrayList<>();
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
package com.sensorsdata.analytics.utils;
2+
3+
import android.graphics.Matrix;
4+
import android.graphics.PointF;
5+
import android.graphics.Rect;
6+
import android.view.View;
7+
import android.view.ViewGroup;
8+
import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
9+
import com.facebook.react.bridge.UiThreadUtil;
10+
import com.facebook.react.touch.ReactHitSlopView;
11+
import com.facebook.react.uimanager.PointerEvents;
12+
import com.facebook.react.uimanager.ReactCompoundView;
13+
import com.facebook.react.uimanager.ReactCompoundViewGroup;
14+
import com.facebook.react.uimanager.ReactPointerEventsView;
15+
16+
public class RNTouchTargetHelper {
17+
private static final float[] mEventCoords = new float[2];
18+
private static final Matrix mInverseMatrix = new Matrix();
19+
private static final float[] mMatrixTransformCoords = new float[2];
20+
private static final PointF mTempPoint = new PointF();
21+
22+
public static int findTargetTagForTouch(float eventX, float eventY, ViewGroup viewGroup) {
23+
return findTargetTagAndCoordinatesForTouch(eventX, eventY, viewGroup, mEventCoords);
24+
}
25+
26+
public static int findTargetTagAndCoordinatesForTouch(float eventX, float eventY, ViewGroup viewGroup, float[] viewCoords) {
27+
UiThreadUtil.assertOnUiThread();
28+
int targetTag = viewGroup.getId();
29+
viewCoords[0] = eventX;
30+
viewCoords[1] = eventY;
31+
View nativeTargetView = findTouchTargetView(viewCoords, viewGroup);
32+
if (nativeTargetView == null) {
33+
return targetTag;
34+
}
35+
View reactTargetView = findClosestReactAncestor(nativeTargetView);
36+
if (reactTargetView != null) {
37+
return getTouchTargetForView(reactTargetView, viewCoords[0], viewCoords[1]);
38+
}
39+
return targetTag;
40+
}
41+
42+
public static View findClosestReactAncestor(View view) {
43+
while (view != null && view.getId() <= 0) {
44+
view = (View) view.getParent();
45+
}
46+
return view;
47+
}
48+
49+
public static View findTouchTargetView(float[] eventCoords, ViewGroup viewGroup) {
50+
for (int i = viewGroup.getChildCount() - 1; i >= 0; i--) {
51+
View child = viewGroup.getChildAt(i);
52+
PointF childPoint = mTempPoint;
53+
if (isTransformedTouchPointInView(eventCoords[0], eventCoords[1], viewGroup, child, childPoint)) {
54+
float restoreX = eventCoords[0];
55+
float restoreY = eventCoords[1];
56+
eventCoords[0] = childPoint.x;
57+
eventCoords[1] = childPoint.y;
58+
View targetView = findTouchTargetViewWithPointerEvents(eventCoords, child);
59+
if (targetView != null) {
60+
return targetView;
61+
}
62+
eventCoords[0] = restoreX;
63+
eventCoords[1] = restoreY;
64+
}
65+
}
66+
return viewGroup;
67+
}
68+
69+
private static boolean isTransformedTouchPointInView(float x, float y, ViewGroup parent, View child, PointF outLocalPoint) {
70+
float localX = (((float) parent.getScrollX()) + x) - ((float) child.getLeft());
71+
float localY = (((float) parent.getScrollY()) + y) - ((float) child.getTop());
72+
Matrix matrix = child.getMatrix();
73+
if (!matrix.isIdentity()) {
74+
float[] localXY = mMatrixTransformCoords;
75+
localXY[0] = localX;
76+
localXY[1] = localY;
77+
Matrix inverseMatrix = mInverseMatrix;
78+
matrix.invert(inverseMatrix);
79+
inverseMatrix.mapPoints(localXY);
80+
localX = localXY[0];
81+
localY = localXY[1];
82+
}
83+
if ((child instanceof ReactHitSlopView) && ((ReactHitSlopView) child).getHitSlopRect() != null) {
84+
Rect hitSlopRect = ((ReactHitSlopView) child).getHitSlopRect();
85+
if (localX < ((float) (-hitSlopRect.left)) || localX >= ((float) ((child.getRight() - child.getLeft()) + hitSlopRect.right)) || localY < ((float) (-hitSlopRect.top)) || localY >= ((float) ((child.getBottom() - child.getTop()) + hitSlopRect.bottom))) {
86+
return false;
87+
}
88+
outLocalPoint.set(localX, localY);
89+
return true;
90+
} else if (localX < 0.0f || localX >= ((float) (child.getRight() - child.getLeft())) || localY < 0.0f || localY >= ((float) (child.getBottom() - child.getTop()))) {
91+
return false;
92+
} else {
93+
outLocalPoint.set(localX, localY);
94+
return true;
95+
}
96+
}
97+
98+
private static View findTouchTargetViewWithPointerEvents(float[] eventCoords, View view) {
99+
PointerEvents pointerEvents = view instanceof ReactPointerEventsView ? ((ReactPointerEventsView) view).getPointerEvents() : PointerEvents.AUTO;
100+
if (pointerEvents == PointerEvents.NONE) {
101+
return null;
102+
}
103+
if (pointerEvents == PointerEvents.BOX_ONLY) {
104+
return view;
105+
}
106+
if (pointerEvents == PointerEvents.BOX_NONE) {
107+
if (view instanceof ViewGroup) {
108+
View targetView = findTouchTargetView(eventCoords, (ViewGroup) view);
109+
if (targetView != view) {
110+
return targetView;
111+
}
112+
if (!(view instanceof ReactCompoundView) || ((ReactCompoundView) view).reactTagForTouch(eventCoords[0], eventCoords[1]) == view.getId()) {
113+
return null;
114+
}
115+
return view;
116+
}
117+
return null;
118+
} else if (pointerEvents != PointerEvents.AUTO) {
119+
StringBuilder stringBuilder = new StringBuilder();
120+
stringBuilder.append("Unknown pointer event type: ");
121+
stringBuilder.append(pointerEvents.toString());
122+
throw new JSApplicationIllegalArgumentException(stringBuilder.toString());
123+
} else if ((!(view instanceof ReactCompoundViewGroup) || !((ReactCompoundViewGroup) view).interceptsTouchEvent(eventCoords[0], eventCoords[1])) && (view instanceof ViewGroup)) {
124+
return findTouchTargetView(eventCoords, (ViewGroup) view);
125+
} else {
126+
return view;
127+
}
128+
}
129+
130+
public static int getTouchTargetForView(View targetView, float eventX, float eventY) {
131+
if (targetView instanceof ReactCompoundView) {
132+
return ((ReactCompoundView) targetView).reactTagForTouch(eventX, eventY);
133+
}
134+
return targetView.getId();
135+
}
136+
}

0 commit comments

Comments
 (0)