From c09891d05fe27bdaa5dcf78cf0b024d45a3a08d6 Mon Sep 17 00:00:00 2001 From: cpacm Date: Tue, 2 Apr 2024 19:59:12 +0800 Subject: [PATCH] feat: page rule (#211) * make downgrade as cdp config. * cdp for 4.0 * upload index when > -1 * optInt or optLong has default value from annotation. * add page rule. 1. load page setting from xml file; 2. add config method for page setting; 3. call track app set page. * attributes.remove(null) => null check --------- Co-authored-by: tianhui12 <83947211+tianhui12@users.noreply.github.com> --- build.gradle | 2 - gradle/libs.versions.toml | 2 +- .../serializer/JsonSerializerGenerator.kt | 20 ++++- .../sdk/autotrack/AutotrackConfig.java | 85 ++++++++++++++++++ .../sdk/autotrack/page/ActivityPage.java | 23 +++-- .../sdk/autotrack/page/FragmentPage.java | 25 ++++-- .../android/sdk/autotrack/page/Page.java | 37 +++++++- .../sdk/autotrack/page/PageConfig.java | 55 ++++++++++++ .../sdk/autotrack/page/PageProvider.java | 46 +++++++--- .../android/sdk/autotrack/page/PageRule.java | 69 ++++++++++++++ .../sdk/autotrack/util/XmlParserUtil.java | 89 +++++++++++++++++++ .../sdk/autotrack/page/PageRuleTest.java | 64 +++++++++++++ .../database/EventDataContentProvider.java | 7 +- growingio-sdk-bom/build.gradle | 4 +- .../sdk/track/middleware/EventSender.java | 4 +- 15 files changed, 496 insertions(+), 36 deletions(-) create mode 100644 growingio-autotracker-core/src/main/java/com/growingio/android/sdk/autotrack/page/PageConfig.java create mode 100644 growingio-autotracker-core/src/main/java/com/growingio/android/sdk/autotrack/page/PageRule.java create mode 100644 growingio-autotracker-core/src/main/java/com/growingio/android/sdk/autotrack/util/XmlParserUtil.java create mode 100644 growingio-autotracker-core/src/test/java/com/growingio/android/sdk/autotrack/page/PageRuleTest.java diff --git a/build.gradle b/build.gradle index 9bf939f4..e0114776 100644 --- a/build.gradle +++ b/build.gradle @@ -54,7 +54,6 @@ subprojects { spotless { java { target '**/*.java' - licenseHeaderFile rootProject.file('gradle/java.header') removeUnusedImports() } @@ -63,7 +62,6 @@ subprojects { targetExclude("$buildDir/**/*.kt") ktlint() - licenseHeaderFile rootProject.file('gradle/java.header') } groovyGradle { target '*.gradle' diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3f30dd6a..c8873bc5 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -29,7 +29,7 @@ powermock = "2.0.9" # !!! SDK VERSION !!! growingio = "4.2.0" growingioCode = "40200" -growingioPlugin = "4.0.0" +growingioPlugin = "4.1.0" [plugins] android-application = { id = "com.android.application", version.ref = "pluginGradle" } diff --git a/growingio-annotation/json-serializer/src/main/java/com/growingio/sdk/annotation/json/serializer/JsonSerializerGenerator.kt b/growingio-annotation/json-serializer/src/main/java/com/growingio/sdk/annotation/json/serializer/JsonSerializerGenerator.kt index 78c33e4c..26ba62b9 100644 --- a/growingio-annotation/json-serializer/src/main/java/com/growingio/sdk/annotation/json/serializer/JsonSerializerGenerator.kt +++ b/growingio-annotation/json-serializer/src/main/java/com/growingio/sdk/annotation/json/serializer/JsonSerializerGenerator.kt @@ -264,11 +264,25 @@ internal class JsonSerializerGenerator( ), ) toJsonMethod.beginControlFlow("if($fieldName != null && !$fieldName.isEmpty())") - .addStatement("$fieldName.remove(null)") .addStatement( - "jsonObject.put(\"${fieldName}\", new \$T(event.$fieldMethod))", + "\$T keys = $fieldName.keySet()", + ParameterizedTypeName.get( + ClassName.get(Set::class.java), + ClassName.get(String::class.java), + ), + ) + .addStatement( + "\$T attrObject = new \$T()", + ClassName.get(JSON_OBJECT_PACKAGE, JSON_OBJECT_CLASS), ClassName.get(JSON_OBJECT_PACKAGE, JSON_OBJECT_CLASS), - ).endControlFlow() + ) + .beginControlFlow("for (String key : keys)") + .beginControlFlow("if (key != null)") + .addStatement("attrObject.put(key, $fieldName.get(key))") + .endControlFlow() + .endControlFlow() + .addStatement("jsonObject.put(\"${fieldName}\", attrObject)") + .endControlFlow() } else { toJsonMethod.addStatement( "jsonObject.put(\"${fieldName}\", new \$T(event.$fieldMethod))", diff --git a/growingio-autotracker-core/src/main/java/com/growingio/android/sdk/autotrack/AutotrackConfig.java b/growingio-autotracker-core/src/main/java/com/growingio/android/sdk/autotrack/AutotrackConfig.java index c40a1bdf..19a1d04d 100644 --- a/growingio-autotracker-core/src/main/java/com/growingio/android/sdk/autotrack/AutotrackConfig.java +++ b/growingio-autotracker-core/src/main/java/com/growingio/android/sdk/autotrack/AutotrackConfig.java @@ -16,12 +16,20 @@ package com.growingio.android.sdk.autotrack; import com.growingio.android.sdk.Configurable; +import com.growingio.android.sdk.autotrack.page.PageRule; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; public class AutotrackConfig implements Configurable { private float mImpressionScale = 0; private boolean enableFragmentTag = false; private final AutotrackOptions mAutotrackOptions = new AutotrackOptions(); + private int pageXmlRes = 0; + private final List pageRules = new ArrayList<>(); + public AutotrackConfig setImpressionScale(float scale) { if (scale < 0) { scale = 0; @@ -36,6 +44,76 @@ public float getImpressionScale() { return mImpressionScale; } + /** + * Set the page rule xml resource id for auto page track. + * + * @param pageXmlRes page rule xml resource id + */ + public AutotrackConfig setPageRuleXml(int pageXmlRes) { + this.pageXmlRes = pageXmlRes; + return this; + } + + /** + * Add page rule for auto track. + * PageName is the alias name of the page, such as "MainPage". + * PageClassPath is the full path of the page class, such as "com.growingio.android.sdk.autotrack.MainActivity". + * + * @param pageName page's alias name + * @param pageClassPath page's class path + * @return AutotrackConfig + */ + public AutotrackConfig addPageRule(String pageName, String pageClassPath) { + pageRules.add(new PageRule(pageName, pageClassPath)); + return this; + } + + /** + * Add page rule for auto track. + * pageClassRegex support regular expression, such as "com.growingio.android.autotrack.*Activity". + * + * @param pageClassRegex page's regular expression + */ + public AutotrackConfig addPageMatchRule(String pageClassRegex) { + pageRules.add(new PageRule(pageClassRegex)); + return this; + } + + /** + * Add page rule for auto track. + * PageName is the alias name of the page, such as "MainPage". + * PageClassPath is the full path of the page class, such as "com.growingio.android.sdk.autotrack.MainActivity". + * PageAttributes is the attributes of the page, such as "{'key1':'value1','key2':'value2'}". + * + * @param pageName page's alias name + * @param pageClassPath page's class path + * @param attributes page's attributes + * @return AutotrackConfig + */ + public AutotrackConfig addPageRuleWithAttributes(String pageName, String pageClassPath, Map attributes) { + PageRule pageRule = new PageRule(pageName, pageClassPath); + pageRule.setAttributes(attributes); + pageRules.add(pageRule); + return this; + } + + /** + * Add page rule for auto track. + * pageClassRegex support regular expression, such as "com.growingio.android.autotrack.*Activity". + * PageAttributes is the attributes of the page, such as "{'key1':'value1','key2':'value2'}". + * + * @param pageClassRegex page's regular expression + * @param attributes page's attributes + * @return AutotrackConfig + */ + public AutotrackConfig addPageMatchRuleWithAttributes(String pageClassRegex, Map attributes) { + PageRule pageRule = new PageRule(pageClassRegex); + pageRule.setAttributes(attributes); + pageRules.add(pageRule); + return this; + } + + public AutotrackConfig setWebViewBridgeEnabled(boolean webViewBridgeEnabled) { mAutotrackOptions.setWebViewBridgeEnabled(webViewBridgeEnabled); return this; @@ -59,4 +137,11 @@ public boolean isEnableFragmentTag() { return enableFragmentTag; } + public List getPageRules() { + return pageRules; + } + + public int getPageXmlRes() { + return pageXmlRes; + } } diff --git a/growingio-autotracker-core/src/main/java/com/growingio/android/sdk/autotrack/page/ActivityPage.java b/growingio-autotracker-core/src/main/java/com/growingio/android/sdk/autotrack/page/ActivityPage.java index cf6470d9..0ac1d388 100644 --- a/growingio-autotracker-core/src/main/java/com/growingio/android/sdk/autotrack/page/ActivityPage.java +++ b/growingio-autotracker-core/src/main/java/com/growingio/android/sdk/autotrack/page/ActivityPage.java @@ -19,19 +19,23 @@ import android.text.TextUtils; import android.view.View; -import com.growingio.android.sdk.autotrack.AutotrackConfig; public class ActivityPage extends Page { - private AutotrackConfig autotrackConfig; + private PageConfig pageConfig; public ActivityPage(Activity carrier) { super(new SuperActivity(carrier)); } - public ActivityPage(Activity carrier, AutotrackConfig autotrackConfig) { + public ActivityPage(Activity carrier, PageConfig pageConfig) { super(new SuperActivity(carrier)); - this.autotrackConfig = autotrackConfig; + this.pageConfig = pageConfig; + + if (this.pageConfig != null) { + String fullPageClassPath = getCarrier().getRealActivity().getClass().getName(); + loadPageRule(this.pageConfig.getPageRules(), fullPageClassPath); + } } @Override @@ -51,7 +55,7 @@ public String getClassName() { @Override public boolean isAutotrack() { // cdp downgrade when activity page is enabled - if (autotrackConfig != null && autotrackConfig.getAutotrackOptions().isActivityPageEnabled()) { + if (pageConfig != null && pageConfig.isActivityPageEnabled()) { return !isIgnored(); } return super.isAutotrack(); @@ -78,4 +82,13 @@ public String getTitle() { } return super.getTitle(); } + + @Override + public String pagePath() { + if (pageConfig != null && pageConfig.isDowngrade()) { + return originPath(true); + } else { + return "/" + getName(); + } + } } diff --git a/growingio-autotracker-core/src/main/java/com/growingio/android/sdk/autotrack/page/FragmentPage.java b/growingio-autotracker-core/src/main/java/com/growingio/android/sdk/autotrack/page/FragmentPage.java index bf58355a..1c7c85d8 100644 --- a/growingio-autotracker-core/src/main/java/com/growingio/android/sdk/autotrack/page/FragmentPage.java +++ b/growingio-autotracker-core/src/main/java/com/growingio/android/sdk/autotrack/page/FragmentPage.java @@ -18,19 +18,21 @@ import android.text.TextUtils; import android.view.View; -import com.growingio.android.sdk.autotrack.AutotrackConfig; - public class FragmentPage extends Page> { - private AutotrackConfig autotrackConfig; + private PageConfig pageConfig; public FragmentPage(SuperFragment carrier) { super(carrier); } - public FragmentPage(SuperFragment carrier, AutotrackConfig autotrackConfig) { + public FragmentPage(SuperFragment carrier, PageConfig pageConfig) { super(carrier); - this.autotrackConfig = autotrackConfig; + this.pageConfig = pageConfig; + if (this.pageConfig != null) { + String fullPageClassPath = getCarrier().getRealFragment().getClass().getName(); + loadPageRule(this.pageConfig.getPageRules(), fullPageClassPath); + } } @Override @@ -53,7 +55,7 @@ public View getView() { @Override public String getTag() { - if (autotrackConfig.isEnableFragmentTag()) { + if (pageConfig.isEnableFragmentTag()) { String tag = getCarrier().getTag(); if (!TextUtils.isEmpty(tag)) { return transformSwitcherTag(tag); @@ -87,9 +89,18 @@ private String transformSwitcherTag(String tag) { @Override public boolean isAutotrack() { // cdp downgrade when fragment page is enabled - if (autotrackConfig != null && autotrackConfig.getAutotrackOptions().isFragmentPageEnabled()) { + if (pageConfig != null && pageConfig.isFragmentPageEnabled()) { return !isIgnored(); } return super.isAutotrack(); } + + @Override + public String pagePath() { + if (pageConfig != null && pageConfig.isDowngrade()) { + return originPath(true); + } else { + return "/" + getName(); + } + } } diff --git a/growingio-autotracker-core/src/main/java/com/growingio/android/sdk/autotrack/page/Page.java b/growingio-autotracker-core/src/main/java/com/growingio/android/sdk/autotrack/page/Page.java index d078f559..3b3e937e 100644 --- a/growingio-autotracker-core/src/main/java/com/growingio/android/sdk/autotrack/page/Page.java +++ b/growingio-autotracker-core/src/main/java/com/growingio/android/sdk/autotrack/page/Page.java @@ -31,6 +31,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.regex.PatternSyntaxException; public abstract class Page { private final static int MAX_PAGE_LEVEL = 3; @@ -256,7 +257,41 @@ public String path() { return mPath; } - this.mPath = originPath(true); + this.mPath = pagePath(); return this.mPath; } + + protected String pagePath() { + return "/" + getClassName(); + } + + protected void loadPageRule(List pageRuleList, String fullPageClassPath) { + if (pageRuleList == null || fullPageClassPath == null) return; + // match exactly page classpath at first + for (PageRule pageRule : pageRuleList) { + if (!pageRule.isRegMatch() && fullPageClassPath.equals(pageRule.getPageClassPath())) { + setAlias(pageRule.getPageName()); + setAttributes(pageRule.getAttributes()); + setIsAutotrack(true); + } + } + if (!mIsAutotrack) { + // match reg page classpath secondly + for (PageRule pageRule : pageRuleList) { + if (pageRule.isRegMatch() && matchPageRule(fullPageClassPath, pageRule.getPageClassPath())) { + setAlias(getName()); + setAttributes(pageRule.getAttributes()); + setIsAutotrack(true); + } + } + } + } + + private boolean matchPageRule(String input, String regex) { + try { + return input.matches(regex); + } catch (PatternSyntaxException e) { + return false; + } + } } diff --git a/growingio-autotracker-core/src/main/java/com/growingio/android/sdk/autotrack/page/PageConfig.java b/growingio-autotracker-core/src/main/java/com/growingio/android/sdk/autotrack/page/PageConfig.java new file mode 100644 index 00000000..c1f6987f --- /dev/null +++ b/growingio-autotracker-core/src/main/java/com/growingio/android/sdk/autotrack/page/PageConfig.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2024 Beijing Yishu Technology Co., Ltd. + * + * 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.growingio.android.sdk.autotrack.page; + +import java.util.List; + +class PageConfig { + private boolean enableFragmentTag = false; + private List pageRuleList; + private boolean isActivityPageEnabled = true; + private boolean isFragmentPageEnabled = true; + private boolean isDowngrade = false; + + public PageConfig(List pageRuleList, boolean isActivityPageEnabled, boolean isFragmentPageEnabled, boolean enableFragmentTag, boolean isDowngrade) { + this.pageRuleList = pageRuleList; + this.isActivityPageEnabled = isActivityPageEnabled; + this.isFragmentPageEnabled = isFragmentPageEnabled; + this.enableFragmentTag = enableFragmentTag; + this.isDowngrade = isDowngrade; + } + + public boolean isEnableFragmentTag() { + return enableFragmentTag; + } + + public List getPageRules() { + return pageRuleList; + } + + public boolean isActivityPageEnabled() { + return isActivityPageEnabled; + } + + public boolean isFragmentPageEnabled() { + return isFragmentPageEnabled; + } + + public boolean isDowngrade() { + return isDowngrade; + } +} diff --git a/growingio-autotracker-core/src/main/java/com/growingio/android/sdk/autotrack/page/PageProvider.java b/growingio-autotracker-core/src/main/java/com/growingio/android/sdk/autotrack/page/PageProvider.java index 42a4b6cc..0a9fa11a 100644 --- a/growingio-autotracker-core/src/main/java/com/growingio/android/sdk/autotrack/page/PageProvider.java +++ b/growingio-autotracker-core/src/main/java/com/growingio/android/sdk/autotrack/page/PageProvider.java @@ -24,6 +24,7 @@ import com.growingio.android.sdk.TrackerContext; import com.growingio.android.sdk.autotrack.AutotrackConfig; +import com.growingio.android.sdk.autotrack.util.XmlParserUtil; import com.growingio.android.sdk.track.events.PageEvent; import com.growingio.android.sdk.autotrack.view.ViewAttributeUtil; import com.growingio.android.sdk.track.TrackMainThread; @@ -31,11 +32,15 @@ import com.growingio.android.sdk.track.listener.event.ActivityLifecycleEvent; import com.growingio.android.sdk.track.log.Logger; import com.growingio.android.sdk.track.providers.ActivityStateProvider; +import com.growingio.android.sdk.track.providers.ConfigurationProvider; import com.growingio.android.sdk.track.providers.TrackerLifecycleProvider; import com.growingio.android.sdk.track.utils.ActivityUtil; + +import java.util.Collections; import java.util.HashMap; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.WeakHashMap; @@ -57,7 +62,7 @@ private static class SingleInstance { } private ActivityStateProvider activityStateProvider; - private AutotrackConfig autotrackConfig; + private PageConfig pageConfig; private PageProvider() { ALL_PAGE_TREE.clear(); @@ -67,10 +72,29 @@ private PageProvider() { @Override public void setup(TrackerContext context) { activityStateProvider = context.getActivityStateProvider(); - autotrackConfig = context.getConfigurationProvider().getConfiguration(AutotrackConfig.class); activityStateProvider.registerActivityLifecycleListener(this); + loadPageConfig(context); + } + + private void loadPageConfig(TrackerContext context) { + ConfigurationProvider configurationProvider = context.getConfigurationProvider(); + AutotrackConfig autotrackConfig = configurationProvider.getConfiguration(AutotrackConfig.class); + boolean isDowngrade = configurationProvider.isDowngrade(); + if (autotrackConfig != null) { + boolean isActivityPageEnabled = autotrackConfig.getAutotrackOptions().isActivityPageEnabled(); + boolean isFragmentPageEnabled = autotrackConfig.getAutotrackOptions().isFragmentPageEnabled(); + boolean enableFragmentTag = autotrackConfig.isEnableFragmentTag(); + List pageRuleList = XmlParserUtil.loadPageRuleXml(context, autotrackConfig.getPageXmlRes()); + autotrackConfig.getPageRules().addAll(0, pageRuleList); + + List pageRules = Collections.unmodifiableList(autotrackConfig.getPageRules()); + pageConfig = new PageConfig(pageRules, isActivityPageEnabled, isFragmentPageEnabled, enableFragmentTag, isDowngrade); + } else { + pageConfig = new PageConfig(null, isDowngrade, isDowngrade, false, isDowngrade); + } } + @Override public void shutdown() { activityStateProvider.unregisterActivityLifecycleListener(this); @@ -109,7 +133,7 @@ private ActivityPage generateActivityPageInTree(Activity activity) { CACHE_PAGES.remove(activity); } if (page == null) { - page = new ActivityPage(activity, autotrackConfig); + page = new ActivityPage(activity, pageConfig); } ALL_PAGE_TREE.put(activity, page); return page; @@ -126,7 +150,7 @@ protected ActivityPage findOrCreateActivityPage(Activity activity) { return page; } if (page == null) { - page = new ActivityPage(activity, autotrackConfig); + page = new ActivityPage(activity, pageConfig); CACHE_PAGES.put(activity, page); } return page; @@ -146,7 +170,7 @@ public void autotrackActivity(Activity activity, String alias, Map fragment) { if (CACHE_PAGES.containsKey(realFragment)) { return (FragmentPage) CACHE_PAGES.get(realFragment); } - FragmentPage fragmentPage = new FragmentPage(fragment, autotrackConfig); + FragmentPage fragmentPage = new FragmentPage(fragment, pageConfig); CACHE_PAGES.put(realFragment, fragmentPage); return fragmentPage; } @@ -344,7 +368,7 @@ private FragmentPage generateFragmentPage(SuperFragment fragment) { CACHE_PAGES.remove(realFragment); return fragmentPage; } - return new FragmentPage(fragment, autotrackConfig); + return new FragmentPage(fragment, pageConfig); } public void autotrackFragment(SuperFragment fragment, String alias, Map attributes) { @@ -367,7 +391,7 @@ public void autotrackFragment(SuperFragment fragment, String alias, Map fragment, String alias, Map fragment, boolean ignored){ + public void ignoreFragment(SuperFragment fragment, boolean ignored) { if (fragment.getActivity() == null) return; // find activity page ActivityPage page = findOrCreateActivityPage(fragment.getActivity()); @@ -390,7 +414,7 @@ public void ignoreFragment(SuperFragment fragment, boolean ignored){ if (CACHE_PAGES.containsKey(realFragment)) { fragmentPage = (FragmentPage) CACHE_PAGES.get(realFragment); } else { - fragmentPage = new FragmentPage(fragment, autotrackConfig); + fragmentPage = new FragmentPage(fragment, pageConfig); CACHE_PAGES.put(realFragment, fragmentPage); } fragmentPage.setIgnore(ignored); diff --git a/growingio-autotracker-core/src/main/java/com/growingio/android/sdk/autotrack/page/PageRule.java b/growingio-autotracker-core/src/main/java/com/growingio/android/sdk/autotrack/page/PageRule.java new file mode 100644 index 00000000..efcb2408 --- /dev/null +++ b/growingio-autotracker-core/src/main/java/com/growingio/android/sdk/autotrack/page/PageRule.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2024 Beijing Yishu Technology Co., Ltd. + * + * 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.growingio.android.sdk.autotrack.page; + +import androidx.annotation.NonNull; + +import java.util.HashMap; +import java.util.Map; + +public class PageRule { + private final String pageClassPath; + private String pageName; + private final boolean regMatch; + private Map attributes = new HashMap<>(); + + public PageRule(String pageName, String pageClassPath) { + this.pageClassPath = pageClassPath; + this.pageName = pageName; + this.regMatch = false; + } + + public PageRule(String pageClassPath) { + this.pageClassPath = pageClassPath; + this.regMatch = true; + } + + public String getPageName() { + return pageName; + } + + public Map getAttributes() { + return attributes; + } + + public String getPageClassPath() { + return pageClassPath; + } + + public boolean isRegMatch() { + return regMatch; + } + + public void setAttributes(Map attributes) { + this.attributes = attributes; + } + + @NonNull + @Override + public String toString() { + if (isRegMatch()) { + return "PageRule{" + "pageRegexPath='" + pageClassPath + '\'' + '}'; + } else { + return "PageRule{" + "pageName='" + pageName + '\'' + ", pageClassPath='" + pageClassPath + '\'' + '}'; + } + } +} diff --git a/growingio-autotracker-core/src/main/java/com/growingio/android/sdk/autotrack/util/XmlParserUtil.java b/growingio-autotracker-core/src/main/java/com/growingio/android/sdk/autotrack/util/XmlParserUtil.java new file mode 100644 index 00000000..3f2627db --- /dev/null +++ b/growingio-autotracker-core/src/main/java/com/growingio/android/sdk/autotrack/util/XmlParserUtil.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2024 Beijing Yishu Technology Co., Ltd. + * + * 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.growingio.android.sdk.autotrack.util; + +import android.content.Context; +import android.content.res.Resources; +import android.content.res.XmlResourceParser; + +import com.growingio.android.sdk.autotrack.page.PageRule; +import com.growingio.android.sdk.track.log.Logger; + +import org.xmlpull.v1.XmlPullParserException; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class XmlParserUtil { + private static final String TAG = "XmlParserUtil"; + private static final String GROWINGIO_SETTING_NODE = "growingio-setting"; + private static final String PAGE_RULE_NODE = "page-rule"; + private static final String PAGE_LIST_NODE = "page-list"; + private static final String PAGE_MATCH_NODE = "page-match"; + private static final String PAGE_NODE = "page"; + + public static List loadPageRuleXml(Context context, int xmlResId) { + List pageRules = new ArrayList<>(); + if (xmlResId == 0) return pageRules; + Logger.d(TAG, "Start loadPageRuleXml."); + try { + try (XmlResourceParser xmlParser = context.getResources().getXml(xmlResId)) { + int eventType = xmlParser.getEventType(); + String parentNode = null; + while (eventType != XmlResourceParser.END_DOCUMENT) { + if (eventType == XmlResourceParser.START_TAG) { + if (GROWINGIO_SETTING_NODE.equals(xmlParser.getName()) && parentNode == null) { + parentNode = GROWINGIO_SETTING_NODE; + } + if (GROWINGIO_SETTING_NODE.equals(parentNode) && PAGE_RULE_NODE.equals(xmlParser.getName())) { + parentNode = PAGE_RULE_NODE; + } + if (PAGE_RULE_NODE.equals(parentNode) && PAGE_LIST_NODE.equals(xmlParser.getName())) { + parentNode = PAGE_LIST_NODE; + } + + if (PAGE_RULE_NODE.equals(parentNode) && PAGE_MATCH_NODE.equals(xmlParser.getName())) { + parentNode = PAGE_MATCH_NODE; + } + if (PAGE_NODE.equals(xmlParser.getName()) && PAGE_LIST_NODE.equals(parentNode)) { + String pageName = xmlParser.getAttributeValue(null, "name"); + String pageClassPath = xmlParser.getAttributeValue(null, "path"); + pageRules.add(new PageRule(pageName, pageClassPath)); + } + + if (PAGE_NODE.equals(xmlParser.getName()) && PAGE_MATCH_NODE.equals(parentNode)) { + String pageRegex = xmlParser.getAttributeValue(null, "regex"); + pageRules.add(new PageRule(pageRegex)); + } + } + if (eventType == XmlResourceParser.END_TAG) { + if (PAGE_MATCH_NODE.equals(xmlParser.getName()) || PAGE_LIST_NODE.equals(xmlParser.getName())) { + parentNode = PAGE_RULE_NODE; + } + } + eventType = xmlParser.next(); + } + } catch (XmlPullParserException | IOException e) { + Logger.e(TAG, "loadPageRuleXml failed.", e); + } + } catch (Resources.NotFoundException e) { + Logger.e(TAG, "Not found xml file.", e); + } + return pageRules; + } +} diff --git a/growingio-autotracker-core/src/test/java/com/growingio/android/sdk/autotrack/page/PageRuleTest.java b/growingio-autotracker-core/src/test/java/com/growingio/android/sdk/autotrack/page/PageRuleTest.java new file mode 100644 index 00000000..ba05d15b --- /dev/null +++ b/growingio-autotracker-core/src/test/java/com/growingio/android/sdk/autotrack/page/PageRuleTest.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2023 Beijing Yishu Technology Co., Ltd. + * + * 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.growingio.android.sdk.autotrack.page; + +import com.google.common.truth.Truth; + +import org.junit.Test; + +public class PageRuleTest { + + @Test + public void testPageRule() { + PageRule pageRule = new PageRule("pageName", "pageClassPath"); + + Truth.assertThat(match(pageRule, "pageClassPath")).isTrue(); + Truth.assertThat(match(pageRule, "pageClassPath2")).isFalse(); + } + + @Test + public void testPageMatchRule() { + PageRule pageRule = new PageRule("com.growingio.*Activity"); + + Truth.assertThat(match(pageRule, "com.growingio.MainActivity")).isTrue(); + Truth.assertThat(match(pageRule, "com.growingio.BaseFragment")).isFalse(); + } + + @Test + public void testAllPageMatchRule() { + PageRule pageRule = new PageRule(".*"); + + Truth.assertThat(match(pageRule, "com.growingio.MainActivity")).isTrue(); + Truth.assertThat(match(pageRule, "ksld")).isTrue(); + } + + private boolean match(PageRule pageRule, String inputPageClassPath) { + String pageClassPath = pageRule.getPageClassPath(); + boolean regMatch = pageRule.isRegMatch(); + if (pageClassPath == null || inputPageClassPath == null) { + return false; + } + if (!regMatch) { + return pageClassPath.equals(inputPageClassPath); + } else { + try { + return inputPageClassPath.matches(pageClassPath); + } catch (Exception e) { + return false; + } + } + } +} diff --git a/growingio-data/database/src/main/java/com/growingio/android/database/EventDataContentProvider.java b/growingio-data/database/src/main/java/com/growingio/android/database/EventDataContentProvider.java index 6bfe0790..c39570a2 100644 --- a/growingio-data/database/src/main/java/com/growingio/android/database/EventDataContentProvider.java +++ b/growingio-data/database/src/main/java/com/growingio/android/database/EventDataContentProvider.java @@ -56,8 +56,11 @@ public boolean onCreate() { } private void trackAppStart() { - if (ClassExistHelper.hasClass("com.growingio.android.gmonitor.GMonitor")) { - com.growingio.android.gmonitor.GMonitor.appStart(); + try { + if (ClassExistHelper.hasClass("com.growingio.android.gmonitor.GMonitor")) { + com.growingio.android.gmonitor.GMonitor.appStart(); + } + } catch (Throwable ignored) { } } diff --git a/growingio-sdk-bom/build.gradle b/growingio-sdk-bom/build.gradle index 5227ecf1..e84d92b5 100644 --- a/growingio-sdk-bom/build.gradle +++ b/growingio-sdk-bom/build.gradle @@ -46,8 +46,8 @@ dependencies { } api "com.growingio.android:analytics-fa:4.0.0" - api "com.growingio.android:analytics-sa:4.0.0" - api "com.growingio.android:dummy-sa:4.0.0" + api "com.growingio.android:analytics-sa:4.1.0" + api "com.growingio.android:dummy-sa:4.1.0" // giokit api 'com.growingio.giokit:giokit:2.0.0' diff --git a/growingio-tracker-core/src/main/java/com/growingio/android/sdk/track/middleware/EventSender.java b/growingio-tracker-core/src/main/java/com/growingio/android/sdk/track/middleware/EventSender.java index 59a186e1..61d56cec 100644 --- a/growingio-tracker-core/src/main/java/com/growingio/android/sdk/track/middleware/EventSender.java +++ b/growingio-tracker-core/src/main/java/com/growingio/android/sdk/track/middleware/EventSender.java @@ -181,9 +181,9 @@ private ActivityManager.MemoryInfo getMemoryInfo() { private int numOfMaxEventsPerRequest() { ActivityManager.MemoryInfo info = getMemoryInfo(); if (info.lowMemory) { - return 3; + return 10; } - return 50; + return 100; } /**