diff --git a/SensorsAnalyticsSDK/build.gradle b/SensorsAnalyticsSDK/build.gradle index e0bea680..76f691b3 100644 --- a/SensorsAnalyticsSDK/build.gradle +++ b/SensorsAnalyticsSDK/build.gradle @@ -3,7 +3,7 @@ apply plugin: 'com.android.library' apply plugin: 'com.github.dcendents.android-maven' apply plugin: 'com.jfrog.bintray' -version = "3.0.4" +version = "3.0.5" android { compileSdkVersion 23 diff --git a/SensorsAnalyticsSDK/src/main/java/com/sensorsdata/analytics/android/sdk/SAConfigOptions.java b/SensorsAnalyticsSDK/src/main/java/com/sensorsdata/analytics/android/sdk/SAConfigOptions.java new file mode 100644 index 00000000..8e026b2a --- /dev/null +++ b/SensorsAnalyticsSDK/src/main/java/com/sensorsdata/analytics/android/sdk/SAConfigOptions.java @@ -0,0 +1,57 @@ +/**Created by dengshiwei on 2019/03/11. + * Copyright © 2015-2019 Sensors Data Inc. All rights reserved. */ + +package com.sensorsdata.analytics.android.sdk; + +public final class SAConfigOptions { + /** + * 请求配置地址,默认从 ServerUrl 解析 + */ + private String remoteConfigUrl; + + /** + * 数据上报服务器地址 + */ + private String serverUrl; + + /** + * 私有构造函数 + */ + private SAConfigOptions(){} + + /** + * 获取 SAOptionsConfig 实例 + * @param serverUrl,数据上报服务器地址 + */ + public SAConfigOptions(String serverUrl) { + this.serverUrl = serverUrl; + } + + /** + * 设置远程配置请求地址 + * @param remoteConfigUrl,远程配置请求地址 + * @return SAOptionsConfig + */ + public SAConfigOptions setRemoteConfigUrl(String remoteConfigUrl) { + this.remoteConfigUrl = remoteConfigUrl; + return this; + } + + /** + * 设置数据上报地址 + * @param serverUrl,数据上报地址 + * @return SAOptionsConfig + */ + public SAConfigOptions setServerUrl(String serverUrl) { + this.serverUrl = serverUrl; + return this; + } + + String getRemoteConfigUrl() { + return remoteConfigUrl; + } + + String getServerUrl() { + return serverUrl; + } +} diff --git a/SensorsAnalyticsSDK/src/main/java/com/sensorsdata/analytics/android/sdk/SensorsDataAPI.java b/SensorsAnalyticsSDK/src/main/java/com/sensorsdata/analytics/android/sdk/SensorsDataAPI.java index ce19716c..bc2e7cb9 100644 --- a/SensorsAnalyticsSDK/src/main/java/com/sensorsdata/analytics/android/sdk/SensorsDataAPI.java +++ b/SensorsAnalyticsSDK/src/main/java/com/sensorsdata/analytics/android/sdk/SensorsDataAPI.java @@ -430,7 +430,7 @@ public static SensorsDataAPI sharedInstance(Context context) { */ @Deprecated public static SensorsDataAPI sharedInstance(Context context, String serverURL, DebugMode debugMode) { - return getInstance(context,serverURL,debugMode); + return getInstance(context, serverURL, debugMode); } /** @@ -441,10 +441,21 @@ public static SensorsDataAPI sharedInstance(Context context, String serverURL, D * @return SensorsDataAPI单例 */ public static SensorsDataAPI sharedInstance(Context context, String serverURL) { - return getInstance(context,serverURL,DebugMode.DEBUG_OFF); + return getInstance(context, serverURL, DebugMode.DEBUG_OFF); } - private static SensorsDataAPI getInstance(Context context, String serverURL, DebugMode debugMode){ + /** + * 初始化并获取 SensorsDataAPI 单例 + * @param context App 的 Context + * @param saConfigOptions SDK 的配置项 + * @return SensorsDataAPI 单例 + */ + public static SensorsDataAPI sharedInstance(Context context, SAConfigOptions saConfigOptions) { + mSAConfigOptions = saConfigOptions; + return getInstance(context, saConfigOptions.getServerUrl(), DebugMode.DEBUG_OFF); + } + + private static SensorsDataAPI getInstance(Context context, String serverURL, DebugMode debugMode) { if (null == context) { return new SensorsDataAPIEmptyImplementation(); } @@ -535,21 +546,32 @@ public void run() { return; } - URL url = null; + URL url; String configUrl = null; - int pathPrefix = mServerUrl.lastIndexOf("/"); - if (pathPrefix != -1) { - configUrl = mServerUrl.substring(0, pathPrefix); + if (mSAConfigOptions != null && !TextUtils.isEmpty(mSAConfigOptions.getRemoteConfigUrl())) { + configUrl = mSAConfigOptions.getRemoteConfigUrl(); + } else { + int pathPrefix = mServerUrl.lastIndexOf("/"); + if (pathPrefix != -1) { + configUrl = mServerUrl.substring(0, pathPrefix); + configUrl = configUrl + "/config/Android.conf"; + } + } + + if (!TextUtils.isEmpty(configUrl)) { String configVersion = null; if (mSDKRemoteConfig != null) { configVersion = mSDKRemoteConfig.getV(); } - configUrl = configUrl + "/config/Android.conf"; - - if (configVersion != null) { - configUrl = configUrl + "?v=" + configVersion; + if (!TextUtils.isEmpty(configVersion)) { + if (configUrl.contains("?")) { + configUrl = configUrl + "&v=" + configVersion; + } else { + configUrl = configUrl + "?v=" + configVersion; + } } + SALog.d(TAG, "Android remote config url:" + configUrl); } url = new URL(configUrl); @@ -575,8 +597,11 @@ public void run() { while ((data = bufferedReader.readLine()) != null) { result.append(data); } - SensorsDataSDKRemoteConfig sdkRemoteConfig = SensorsDataUtils.toSDKRemoteConfig(result.toString()); - setSDKRemoteConfig(sdkRemoteConfig, false); + data = result.toString(); + if (!TextUtils.isEmpty(data)) { + SensorsDataSDKRemoteConfig sdkRemoteConfig = SensorsDataUtils.toSDKRemoteConfig(data); + setSDKRemoteConfig(sdkRemoteConfig, false); + } } } catch (Exception e) { com.sensorsdata.analytics.android.sdk.SALog.printStackTrace(e); @@ -835,7 +860,7 @@ public void setFlushBulkSize(int flushBulkSize) { */ @Override public void setSessionIntervalTime(int sessionIntervalTime) { - if(DbAdapter.getInstance() == null){ + if (DbAdapter.getInstance() == null) { SALog.i(TAG, "The static method sharedInstance(context, serverURL, debugMode) should be called before calling sharedInstance()"); return; } @@ -859,7 +884,7 @@ public void setSessionIntervalTime(int sessionIntervalTime) { */ @Override public int getSessionIntervalTime() { - if(DbAdapter.getInstance() == null){ + if (DbAdapter.getInstance() == null) { SALog.i(TAG, "The static method sharedInstance(context, serverURL, debugMode) should be called before calling sharedInstance()"); return 30 * 1000; } @@ -879,8 +904,8 @@ public void setGPSLocation(double latitude, double longitude) { mGPSLocation = new SensorsDataGPSLocation(); } - mGPSLocation.setLatitude((long)(latitude * Math.pow(10, 6))); - mGPSLocation.setLongitude((long)(longitude * Math.pow(10, 6))); + mGPSLocation.setLatitude((long) (latitude * Math.pow(10, 6))); + mGPSLocation.setLongitude((long) (longitude * Math.pow(10, 6))); } catch (Exception e) { com.sensorsdata.analytics.android.sdk.SALog.printStackTrace(e); } @@ -1083,7 +1108,8 @@ public void trackAppCrash() { public void process(SensorsDataAPI m); } - /* package */ static void allInstances(InstanceProcessor processor) { + /* package */ + static void allInstances(InstanceProcessor processor) { synchronized (sInstanceMap) { for (final SensorsDataAPI instance : sInstanceMap.values()) { processor.process(instance); @@ -1291,7 +1317,7 @@ public void resumeAutoTrackActivities(List> activitiesList) { return; } - if (mAutoTrackIgnoredActivities == null){ + if (mAutoTrackIgnoredActivities == null) { mAutoTrackIgnoredActivities = new ArrayList<>(); } @@ -1475,7 +1501,7 @@ public boolean isFragmentAutoTrackAppViewScreen(Class fragment) { if (fragment.getClass().getAnnotation(SensorsDataIgnoreTrackAppViewScreen.class) != null) { return false; } - } catch (Exception e){ + } catch (Exception e) { com.sensorsdata.analytics.android.sdk.SALog.printStackTrace(e); } @@ -1538,7 +1564,7 @@ public void ignoreAutoTrackEventType(List eventTypeList) { return; } - for (AutoTrackEventType eventType: eventTypeList) { + for (AutoTrackEventType eventType : eventTypeList) { if (eventType != null && mAutoTrackEventTypeList.contains(eventType)) { mAutoTrackEventTypeList.remove(eventType); } @@ -1560,7 +1586,7 @@ public boolean isAutoTrackEventTypeIgnored(AutoTrackEventType eventType) { return mSDKRemoteConfig.isAutoTrackEventTypeIgnored(eventType); } } - if (eventType != null && !mAutoTrackEventTypeList.contains(eventType)) { + if (eventType != null && !mAutoTrackEventTypeList.contains(eventType)) { return true; } return false; @@ -1647,7 +1673,7 @@ public void setViewID(Object alertDialog, String viewID) { return; } - Window window = (Window)getWindowMethod.invoke(alertDialog); + Window window = (Window) getWindowMethod.invoke(alertDialog); if (window != null) { window.getDecorView().setTag(R.id.sensors_analytics_tag_view_id, viewID); } @@ -1708,7 +1734,7 @@ public void ignoreView(View view) { @Override public void ignoreView(View view, boolean ignore) { if (view != null) { - view.setTag(R.id.sensors_analytics_tag_view_ignored, ignore ? "1": "0"); + view.setTag(R.id.sensors_analytics_tag_view_ignored, ignore ? "1" : "0"); } } @@ -1803,7 +1829,7 @@ public void addHeatMapActivities(List> activitiesList) { return; } - for (Class activity: activitiesList) { + for (Class activity : activitiesList) { if (activity != null) { if (!mHeatMapActivities.contains(activity.hashCode())) { mHeatMapActivities.add(activity.hashCode()); @@ -1957,7 +1983,7 @@ public void login(final String loginId) { * @param properties 用户登录属性 */ @Override - public void login(final String loginId , final JSONObject properties) { + public void login(final String loginId, final JSONObject properties) { try { assertDistinctId(loginId); } catch (Exception e) { @@ -2561,9 +2587,9 @@ public void trackViewScreen(final Object fragment) { //ignored } - if (!(supportFragmentClass !=null && supportFragmentClass.isInstance(fragment)) && - !(appFragmentClass !=null && appFragmentClass.isInstance(fragment)) && - !(androidXFragmentClass !=null && androidXFragmentClass.isInstance(fragment))) { + if (!(supportFragmentClass != null && supportFragmentClass.isInstance(fragment)) && + !(appFragmentClass != null && appFragmentClass.isInstance(fragment)) && + !(androidXFragmentClass != null && androidXFragmentClass.isInstance(fragment))) { return; } @@ -2588,7 +2614,7 @@ public void run() { try { Method getActivityMethod = fragment.getClass().getMethod("getActivity"); if (getActivityMethod != null) { - activity = (Activity)getActivityMethod.invoke(fragment); + activity = (Activity) getActivityMethod.invoke(fragment); } } catch (Exception e) { //ignored @@ -2602,7 +2628,7 @@ public void run() { } if (!TextUtils.isEmpty(title)) { - properties.put(AopConstants.TITLE,title); + properties.put(AopConstants.TITLE, title); } properties.put("$screen_name", screenName); @@ -2840,7 +2866,7 @@ public void run() { * @param properties 属性列表 */ @Override - public void profileSetOnce(final JSONObject properties) { + public void profileSetOnce(final JSONObject properties) { mTrackTaskManager.addTrackEventTask(new Runnable() { @Override public void run() { @@ -3527,7 +3553,7 @@ private void trackEvent(final EventType eventType, final String eventName, final libProperties.put("$lib_detail", libDetail); //防止用户自定义事件以及公共属性可能会加$device_id属性,导致覆盖sdk原始的$device_id属性值 - if (sendProperties.has("$device_id")){//由于profileSet等类型事件没有$device_id属性,故加此判断 + if (sendProperties.has("$device_id")) {//由于profileSet等类型事件没有$device_id属性,故加此判断 if (mDeviceInfo.containsKey("$device_id")) { sendProperties.put("$device_id", mDeviceInfo.get("$device_id")); } @@ -3569,7 +3595,7 @@ public void resumeTrackTaskThread() { /** * 点击图是否进行检查 SSL * @return boolean 是否进行检查 */ - protected boolean isSSLCertificateChecking(){ + protected boolean isSSLCertificateChecking() { return mIsSSLCertificateChecking; } @@ -3661,7 +3687,7 @@ public void profilePushId(String propertyKey, String pushId) { try { assertKey(propertyKey); if (TextUtils.isEmpty(pushId)) { - SALog.d(TAG,"pushId is empty"); + SALog.d(TAG, "pushId is empty"); return; } String distinctId = getLoginId(); @@ -3680,12 +3706,11 @@ public void profilePushId(String propertyKey, String pushId) { } } - // 可视化埋点功能最低API版本 static final int VTRACK_SUPPORTED_MIN_API = 16; // SDK版本 - static final String VERSION = "3.0.4"; + static final String VERSION = "3.0.5"; // 此属性插件会进行访问,谨慎删除。当前 SDK 版本所需插件最低版本号,设为空,意为没有任何限制 static final String MIN_PLUGIN_VERSION = "3.0.0"; @@ -3704,9 +3729,11 @@ public void profilePushId(String propertyKey, String pushId) { private static SensorsDataGPSLocation mGPSLocation; // Configures - /* SensorsAnalytics 地址 */ + /* SensorsAnalytics 地址 */ private String mServerUrl; private String mOriginServerUrl; + /* 远程配置 */ + private static SAConfigOptions mSAConfigOptions; /* Debug模式选项 */ private DebugMode mDebugMode = DebugMode.DEBUG_OFF; /* Flush时间间隔 */ diff --git a/SensorsAnalyticsSDK/src/main/java/com/sensorsdata/analytics/android/sdk/SensorsDataActivityLifecycleCallbacks.java b/SensorsAnalyticsSDK/src/main/java/com/sensorsdata/analytics/android/sdk/SensorsDataActivityLifecycleCallbacks.java index 07a9e88b..7511eaf2 100644 --- a/SensorsAnalyticsSDK/src/main/java/com/sensorsdata/analytics/android/sdk/SensorsDataActivityLifecycleCallbacks.java +++ b/SensorsAnalyticsSDK/src/main/java/com/sensorsdata/analytics/android/sdk/SensorsDataActivityLifecycleCallbacks.java @@ -116,14 +116,6 @@ public void onActivityCreated(Activity activity, Bundle bundle) { @Override public void onActivityStarted(Activity activity) { try { - SensorsDataUtils.getScreenNameAndTitleFromActivity(activityProperty, activity); - SensorsDataUtils.mergeJSONObject(activityProperty, endDataProperty); - boolean sessionTimeOut = System.currentTimeMillis() - mDbAdapter.getAppPausedTime() > mDbAdapter.getSessionIntervalTime(); - SALog.d(TAG, "SessionTimeOut:" + sessionTimeOut); - if (sessionTimeOut && !mDbAdapter.getAppEndState()) { - trackAppEnd(); - } - isAutoTrackEnabled = mSensorsDataInstance.isAutoTrackEnabled(); if (!isAutoTrackEnabled) { if (mFirstDay.get() == null) { @@ -132,12 +124,22 @@ public void onActivityStarted(Activity activity) { } mFirstDay.commit(mIsFirstDayDateFormat.format(System.currentTimeMillis())); } + //先从缓存中读取 SDKConfig + mSensorsDataInstance.applySDKConfigFromCache(); //每次启动 App,重新拉取最新的配置信息 mSensorsDataInstance.pullSDKConfigFromServer(); return; } - if (mDbAdapter.getAppEndState()) { + SensorsDataUtils.getScreenNameAndTitleFromActivity(activityProperty, activity); + SensorsDataUtils.mergeJSONObject(activityProperty, endDataProperty); + boolean sessionTimeOut = Math.abs(System.currentTimeMillis() - mDbAdapter.getAppPausedTime()) > mDbAdapter.getSessionIntervalTime(); + SALog.d(TAG, "SessionTimeOut:" + sessionTimeOut); + if (sessionTimeOut && !mDbAdapter.getAppEndState()) { + trackAppEnd(); + } + + if (sessionTimeOut || mDbAdapter.getAppEndState()) { mDbAdapter.commitAppEndState(false); if (mFirstDay.get() == null) { @@ -162,25 +164,28 @@ public void onActivityStarted(Activity activity) { mSensorsDataInstance.applySDKConfigFromCache(); mSensorsDataInstance.resumeTrackScreenOrientation(); mSensorsDataInstance.resumeTrackTaskThread(); + isAutoTrackEnabled = mSensorsDataInstance.isAutoTrackEnabled(); } //每次启动 App,重新拉取最新的配置信息 mSensorsDataInstance.pullSDKConfigFromServer(); try { - if (!mSensorsDataInstance.isAutoTrackEventTypeIgnored(SensorsDataAPI.AutoTrackEventType.APP_START)) { - if (firstStart) { - mFirstStart.commit(false); + if (isAutoTrackEnabled) { + if (!mSensorsDataInstance.isAutoTrackEventTypeIgnored(SensorsDataAPI.AutoTrackEventType.APP_START)) { + if (firstStart) { + mFirstStart.commit(false); + } + JSONObject properties = new JSONObject(); + properties.put("$resume_from_background", resumeFromBackground); + properties.put("$is_first_time", firstStart); + SensorsDataUtils.mergeJSONObject(activityProperty, properties); + mSensorsDataInstance.track("$AppStart", properties); } - JSONObject properties = new JSONObject(); - properties.put("$resume_from_background", resumeFromBackground); - properties.put("$is_first_time", firstStart); - SensorsDataUtils.mergeJSONObject(activityProperty, properties); - mSensorsDataInstance.track("$AppStart", properties); - } - if (!mSensorsDataInstance.isAutoTrackEventTypeIgnored(SensorsDataAPI.AutoTrackEventType.APP_END)) { - mDbAdapter.commitAppStartTime(SystemClock.elapsedRealtime()); - mSensorsDataInstance.trackTimer("$AppEnd", TimeUnit.SECONDS); + if (!mSensorsDataInstance.isAutoTrackEventTypeIgnored(SensorsDataAPI.AutoTrackEventType.APP_END)) { + mDbAdapter.commitAppStartTime(SystemClock.elapsedRealtime()); + mSensorsDataInstance.trackTimer("$AppEnd", TimeUnit.SECONDS); + } } } catch (Exception e) { SALog.i(TAG, e); @@ -373,6 +378,7 @@ public void onTick(long l) { public void onFinish() { SALog.d(TAG,"timeFinish"); trackAppEnd(); + resumeFromBackground = true; mSensorsDataInstance.stopTrackTaskThread(); } }; diff --git a/SensorsAnalyticsSDK/src/main/java/com/sensorsdata/analytics/android/sdk/SensorsDataAutoTrackHelper.java b/SensorsAnalyticsSDK/src/main/java/com/sensorsdata/analytics/android/sdk/SensorsDataAutoTrackHelper.java index f26aedb6..20470a48 100644 --- a/SensorsAnalyticsSDK/src/main/java/com/sensorsdata/analytics/android/sdk/SensorsDataAutoTrackHelper.java +++ b/SensorsAnalyticsSDK/src/main/java/com/sensorsdata/analytics/android/sdk/SensorsDataAutoTrackHelper.java @@ -220,7 +220,7 @@ private static void trackFragmentAppViewScreen(Object fragment) { } if (fragment.getClass().getAnnotation(SensorsDataIgnoreTrackAppViewScreen.class) != null - && fragmentsSets == null ) { + && fragmentsSets == null) { return; } @@ -231,7 +231,7 @@ private static void trackFragmentAppViewScreen(Object fragment) { try { Method getActivityMethod = fragment.getClass().getMethod("getActivity"); if (getActivityMethod != null) { - activity = (Activity)getActivityMethod.invoke(fragment); + activity = (Activity) getActivityMethod.invoke(fragment); } } catch (Exception e) { //ignored @@ -286,7 +286,7 @@ public static void trackFragmentResume(Object object) { try { Method getParentFragmentMethod = object.getClass().getMethod("getParentFragment"); - if (getParentFragmentMethod != null ) { + if (getParentFragmentMethod != null) { Object parentFragment = getParentFragmentMethod.invoke(object); if (parentFragment == null) { if (!fragmentIsHidden(object) && fragmentGetUserVisibleHint(object)) { @@ -307,7 +307,7 @@ private static boolean fragmentGetUserVisibleHint(Object fragment) { try { Method getUserVisibleHintMethod = fragment.getClass().getMethod("getUserVisibleHint"); if (getUserVisibleHintMethod != null) { - return (boolean)getUserVisibleHintMethod.invoke(fragment); + return (boolean) getUserVisibleHintMethod.invoke(fragment); } } catch (Exception e) { //ignored @@ -319,7 +319,7 @@ private static boolean fragmentIsHidden(Object fragment) { try { Method isHiddenMethod = fragment.getClass().getMethod("isHidden"); if (isHiddenMethod != null) { - return (boolean)isHiddenMethod.invoke(fragment); + return (boolean) isHiddenMethod.invoke(fragment); } } catch (Exception e) { //ignored @@ -369,7 +369,7 @@ private static boolean fragmentIsResumed(Object fragment) { try { Method isResumedMethod = fragment.getClass().getMethod("isResumed"); if (isResumedMethod != null) { - return (boolean)isResumedMethod.invoke(fragment); + return (boolean) isResumedMethod.invoke(fragment); } } catch (Exception e) { //ignored @@ -712,6 +712,7 @@ public static void trackTabLayoutSelected(Object object, Object tab) { //将 Context 转成 Activity Activity activity = null; + boolean isFragment = false; if (object instanceof Context) { activity = AopUtil.getActivityFromContext((Context) object, null); } else { @@ -723,6 +724,13 @@ public static void trackTabLayoutSelected(Object object, Object tab) { if (bridgeObject instanceof Activity) { activity = (Activity) bridgeObject; break; + } else if (isFragment(bridgeObject)) { + object = bridgeObject; + isFragment = true; + break; + } else if (bridgeObject instanceof View) { + View view = (View) bridgeObject; + activity = AopUtil.getActivityFromContext(view.getContext(), null); } } } catch (Exception e) { @@ -739,7 +747,10 @@ public static void trackTabLayoutSelected(Object object, Object tab) { JSONObject properties = new JSONObject(); //$screen_name & $title - if (activity != null) { + if (isFragment) { + activity = AopUtil.getActivityFromFragment(object); + AopUtil.getScreenNameAndTitleFromFragment(properties, object); + } else if (activity != null) { SensorsDataUtils.mergeJSONObject(buildTitleAndScreenName(activity), properties); } @@ -1109,7 +1120,7 @@ public static void trackDialog(DialogInterface dialogInterface, int whichButton) try { Method getButtonMethod = dialog.getClass().getMethod("getButton", new Class[]{int.class}); if (getButtonMethod != null) { - button = (Button)getButtonMethod.invoke(dialog, whichButton); + button = (Button) getButtonMethod.invoke(dialog, whichButton); } } catch (Exception e) { //ignored @@ -1123,7 +1134,7 @@ public static void trackDialog(DialogInterface dialogInterface, int whichButton) try { Method getListViewMethod = dialog.getClass().getMethod("getListView"); if (getListViewMethod != null) { - ListView listView = (ListView)getListViewMethod.invoke(dialog); + ListView listView = (ListView) getListViewMethod.invoke(dialog); if (listView != null) { ListAdapter listAdapter = listView.getAdapter(); Object object = listAdapter.getItem(whichButton); @@ -1405,11 +1416,11 @@ public static void trackViewOnClick(View view) { Object viewPagerAdapter = getAdapterMethod.invoke(view); Method getCurrentItemMethod = view.getClass().getMethod("getCurrentItem"); if (getCurrentItemMethod != null) { - int currentItem = (int)getCurrentItemMethod.invoke(view); + int currentItem = (int) getCurrentItemMethod.invoke(view); properties.put(AopConstants.ELEMENT_POSITION, String.format(Locale.CHINA, "%d", currentItem)); Method getPageTitleMethod = viewPagerAdapter.getClass().getMethod("getPageTitle", new Class[]{int.class}); if (getPageTitleMethod != null) { - viewText = (String)getPageTitleMethod.invoke(viewPagerAdapter, new Object[]{currentItem}); + viewText = (String) getPageTitleMethod.invoke(viewPagerAdapter, new Object[]{currentItem}); } } } @@ -1425,7 +1436,7 @@ public static void trackViewOnClick(View view) { } else { method = view.getClass().getMethod("getTextOff"); } - viewText = (String)method.invoke(view); + viewText = (String) method.invoke(view); } else if (view instanceof RadioButton) { // RadioButton viewType = "RadioButton"; RadioButton radioButton = (RadioButton) view; @@ -1511,7 +1522,7 @@ public static void trackViewOnClick(View view) { } } - public static void track(String eventName,String properties) { + public static void track(String eventName, String properties) { try { if (TextUtils.isEmpty(eventName)) { return; diff --git a/SensorsAnalyticsSDK/src/main/java/com/sensorsdata/analytics/android/sdk/util/AopUtil.java b/SensorsAnalyticsSDK/src/main/java/com/sensorsdata/analytics/android/sdk/util/AopUtil.java index 67017365..6597c21d 100644 --- a/SensorsAnalyticsSDK/src/main/java/com/sensorsdata/analytics/android/sdk/util/AopUtil.java +++ b/SensorsAnalyticsSDK/src/main/java/com/sensorsdata/analytics/android/sdk/util/AopUtil.java @@ -25,7 +25,10 @@ import com.sensorsdata.analytics.android.sdk.AopConstants; import com.sensorsdata.analytics.android.sdk.Pathfinder; import com.sensorsdata.analytics.android.sdk.R; +import com.sensorsdata.analytics.android.sdk.SALog; +import com.sensorsdata.analytics.android.sdk.ScreenAutoTracker; import com.sensorsdata.analytics.android.sdk.SensorsDataAPI; +import com.sensorsdata.analytics.android.sdk.SensorsDataFragmentTitle; import org.json.JSONObject; @@ -232,11 +235,30 @@ public static void getFragmentNameFromView(View view, JSONObject properties) { fragmentName = fragmentName2; } if (!TextUtils.isEmpty(fragmentName)) { - String screenName = properties.optString(AopConstants.SCREEN_NAME); - if (!TextUtils.isEmpty(fragmentName)) { - properties.put(AopConstants.SCREEN_NAME, String.format(Locale.CHINA, "%s|%s", screenName, fragmentName)); - } else { - properties.put(AopConstants.SCREEN_NAME, fragmentName); + boolean isScreenNameAdd = false; + Object fragment = Class.forName(fragmentName).newInstance(); + if (fragment instanceof ScreenAutoTracker) { + ScreenAutoTracker screenAutoTracker = (ScreenAutoTracker) fragment; + JSONObject trackProperties = screenAutoTracker.getTrackProperties(); + if (trackProperties != null) { + if (trackProperties.has(AopConstants.SCREEN_NAME)) { + properties.put(AopConstants.SCREEN_NAME, trackProperties.optString(AopConstants.SCREEN_NAME)); + isScreenNameAdd = true; + } + + if (trackProperties.has(AopConstants.TITLE)) { + properties.put(AopConstants.TITLE, trackProperties.optString(AopConstants.TITLE)); + } + } + } + + if (!isScreenNameAdd) { + String screenName = properties.optString(AopConstants.SCREEN_NAME); + if (!TextUtils.isEmpty(screenName)) { + properties.put(AopConstants.SCREEN_NAME, String.format(Locale.CHINA, "%s|%s", screenName, fragmentName)); + } else { + properties.put(AopConstants.SCREEN_NAME, fragmentName); + } } } } @@ -275,6 +297,86 @@ public static Activity getActivityFromContext(Context context, View view) { return activity; } + /** + * 尝试读取页面 title + * + * @param properties JSONObject + * @param fragment Fragment + */ + public static void getScreenNameAndTitleFromFragment(JSONObject properties, Object fragment) { + try { + String screenName = null; + String title = null; + if (fragment instanceof ScreenAutoTracker) { + ScreenAutoTracker screenAutoTracker = (ScreenAutoTracker) fragment; + JSONObject trackProperties = screenAutoTracker.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); + } + } + } + + if (TextUtils.isEmpty(title) && fragment.getClass().isAnnotationPresent(SensorsDataFragmentTitle.class)) { + SensorsDataFragmentTitle sensorsDataFragmentTitle = fragment.getClass().getAnnotation(SensorsDataFragmentTitle.class); + if (sensorsDataFragmentTitle != null) { + title = sensorsDataFragmentTitle.title(); + } + } + + boolean isTitleNull = TextUtils.isEmpty(title); + boolean isScreenNameNull = TextUtils.isEmpty(screenName); + if (isTitleNull || isScreenNameNull) { + Activity activity = getActivityFromFragment(fragment); + if (activity != null) { + if (isTitleNull) { + title = SensorsDataUtils.getActivityTitle(activity); + } + + if (isScreenNameNull) { + screenName = fragment.getClass().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 = fragment.getClass().getCanonicalName(); + } + properties.put("$screen_name", screenName); + } catch (Exception ex) { + SALog.printStackTrace(ex); + } + } + + /** + * 根据 Fragment 获取对应的 Activity + * @param fragment,Fragment + * @return Activity or null + */ + public static Activity getActivityFromFragment(Object fragment) { + Activity activity = null; + if (Build.VERSION.SDK_INT >= 11) { + try { + Method getActivityMethod = fragment.getClass().getMethod("getActivity"); + if (getActivityMethod != null) { + activity = (Activity) getActivityMethod.invoke(fragment); + } + } catch (Exception e) { + //ignored + } + } + return activity; + } + public static String getViewId(View view) { String idString = null; try { diff --git a/SensorsAnalyticsSDK/src/main/java/com/sensorsdata/analytics/android/sdk/util/SensorsDataUtils.java b/SensorsAnalyticsSDK/src/main/java/com/sensorsdata/analytics/android/sdk/util/SensorsDataUtils.java index ab2e5f9c..9e7e07f3 100644 --- a/SensorsAnalyticsSDK/src/main/java/com/sensorsdata/analytics/android/sdk/util/SensorsDataUtils.java +++ b/SensorsAnalyticsSDK/src/main/java/com/sensorsdata/analytics/android/sdk/util/SensorsDataUtils.java @@ -74,11 +74,6 @@ public static SensorsDataSDKRemoteConfig toSDKRemoteConfig(String config) { sdkRemoteConfig.setAutoTrackMode(-1); } return sdkRemoteConfig; - } else { - //默认配置 - sdkRemoteConfig.setDisableDebugMode(false); - sdkRemoteConfig.setDisableSDK(false); - sdkRemoteConfig.setAutoTrackMode(-1); } } catch (Exception e) { com.sensorsdata.analytics.android.sdk.SALog.printStackTrace(e);