Skip to content

Commit

Permalink
提交 Android 少提交代码
Browse files Browse the repository at this point in the history
  • Loading branch information
chenru committed May 14, 2020
1 parent d2355b3 commit 37308d1
Show file tree
Hide file tree
Showing 5 changed files with 514 additions and 0 deletions.
110 changes: 110 additions & 0 deletions android/src/main/java/com/sensorsdata/analytics/RNAgent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package com.sensorsdata.analytics;

import android.view.MotionEvent;
import android.view.MotionEvent.*;
import android.view.View;
import android.view.ViewGroup;
import com.facebook.react.bridge.ReadableMap;
import com.sensorsdata.analytics.RNSensorsAnalyticsModule;
import com.sensorsdata.analytics.utils.RNViewUtils;

import com.facebook.react.uimanager.JSTouchDispatcher;
import com.facebook.react.uimanager.events.EventDispatcher;
import com.sensorsdata.analytics.android.sdk.SALog;
import com.sensorsdata.analytics.android.sdk.SensorsDataAPI;
import com.sensorsdata.analytics.android.sdk.util.SensorsDataUtils;
import com.sensorsdata.analytics.android.sdk.SensorsDataAutoTrackHelper;
import com.sensorsdata.analytics.utils.RNTouchTargetHelper;

import java.lang.reflect.Field;
import java.util.WeakHashMap;
import java.util.HashMap;
import org.json.JSONObject;

