Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.sensorsdata.analytics.android.sdk;

import android.app.Activity;

import org.json.JSONException;
import org.json.JSONObject;

import java.lang.ref.WeakReference;

/**
* author : Handy
* e-mail : [email protected]
* time : 2021/09/07
* desc :
*/
public class FragmentCacheInfo {
private WeakReference<Activity> activityWeakReference;
private final Class<?> fragmentClazz;
private final JSONObject trackProperties;

public FragmentCacheInfo(Activity activity, Object fragment) {
this.activityWeakReference = new WeakReference<>(activity);
this.fragmentClazz = fragment.getClass();
JSONObject trackProperties = null;
if (fragment instanceof ScreenAutoTracker) {
ScreenAutoTracker screenAutoTracker = (ScreenAutoTracker) fragment;
try {
trackProperties = screenAutoTracker.getTrackProperties();
} catch (JSONException e) {
e.printStackTrace();
}
}
this.trackProperties = trackProperties;
}

public Activity getActivity() {
return activityWeakReference == null ? null : activityWeakReference.get();
}

public void setActivity(Activity activity) {
this.activityWeakReference = new WeakReference<>(activity);
}

public Class<?> getFragmentClazz() {
return fragmentClazz;
}

public JSONObject getTrackProperties() {
return trackProperties;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -179,12 +179,12 @@ public static void trackExpandableListViewOnGroupClick(ExpandableListView expand
}
}

// 获取 view 所在的 fragment
Object fragment = AopUtil.getFragmentFromView(expandableListView, activity);
// 获取 view 所在的 fragment缓存信息
FragmentCacheInfo fragmentCacheInfo = AopUtil.getFragmentFromView(expandableListView, activity);

// fragment 忽略
if (fragment != null) {
if (SensorsDataAPI.sharedInstance().isActivityAutoTrackAppClickIgnored(fragment.getClass())) {
if (fragmentCacheInfo != null) {
if (SensorsDataAPI.sharedInstance().isActivityAutoTrackAppClickIgnored(fragmentCacheInfo.getFragmentClazz())) {
return;
}
}
Expand Down Expand Up @@ -235,8 +235,8 @@ public static void trackExpandableListViewOnGroupClick(ExpandableListView expand
}

//fragmentName
if (fragment != null) {
AopUtil.getScreenNameAndTitleFromFragment(properties, fragment, activity);
if (fragmentCacheInfo != null) {
AopUtil.getScreenNameAndTitleFromFragmentCacheInfo(properties, fragmentCacheInfo, activity);
}

// 获取 View 自定义属性
Expand Down Expand Up @@ -300,12 +300,12 @@ public static void trackExpandableListViewOnChildClick(ExpandableListView expand
}
}

// 获取 view 所在的 fragment
Object fragment = AopUtil.getFragmentFromView(expandableListView, activity);
// 获取 view 所在的 fragment缓存信息
FragmentCacheInfo fragmentCacheInfo = AopUtil.getFragmentFromView(expandableListView, activity);

// fragment 忽略
if (fragment != null) {
if (SensorsDataAPI.sharedInstance().isActivityAutoTrackAppClickIgnored(fragment.getClass())) {
if (fragmentCacheInfo != null) {
if (SensorsDataAPI.sharedInstance().isActivityAutoTrackAppClickIgnored(fragmentCacheInfo.getFragmentClazz())) {
return;
}
}
Expand Down Expand Up @@ -378,8 +378,8 @@ public static void trackExpandableListViewOnChildClick(ExpandableListView expand
}

//fragmentName
if (fragment != null) {
AopUtil.getScreenNameAndTitleFromFragment(properties, fragment, activity);
if (fragmentCacheInfo != null) {
AopUtil.getScreenNameAndTitleFromFragmentCacheInfo(properties, fragmentCacheInfo, activity);
}

//获取 View 自定义属性
Expand Down Expand Up @@ -435,12 +435,12 @@ public void run() {
}
SensorsDataUtils.mergeJSONObject(AopUtil.buildTitleAndScreenName(activity), properties);

Object fragment = AopUtil.getFragmentFromView(view, activity);
if (fragment != null) {
if (SensorsDataAPI.sharedInstance().isActivityAutoTrackAppClickIgnored(fragment.getClass())) {
FragmentCacheInfo fragmentCacheInfo = AopUtil.getFragmentFromView(view, activity);
if (fragmentCacheInfo != null) {
if (SensorsDataAPI.sharedInstance().isActivityAutoTrackAppClickIgnored(fragmentCacheInfo.getFragmentClazz())) {
return;
}
AopUtil.getScreenNameAndTitleFromFragment(properties, fragment, activity);
AopUtil.getScreenNameAndTitleFromFragmentCacheInfo(properties, fragmentCacheInfo, activity);
}

viewNode = AopUtil.addViewPathProperties(activity, view, properties);
Expand Down Expand Up @@ -853,12 +853,12 @@ public static void trackRadioGroup(RadioGroup view, int checkedId) {
}
}

// 获取 view 所在的 fragment
Object fragment = AopUtil.getFragmentFromView(view, activity);
// 获取 view 所在的 fragment缓存信息
FragmentCacheInfo fragmentCacheInfo = AopUtil.getFragmentFromView(view, activity);

// fragment 忽略
if (fragment != null) {
if (SensorsDataAPI.sharedInstance().isActivityAutoTrackAppClickIgnored(fragment.getClass())) {
if (fragmentCacheInfo != null) {
if (SensorsDataAPI.sharedInstance().isActivityAutoTrackAppClickIgnored(fragmentCacheInfo.getFragmentClazz())) {
return;
}
}
Expand Down Expand Up @@ -908,8 +908,8 @@ public static void trackRadioGroup(RadioGroup view, int checkedId) {
}

//fragmentName
if (fragment != null) {
AopUtil.getScreenNameAndTitleFromFragment(properties, fragment, activity);
if (fragmentCacheInfo != null) {
AopUtil.getScreenNameAndTitleFromFragmentCacheInfo(properties, fragmentCacheInfo, activity);
}

//获取 View 自定义属性
Expand Down Expand Up @@ -1125,12 +1125,12 @@ public static void trackListView(AdapterView<?> adapterView, View view, int posi
}
}

// 获取 view 所在的 fragment
Object fragment = AopUtil.getFragmentFromView(adapterView, activity);
// 获取 view 所在的 fragment缓存信息
FragmentCacheInfo fragmentCacheInfo = AopUtil.getFragmentFromView(adapterView, activity);

// fragment 忽略
if (fragment != null) {
if (SensorsDataAPI.sharedInstance().isActivityAutoTrackAppClickIgnored(fragment.getClass())) {
if (fragmentCacheInfo != null) {
if (SensorsDataAPI.sharedInstance().isActivityAutoTrackAppClickIgnored(fragmentCacheInfo.getFragmentClazz())) {
return;
}
}
Expand Down Expand Up @@ -1210,8 +1210,8 @@ public static void trackListView(AdapterView<?> adapterView, View view, int posi
}

//fragmentName
if (fragment != null) {
AopUtil.getScreenNameAndTitleFromFragment(properties, fragment, activity);
if (fragmentCacheInfo != null) {
AopUtil.getScreenNameAndTitleFromFragmentCacheInfo(properties, fragmentCacheInfo, activity);
}

//获取 View 自定义属性
Expand Down Expand Up @@ -1292,12 +1292,12 @@ public static void trackViewOnClick(View view, boolean isFromUser) {
}
}

// 获取 view 所在的 fragment
Object fragment = AopUtil.getFragmentFromView(view, activity);
// 获取 view 所在的 fragment缓存信息
FragmentCacheInfo fragmentCacheInfo = AopUtil.getFragmentFromView(view, activity);

// fragment 忽略
if (fragment != null) {
if (SensorsDataAPI.sharedInstance().isActivityAutoTrackAppClickIgnored(fragment.getClass())) {
if (fragmentCacheInfo != null) {
if (SensorsDataAPI.sharedInstance().isActivityAutoTrackAppClickIgnored(fragmentCacheInfo.getFragmentClazz())) {
return;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import android.widget.ToggleButton;

import com.sensorsdata.analytics.android.sdk.AopConstants;
import com.sensorsdata.analytics.android.sdk.FragmentCacheInfo;
import com.sensorsdata.analytics.android.sdk.R;
import com.sensorsdata.analytics.android.sdk.SALog;
import com.sensorsdata.analytics.android.sdk.ScreenAutoTracker;
Expand All @@ -61,7 +62,7 @@

public class AopUtil {

private static LruCache<String, Object> sLruCache;
private static LruCache<String, FragmentCacheInfo> sLruCache;

// 采集 viewType 忽略以下包内 view 直接返回对应的基础控件 viewType
private static ArrayList<String> sOSViewPackage = new ArrayList<String>() {{
Expand Down Expand Up @@ -284,6 +285,68 @@ public static void getScreenNameAndTitleFromFragment(JSONObject properties, Obje
}
}

/**
* 尝试读取页面 title
*
* @param properties JSONObject
* @param fragmentCacheInfo FragmentCacheInfo
* @param activity Activity
*/
public static void getScreenNameAndTitleFromFragmentCacheInfo(JSONObject properties, FragmentCacheInfo fragmentCacheInfo, Activity activity) {
try {
String screenName = null;
String title = null;
JSONObject trackProperties = fragmentCacheInfo.getTrackProperties();
if (trackProperties != null) {
if (trackProperties.has(AopConstants.SCREEN_NAME)) {
screenName = trackProperties.optString(AopConstants.SCREEN_NAME);
}

if (trackProperties.has(AopConstants.TITLE)) {
title = trackProperties.optString(AopConstants.TITLE);
}
SensorsDataUtils.mergeJSONObject(trackProperties, properties);
}

Class<?> fragmentClazz = fragmentCacheInfo.getFragmentClazz();
if (TextUtils.isEmpty(title) && fragmentClazz.isAnnotationPresent(SensorsDataFragmentTitle.class)) {
SensorsDataFragmentTitle sensorsDataFragmentTitle = fragmentClazz.getAnnotation(SensorsDataFragmentTitle.class);
if (sensorsDataFragmentTitle != null) {
title = sensorsDataFragmentTitle.title();
}
}

boolean isTitleNull = TextUtils.isEmpty(title);
boolean isScreenNameNull = TextUtils.isEmpty(screenName);
if (isTitleNull || isScreenNameNull) {
if (activity == null) {
activity = fragmentCacheInfo.getActivity();
}
if (activity != null) {
if (isTitleNull) {
title = SensorsDataUtils.getActivityTitle(activity);
}

if (isScreenNameNull) {
screenName = fragmentClazz.getCanonicalName();
screenName = String.format(Locale.CHINA, "%s|%s", activity.getClass().getCanonicalName(), screenName);
}
}
}

if (!TextUtils.isEmpty(title)) {
properties.put(AopConstants.TITLE, title);
}

if (TextUtils.isEmpty(screenName)) {
screenName = fragmentClazz.getCanonicalName();
}
properties.put("$screen_name", screenName);
} catch (Exception ex) {
SALog.printStackTrace(ex);
}
}

/**
* 根据 Fragment 获取对应的 Activity
*
Expand Down Expand Up @@ -675,9 +738,9 @@ public static boolean injectClickInfo(View view, JSONObject properties, boolean
}

//fragmentName
Object fragment = AopUtil.getFragmentFromView(view, activity);
if (fragment != null) {
AopUtil.getScreenNameAndTitleFromFragment(eventJson, fragment, activity);
FragmentCacheInfo fragmentCacheInfo = AopUtil.getFragmentFromView(view, activity);
if (fragmentCacheInfo != null) {
AopUtil.getScreenNameAndTitleFromFragmentCacheInfo(eventJson, fragmentCacheInfo, activity);
}
//3.获取 View 自定义属性
JSONObject p = (JSONObject) view.getTag(R.id.sensors_analytics_tag_view_properties);
Expand All @@ -699,19 +762,19 @@ public static boolean injectClickInfo(View view, JSONObject properties, boolean
* @param view 点击的 view
* @return object 这里是 fragment 实例对象
*/
public static Object getFragmentFromView(View view) {
public static FragmentCacheInfo getFragmentFromView(View view) {
return getFragmentFromView(view, null);
}

/**
* 获取点击 view 的 fragment 对象
* 获取点击 view 的 fragmentCacheInfo 对象
*
* @param view 点击的 view
* @param activity Activity
* @return object 这里是 fragment 实例对象
* @return object 这里是 fragmentCacheInfo 实例对象
*/
@SuppressLint("NewApi")
public static Object getFragmentFromView(View view, Activity activity) {
public static FragmentCacheInfo getFragmentFromView(View view, Activity activity) {
try {
if (view != null) {
String fragmentName = (String) view.getTag(R.id.sensors_analytics_tag_view_fragment_name);
Expand Down Expand Up @@ -740,13 +803,15 @@ public static Object getFragmentFromView(View view, Activity activity) {
if (sLruCache == null) {
sLruCache = new LruCache<>(10);
}
Object object = sLruCache.get(fragmentName);
if (object != null) {
return object;
FragmentCacheInfo cacheInfo = sLruCache.get(fragmentName);
if (cacheInfo != null) {
cacheInfo.setActivity(activity);
return cacheInfo;
}
object = Class.forName(fragmentName).newInstance();
sLruCache.put(fragmentName, object);
return object;
Object object = Class.forName(fragmentName).newInstance();
cacheInfo = new FragmentCacheInfo(activity, object);
sLruCache.put(fragmentName, cacheInfo);
return cacheInfo;
}
}
} catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import android.widget.ToggleButton;

import com.sensorsdata.analytics.android.sdk.AppStateManager;
import com.sensorsdata.analytics.android.sdk.FragmentCacheInfo;
import com.sensorsdata.analytics.android.sdk.SALog;
import com.sensorsdata.analytics.android.sdk.visual.model.ViewNode;
import com.sensorsdata.analytics.android.sdk.visual.util.VisualUtil;
Expand Down Expand Up @@ -162,8 +163,8 @@ private static String getCanonicalName(Class clazz) {
* view 是否为 Fragment 中的顶层 View
*/
private static Object instanceOfFragmentRootView(View parentView, View childView) {
Object parentFragment = AopUtil.getFragmentFromView(parentView);
Object childFragment = AopUtil.getFragmentFromView(childView);
FragmentCacheInfo parentFragment = AopUtil.getFragmentFromView(parentView);
FragmentCacheInfo childFragment = AopUtil.getFragmentFromView(childView);
if (parentFragment == null && childFragment != null) {
return childFragment;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@

import com.sensorsdata.analytics.android.sdk.AppStateManager;
import com.sensorsdata.analytics.android.sdk.AopConstants;
import com.sensorsdata.analytics.android.sdk.FragmentCacheInfo;
import com.sensorsdata.analytics.android.sdk.SALog;
import com.sensorsdata.analytics.android.sdk.util.AopUtil;
import com.sensorsdata.analytics.android.sdk.util.ReflectUtil;
Expand Down Expand Up @@ -138,9 +139,9 @@ public static JSONObject getScreenNameAndTitle(View view, SnapInfo info) {
}
if (activity != null && activity.getWindow() != null && activity.getWindow().isActive()) {
object = new JSONObject();
Object fragment = AopUtil.getFragmentFromView(view, activity);
if (fragment != null) {
AopUtil.getScreenNameAndTitleFromFragment(object, fragment, activity);
FragmentCacheInfo fragmentCacheInfo = AopUtil.getFragmentFromView(view, activity);
if (fragmentCacheInfo != null) {
AopUtil.getScreenNameAndTitleFromFragmentCacheInfo(object, fragmentCacheInfo, activity);
if (info != null && !info.hasFragment) {
info.hasFragment = true;
}
Expand Down