Skip to content

Commit 37308d1

Browse files
author
chenru
committed
提交 Android 少提交代码
1 parent d2355b3 commit 37308d1

File tree

5 files changed

+514
-0
lines changed

5 files changed

+514
-0
lines changed
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
package com.sensorsdata.analytics;
2+
3+
import android.view.MotionEvent;
4+
import android.view.MotionEvent.*;
5+
import android.view.View;
6+
import android.view.ViewGroup;
7+
import com.facebook.react.bridge.ReadableMap;
8+
import com.sensorsdata.analytics.RNSensorsAnalyticsModule;
9+
import com.sensorsdata.analytics.utils.RNViewUtils;
10+
11+
import com.facebook.react.uimanager.JSTouchDispatcher;
12+
import com.facebook.react.uimanager.events.EventDispatcher;
13+
import com.sensorsdata.analytics.android.sdk.SALog;
14+
import com.sensorsdata.analytics.android.sdk.SensorsDataAPI;
15+
import com.sensorsdata.analytics.android.sdk.util.SensorsDataUtils;
16+
import com.sensorsdata.analytics.android.sdk.SensorsDataAutoTrackHelper;
17+
import com.sensorsdata.analytics.utils.RNTouchTargetHelper;
18+
19+
import java.lang.reflect.Field;
20+
import java.util.WeakHashMap;
21+
import java.util.HashMap;
22+
import org.json.JSONObject;
23+
24+
public class RNAgent {
25+
private static final WeakHashMap jsTouchDispatcherViewGroupWeakHashMap = new WeakHashMap();
26+
27+
public static void handleTouchEvent(
28+
JSTouchDispatcher jsTouchDispatcher, MotionEvent event, EventDispatcher eventDispatcher) {
29+
30+
if (event.getAction() == MotionEvent.ACTION_DOWN) { // ActionDown
31+
ViewGroup viewGroup = (ViewGroup)jsTouchDispatcherViewGroupWeakHashMap.get(jsTouchDispatcher);
32+
if (viewGroup == null) {
33+
try {
34+
Field viewGroupField = jsTouchDispatcher.getClass().getDeclaredField("mRootViewGroup");
35+
viewGroupField.setAccessible(true);
36+
viewGroup = (ViewGroup) viewGroupField.get(jsTouchDispatcher);
37+
jsTouchDispatcherViewGroupWeakHashMap.put(jsTouchDispatcher, viewGroup);
38+
} catch (Exception e) {
39+
SALog.printStackTrace(e);
40+
}
41+
}
42+
if (viewGroup != null) {
43+
View nativeTargetView =
44+
RNTouchTargetHelper.findTouchTargetView(
45+
new float[] {event.getX(), event.getY()}, viewGroup);
46+
if (nativeTargetView != null) {
47+
View reactTargetView = RNTouchTargetHelper.findClosestReactAncestor(nativeTargetView);
48+
if (reactTargetView != null) {
49+
nativeTargetView = reactTargetView;
50+
}
51+
}
52+
if (nativeTargetView != null) {
53+
RNViewUtils.setOnTouchView(nativeTargetView);
54+
}
55+
}
56+
}
57+
}
58+
59+
public static void trackViewScreen(String url, JSONObject properties, boolean isAuto){
60+
try{
61+
String screenName = url;
62+
if(properties == null){
63+
properties = new JSONObject();
64+
}
65+
if(properties.has("$screen_name")){
66+
screenName = properties.getString("$screen_name");
67+
}
68+
String title = screenName;
69+
if(properties.has("$title")){
70+
title = properties.getString("$title");
71+
}
72+
if(screenName != null){
73+
properties.put("$screen_name",screenName);
74+
}
75+
if(title != null){
76+
properties.put("$title",title);
77+
}
78+
RNViewUtils.saveScreenAndTitle(screenName,title);
79+
//关闭 AutoTrack
80+
if (isAuto && !SensorsDataAPI.sharedInstance().isAutoTrackEnabled()) {
81+
return;
82+
}
83+
//$AppViewScreen 被过滤
84+
if (isAuto && SensorsDataAPI.sharedInstance().isAutoTrackEventTypeIgnored(SensorsDataAPI.AutoTrackEventType.APP_VIEW_SCREEN)) {
85+
return;
86+
}
87+
SensorsDataAPI.sharedInstance().trackViewScreen(url, properties);
88+
}catch(Exception e){
89+
SALog.printStackTrace(e);
90+
}
91+
}
92+
93+
public static void trackViewClick(int viewId){
94+
try {
95+
View clickView = RNViewUtils.getTouchViewByTag(viewId);
96+
if (clickView != null) {
97+
JSONObject properties = new JSONObject();
98+
if(RNViewUtils.getTitle() != null){
99+
properties.put("$title",RNViewUtils.getTitle());
100+
}
101+
if(RNViewUtils.getScreenName() != null){
102+
properties.put("$screen_name",RNViewUtils.getScreenName());
103+
}
104+
SensorsDataAPI.sharedInstance().trackViewAppClick(clickView,properties);
105+
}
106+
} catch (Exception e) {
107+
SALog.printStackTrace(e);
108+
}
109+
}
110+
}
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*
2+
* Created by chenru on 2019/08/27.
3+
* Copyright 2015-2020 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;
19+
20+
21+
import android.text.TextUtils;
22+
import android.util.Log;
23+
24+
import com.facebook.react.bridge.Callback;
25+
import com.facebook.react.bridge.Promise;
26+
import com.facebook.react.bridge.ReactApplicationContext;
27+
import com.facebook.react.bridge.ReactContextBaseJavaModule;
28+
import com.facebook.react.bridge.ReactMethod;
29+
import com.facebook.react.bridge.ReadableArray;
30+
import com.facebook.react.bridge.ReadableMap;
31+
import com.facebook.react.bridge.ReadableNativeMap;
32+
import com.sensorsdata.analytics.android.sdk.SensorsDataAPI;
33+
import com.sensorsdata.analytics.android.sdk.SALog;
34+
import com.sensorsdata.analytics.RNAgent;
35+
import com.sensorsdata.analytics.utils.RNUtils;
36+
import com.sensorsdata.analytics.utils.RNViewUtils;
37+
38+
import org.json.JSONObject;
39+
40+
import java.util.HashSet;
41+
42+
43+
/**
44+
* Created by yang on 2017/4/5
45+
* <p>
46+
* 参数类型在@ReactMethod注明的方法中,会被直接映射到它们对应的JavaScript类型
47+
* String -> String
48+
* ReadableMap -> Object
49+
* Boolean -> Bool
50+
* Integer -> Number
51+
* Double -> Number
52+
* Float -> Number
53+
* Callback -> function
54+
* ReadableArray -> Array
55+
*/
56+
57+
public class RNSensorsDataModule extends ReactContextBaseJavaModule {
58+
59+
public RNSensorsDataModule(ReactApplicationContext reactContext) {
60+
super(reactContext);
61+
}
62+
63+
private static final String MODULE_NAME = "RNSensorsDataModule";
64+
private static final String TAG = "SA.RNSensorsDataModule";
65+
66+
/**
67+
* 返回一个字符串名字,这个名字在 JavaScript (RN)端标记这个模块。
68+
*/
69+
@Override
70+
public String getName() {
71+
return MODULE_NAME;
72+
}
73+
74+
@ReactMethod
75+
public void trackViewClick(int viewId) {
76+
//关闭 AutoTrack
77+
if (!SensorsDataAPI.sharedInstance().isAutoTrackEnabled()) {
78+
return;
79+
}
80+
//$AppClick 被过滤
81+
if (SensorsDataAPI.sharedInstance().isAutoTrackEventTypeIgnored(SensorsDataAPI.AutoTrackEventType.APP_CLICK)) {
82+
return;
83+
}
84+
85+
RNAgent.trackViewClick(viewId);
86+
}
87+
88+
@ReactMethod
89+
public void trackViewScreen(ReadableMap params) {
90+
try{
91+
if (params != null) {
92+
JSONObject jsonParams = RNUtils.convertToJSONObject(params);
93+
JSONObject properties = null;
94+
if(jsonParams.has("sensorsdataparams")){
95+
properties = jsonParams.optJSONObject("sensorsdataparams");
96+
}
97+
String url = null;
98+
if(jsonParams.has("sensorsdataurl")){
99+
url = jsonParams.getString("sensorsdataurl");
100+
}
101+
if(url == null){
102+
return;
103+
}
104+
RNAgent.trackViewScreen(url, properties, true);
105+
}
106+
}catch(Exception e){
107+
SALog.printStackTrace(e);
108+
}
109+
}
110+
}
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+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.sensorsdata.analytics.utils;
2+
3+
import android.view.View;
4+
import com.facebook.react.bridge.ReadableMap;
5+
import com.facebook.react.bridge.ReadableNativeMap;
6+
import com.sensorsdata.analytics.android.sdk.SensorsDataAPI;
7+
import com.sensorsdata.analytics.android.sdk.SALog;
8+
import org.json.JSONObject;
9+
10+
11+
public class RNUtils {
12+
/**
13+
* ReadableMap 转换成 JSONObject
14+
*/
15+
public static JSONObject convertToJSONObject(ReadableMap properties) {
16+
if (properties == null) {
17+
return null;
18+
}
19+
20+
JSONObject json = null;
21+
ReadableNativeMap nativeMap = null;
22+
try {
23+
nativeMap = (ReadableNativeMap) properties;
24+
json = new JSONObject(properties.toString()).getJSONObject("NativeMap");
25+
} catch (Exception e) {
26+
SALog.printStackTrace(e);
27+
String superName = nativeMap.getClass().getSuperclass().getSimpleName();
28+
try {
29+
json = new JSONObject(properties.toString()).getJSONObject(superName);
30+
} catch (Exception e1) {
31+
SALog.printStackTrace(e1);
32+
}
33+
}
34+
return json;
35+
}
36+
}

0 commit comments

Comments
 (0)