public class RNAgent {
private static final WeakHashMap jsTouchDispatcherViewGroupWeakHashMap = new WeakHashMap();

public static void handleTouchEvent(
JSTouchDispatcher jsTouchDispatcher, MotionEvent event, EventDispatcher eventDispatcher) {

if (event.getAction() == MotionEvent.ACTION_DOWN) { // ActionDown
ViewGroup viewGroup = (ViewGroup)jsTouchDispatcherViewGroupWeakHashMap.get(jsTouchDispatcher);
if (viewGroup == null) {
try {
Field viewGroupField = jsTouchDispatcher.getClass().getDeclaredField("mRootViewGroup");
viewGroupField.setAccessible(true);
viewGroup = (ViewGroup) viewGroupField.get(jsTouchDispatcher);
jsTouchDispatcherViewGroupWeakHashMap.put(jsTouchDispatcher, viewGroup);
} catch (Exception e) {
SALog.printStackTrace(e);
}
}
if (viewGroup != null) {
View nativeTargetView =
RNTouchTargetHelper.findTouchTargetView(
new float[] {event.getX(), event.getY()}, viewGroup);
if (nativeTargetView != null) {
View reactTargetView = RNTouchTargetHelper.findClosestReactAncestor(nativeTargetView);
if (reactTargetView != null) {
nativeTargetView = reactTargetView;
}
}
if (nativeTargetView != null) {
RNViewUtils.setOnTouchView(nativeTargetView);
}
}
}
}

public static void trackViewScreen(String url, JSONObject properties, boolean isAuto){
try{
String screenName = url;
if(properties == null){
properties = new JSONObject();
}
if(properties.has("$screen_name")){
screenName = properties.getString("$screen_name");
}
String title = screenName;
if(properties.has("$title")){
title = properties.getString("$title");
}
if(screenName != null){
properties.put("$screen_name",screenName);
}
if(title != null){
properties.put("$title",title);
}
RNViewUtils.saveScreenAndTitle(screenName,title);
//关闭 AutoTrack
if (isAuto && !SensorsDataAPI.sharedInstance().isAutoTrackEnabled()) {
return;
}
//$AppViewScreen 被过滤
if (isAuto && SensorsDataAPI.sharedInstance().isAutoTrackEventTypeIgnored(SensorsDataAPI.AutoTrackEventType.APP_VIEW_SCREEN)) {
return;
}
SensorsDataAPI.sharedInstance().trackViewScreen(url, properties);
}catch(Exception e){
SALog.printStackTrace(e);
}
}

public static void trackViewClick(int viewId){
try {
View clickView = RNViewUtils.getTouchViewByTag(viewId);
if (clickView != null) {
JSONObject properties = new JSONObject();
if(RNViewUtils.getTitle() != null){
properties.put("$title",RNViewUtils.getTitle());
}
if(RNViewUtils.getScreenName() != null){
properties.put("$screen_name",RNViewUtils.getScreenName());
}
SensorsDataAPI.sharedInstance().trackViewAppClick(clickView,properties);
}
} catch (Exception e) {
SALog.printStackTrace(e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* Created by chenru on 2019/08/27.
* Copyright 2015-2020 Sensors Data Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.sensorsdata.analytics;


import android.text.TextUtils;
import android.util.Log;

import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableNativeMap;
import com.sensorsdata.analytics.android.sdk.SensorsDataAPI;
import com.sensorsdata.analytics.android.sdk.SALog;
import com.sensorsdata.analytics.RNAgent;
import com.sensorsdata.analytics.utils.RNUtils;
import com.sensorsdata.analytics.utils.RNViewUtils;

import org.json.JSONObject;

import java.util.HashSet;


/**
* Created by yang on 2017/4/5
* <p>
* 参数类型在@ReactMethod注明的方法中,会被直接映射到它们对应的JavaScript类型
* String -> String
* ReadableMap -> Object
* Boolean -> Bool
* Integer -> Number
* Double -> Number
* Float -> Number
* Callback -> function
* ReadableArray -> Array
*/

public class RNSensorsDataModule extends ReactContextBaseJavaModule {

public RNSensorsDataModule(ReactApplicationContext reactContext) {
super(reactContext);
}

private static final String MODULE_NAME = "RNSensorsDataModule";
private static final String TAG = "SA.RNSensorsDataModule";

/**
* 返回一个字符串名字,这个名字在 JavaScript (RN)端标记这个模块。
*/
@Override
public String getName() {
return MODULE_NAME;
}

@ReactMethod
public void trackViewClick(int viewId) {
//关闭 AutoTrack
if (!SensorsDataAPI.sharedInstance().isAutoTrackEnabled()) {
return;
}
//$AppClick 被过滤
if (SensorsDataAPI.sharedInstance().isAutoTrackEventTypeIgnored(SensorsDataAPI.AutoTrackEventType.APP_CLICK)) {
return;
}

RNAgent.trackViewClick(viewId);
}

@ReactMethod
public void trackViewScreen(ReadableMap params) {
try{
if (params != null) {
JSONObject jsonParams = RNUtils.convertToJSONObject(params);
JSONObject properties = null;
if(jsonParams.has("sensorsdataparams")){
properties = jsonParams.optJSONObject("sensorsdataparams");
}
String url = null;
if(jsonParams.has("sensorsdataurl")){
url = jsonParams.getString("sensorsdataurl");
}
if(url == null){
return;
}
RNAgent.trackViewScreen(url, properties, true);
}
}catch(Exception e){
SALog.printStackTrace(e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
package com.sensorsdata.analytics.utils;

import android.graphics.Matrix;
import android.graphics.PointF;
import android.graphics.Rect;
import android.view.View;
import android.view.ViewGroup;
import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
import com.facebook.react.bridge.UiThreadUtil;
import com.facebook.react.touch.ReactHitSlopView;
import com.facebook.react.uimanager.PointerEvents;
import com.facebook.react.uimanager.ReactCompoundView;
import com.facebook.react.uimanager.ReactCompoundViewGroup;
import com.facebook.react.uimanager.ReactPointerEventsView;

public class RNTouchTargetHelper {
private static final float[] mEventCoords = new float[2];
private static final Matrix mInverseMatrix = new Matrix();
private static final float[] mMatrixTransformCoords = new float[2];
private static final PointF mTempPoint = new PointF();

public static int findTargetTagForTouch(float eventX, float eventY, ViewGroup viewGroup) {
return findTargetTagAndCoordinatesForTouch(eventX, eventY, viewGroup, mEventCoords);
}

public static int findTargetTagAndCoordinatesForTouch(float eventX, float eventY, ViewGroup viewGroup, float[] viewCoords) {
UiThreadUtil.assertOnUiThread();
int targetTag = viewGroup.getId();
viewCoords[0] = eventX;
viewCoords[1] = eventY;
View nativeTargetView = findTouchTargetView(viewCoords, viewGroup);
if (nativeTargetView == null) {
return targetTag;
}
View reactTargetView = findClosestReactAncestor(nativeTargetView);
if (reactTargetView != null) {
return getTouchTargetForView(reactTargetView, viewCoords[0], viewCoords[1]);
}
return targetTag;
}

public static View findClosestReactAncestor(View view) {
while (view != null && view.getId() <= 0) {
view = (View) view.getParent();
}
return view;
}

public static View findTouchTargetView(float[] eventCoords, ViewGroup viewGroup) {
for (int i = viewGroup.getChildCount() - 1; i >= 0; i--) {
View child = viewGroup.getChildAt(i);
PointF childPoint = mTempPoint;
if (isTransformedTouchPointInView(eventCoords[0], eventCoords[1], viewGroup, child, childPoint)) {
float restoreX = eventCoords[0];
float restoreY = eventCoords[1];
eventCoords[0] = childPoint.x;
eventCoords[1] = childPoint.y;
View targetView = findTouchTargetViewWithPointerEvents(eventCoords, child);
if (targetView != null) {
return targetView;
}
eventCoords[0] = restoreX;
eventCoords[1] = restoreY;
}
}
return viewGroup;
}

private static boolean isTransformedTouchPointInView(float x, float y, ViewGroup parent, View child, PointF outLocalPoint) {
float localX = (((float) parent.getScrollX()) + x) - ((float) child.getLeft());
float localY = (((float) parent.getScrollY()) + y) - ((float) child.getTop());
Matrix matrix = child.getMatrix();
if (!matrix.isIdentity()) {
float[] localXY = mMatrixTransformCoords;
localXY[0] = localX;
localXY[1] = localY;
Matrix inverseMatrix = mInverseMatrix;
matrix.invert(inverseMatrix);
inverseMatrix.mapPoints(localXY);
localX = localXY[0];
localY = localXY[1];
}
if ((child instanceof ReactHitSlopView) && ((ReactHitSlopView) child).getHitSlopRect() != null) {
Rect hitSlopRect = ((ReactHitSlopView) child).getHitSlopRect();
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))) {
return false;
}
outLocalPoint.set(localX, localY);
return true;
} else if (localX < 0.0f || localX >= ((float) (child.getRight() - child.getLeft())) || localY < 0.0f || localY >= ((float) (child.getBottom() - child.getTop()))) {
return false;
} else {
outLocalPoint.set(localX, localY);
return true;
}
}

private static View findTouchTargetViewWithPointerEvents(float[] eventCoords, View view) {
PointerEvents pointerEvents = view instanceof ReactPointerEventsView ? ((ReactPointerEventsView) view).getPointerEvents() : PointerEvents.AUTO;
if (pointerEvents == PointerEvents.NONE) {
return null;
}
if (pointerEvents == PointerEvents.BOX_ONLY) {
return view;
}
if (pointerEvents == PointerEvents.BOX_NONE) {
if (view instanceof ViewGroup) {
View targetView = findTouchTargetView(eventCoords, (ViewGroup) view);
if (targetView != view) {
return targetView;
}
if (!(view instanceof ReactCompoundView) || ((ReactCompoundView) view).reactTagForTouch(eventCoords[0], eventCoords[1]) == view.getId()) {
return null;
}
return view;
}
return null;
} else if (pointerEvents != PointerEvents.AUTO) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("Unknown pointer event type: ");
stringBuilder.append(pointerEvents.toString());
throw new JSApplicationIllegalArgumentException(stringBuilder.toString());
} else if ((!(view instanceof ReactCompoundViewGroup) || !((ReactCompoundViewGroup) view).interceptsTouchEvent(eventCoords[0], eventCoords[1])) && (view instanceof ViewGroup)) {
return findTouchTargetView(eventCoords, (ViewGroup) view);
} else {
return view;
}
}

public static int getTouchTargetForView(View targetView, float eventX, float eventY) {
if (targetView instanceof ReactCompoundView) {
return ((ReactCompoundView) targetView).reactTagForTouch(eventX, eventY);
}
return targetView.getId();
}
}
36 changes: 36 additions & 0 deletions android/src/main/java/com/sensorsdata/analytics/utils/RNUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.sensorsdata.analytics.utils;

import android.view.View;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableNativeMap;
import com.sensorsdata.analytics.android.sdk.SensorsDataAPI;
import com.sensorsdata.analytics.android.sdk.SALog;
import org.json.JSONObject;


public class RNUtils {
/**
* ReadableMap 转换成 JSONObject
*/
public static JSONObject convertToJSONObject(ReadableMap properties) {
if (properties == null) {
return null;
}

JSONObject json = null;
ReadableNativeMap nativeMap = null;
try {
nativeMap = (ReadableNativeMap) properties;
json = new JSONObject(properties.toString()).getJSONObject("NativeMap");
} catch (Exception e) {
SALog.printStackTrace(e);
String superName = nativeMap.getClass().getSuperclass().getSimpleName();
try {
json = new JSONObject(properties.toString()).getJSONObject(superName);
} catch (Exception e1) {
SALog.printStackTrace(e1);
}
}
return json;
}
}
Loading

0 comments on commit 37308d1

Please sign in to comment.