Skip to content

Commit

Permalink
feat: abtest (#220)
Browse files Browse the repository at this point in the history
* add abtest experiments names.

* feat: custom event refer with page. (#221)

* feat: auto inject js sdk in webview. (#222)

* fix: update hybrid js initialization code

---------

Co-authored-by: styluo <shu_jiahuili@foxmail.com>

* Update libs.versions.toml

---------
  • Loading branch information
cpacm authored Oct 29, 2024
1 parent 0bd523b commit 72a2c82
Show file tree
Hide file tree
Showing 25 changed files with 862 additions and 62 deletions.
3 changes: 0 additions & 3 deletions .github/workflows/pre_release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,8 @@ jobs:
with:
api-level: 31
target: default
ram-size: 4096M
arch: x86_64
disable-animations: true
disk-size: 6000M
heap-size: 600M
working-directory: ./demo
script: ./gradlew :app:connectedAndroidTest --stacktrace

Expand Down
6 changes: 4 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,10 @@ subprojects {
kotlin {
target '**/*.kt'
targetExclude("$buildDir/**/*.kt")

ktlint()
ktlint().editorConfigOverride([
"ktlint_standard_comment-wrapping": "disabled",
"max_line_length" : 2147483647,
])
}
groovyGradle {
target '*.gradle'
Expand Down
16 changes: 8 additions & 8 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
[versions]
compileSdk = "33"
compileSdk = "34"
minSdk = "17"

# https://developer.android.google.cn/jetpack/androidx/explorer?hl=en&case=all
androidxlifecycle = "2.6.1"
androidxlifecycle = "2.8.2"
androidxtest = "1.5.0"
navigation = "2.5.3"

pluginGradle = "7.4.2" # 4.2.2-7.4.2
kotlin = "1.9.21"
kotlin = "2.0.0"

spotless = "6.20.0"
spotless = "6.25.0"

# https://developer.android.com/jetpack/androidx/releases/compose-compiler
# composeBom = "2023.04.00"

# https://github.com/Kotlin/kotlinx.coroutines
coroutines = "1.6.4"
coroutines = "1.8.1"
# https://github.com/pinterest/ktlint
ktlint = "0.48.2"
# https://square.github.io/okhttp/changelogs/changelog_4x/
Expand All @@ -30,8 +30,8 @@ protobuf = "3.22.3"
powermock = "2.0.9"

# !!! SDK VERSION !!!
growingio = "4.3.1"
growingioCode = "40301"
growingio = "4.3.2"
growingioCode = "40302"
growingioPlugin = "4.3.0"
junit = "1.1.5"

Expand Down Expand Up @@ -176,4 +176,4 @@ powermock = ["mockito-core", "powermock-core", "powermock-api-mockito2", "powerm
okhttp3 = ["okhttp3", "okhttp3-logging"]

growingio-autotracker-sdk = ["growingio-tracker-core", "growingio-autotracker-core", "growingio-okhttp3", "growingio-database", "growingio-protobuf", "growingio-circler", "growingio-debugger", "growingio-hybrid"]
growingio-tracker-sdk = ["growingio-tracker-core", "growingio-okhttp3", "growingio-database", "growingio-protobuf", "growingio-debugger"]
growingio-tracker-sdk = ["growingio-tracker-core", "growingio-okhttp3", "growingio-database", "growingio-protobuf", "growingio-debugger"]
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,10 @@ private void sendAbTestTrackEvent(ABExperiment abExperiment) {
attributesBuilder
.addAttribute("$exp_id", abExperiment.getExperimentId())
.addAttribute("$exp_strategy_id", abExperiment.getStrategyId())
.addAttribute("$exp_layer_id", abExperiment.getLayerId());
.addAttribute("$exp_layer_id", abExperiment.getLayerId())
.addAttribute("$exp_layer_name", abExperiment.getExpLayerName())
.addAttribute("$exp_name", abExperiment.getExpName())
.addAttribute("$exp_strategy_name", abExperiment.getExpStrategyName());
CustomEvent.Builder customEventBuilder = new CustomEvent.Builder();
customEventBuilder.setEventName("$exp_hit");
customEventBuilder.setAttributes(attributesBuilder.build());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@
import java.util.Map;

class ABTestResponse {

private static final String LAYER_ID = "layerId";
private static final String LAYER_NAME = "layerName";
private static final String STRATEGY_ID = "strategyId";
private static final String STRATEGY_NAME = "strategyName";
private static final String EXPERIMENT_ID = "experimentId";
private static final String EXPERIMENT_NAME = "experimentName";
private static final String VARIABLES = "variables";

private int code = -1;
private String errorMsg;

Expand All @@ -48,9 +57,9 @@ public static ABTestResponse parseHttpJson(long expiredTime, String layerId, Str
int code = jsonObject.getInt("code");
response.code = code;
if (code == 0) {
long experimentId = jsonObject.optLong("experimentId");
long strategyId = jsonObject.optLong("strategyId");
JSONObject variables = jsonObject.optJSONObject("variables");
long experimentId = jsonObject.optLong(EXPERIMENT_ID);
long strategyId = jsonObject.optLong(STRATEGY_ID);
JSONObject variables = jsonObject.optJSONObject(VARIABLES);
Map<String, String> variableMap = new HashMap<>();
if (variables != null) {
Iterator<String> keys = variables.keys();
Expand All @@ -62,6 +71,10 @@ public static ABTestResponse parseHttpJson(long expiredTime, String layerId, Str
response.expiredTime = System.currentTimeMillis() + expiredTime;
response.naturalDaytime = tomorrowMill();
response.abExperiment = new ABExperiment(layerId, strategyId, experimentId, variableMap);
String expLayerName = jsonObject.optString(LAYER_NAME);
String expName = jsonObject.optString(EXPERIMENT_NAME);
String expStrategyName = jsonObject.optString(STRATEGY_NAME);
response.abExperiment.setExperimentNames(expLayerName, expName, expStrategyName);
} else {
response.errorMsg = jsonObject.getString("errorMsg");
}
Expand Down Expand Up @@ -104,17 +117,20 @@ public String toSavedJson() {
jsonObject.put("expiredTime", expiredTime);
jsonObject.put("naturalDaytime", naturalDaytime);
if (abExperiment != null) {
jsonObject.put("layerId", abExperiment.getLayerId());
jsonObject.put("strategyId", abExperiment.getStrategyId());
jsonObject.put("experimentId", abExperiment.getExperimentId());
jsonObject.put(LAYER_ID, abExperiment.getLayerId());
jsonObject.put(STRATEGY_ID, abExperiment.getStrategyId());
jsonObject.put(EXPERIMENT_ID, abExperiment.getExperimentId());
Map<String, String> variableMap = abExperiment.getVariables();
Iterator<String> keys = variableMap.keySet().iterator();
JSONObject variablesJson = new JSONObject();
while (keys.hasNext()) {
String key = keys.next();
variablesJson.put(key, variableMap.get(key));
}
jsonObject.put("variables", variablesJson);
jsonObject.put(VARIABLES, variablesJson);
jsonObject.put(LAYER_NAME, abExperiment.getExpLayerName());
jsonObject.put(EXPERIMENT_NAME, abExperiment.getExpName());
jsonObject.put(STRATEGY_NAME, abExperiment.getExpStrategyName());
}

return jsonObject.toString();
Expand All @@ -133,17 +149,21 @@ public static ABTestResponse parseSavedJson(String json) {
abTestResponse.expiredTime = expiredTime;
abTestResponse.naturalDaytime = naturalDaytime;

String layerId = jsonObject.getString("layerId");
long strategyId = jsonObject.getLong("strategyId");
long experimentId = jsonObject.getLong("experimentId");
JSONObject variables = jsonObject.getJSONObject("variables");
String layerId = jsonObject.getString(LAYER_ID);
long strategyId = jsonObject.getLong(STRATEGY_ID);
long experimentId = jsonObject.getLong(EXPERIMENT_ID);
JSONObject variables = jsonObject.getJSONObject(VARIABLES);
Iterator<String> keys = variables.keys();
Map<String, String> variableMap = new HashMap<>();
while (keys.hasNext()) {
String key = keys.next();
variableMap.put(key, variables.get(key).toString());
}
abTestResponse.abExperiment = new ABExperiment(layerId, strategyId, experimentId, variableMap);
String expLayerName = jsonObject.optString(LAYER_NAME);
String expName = jsonObject.optString(EXPERIMENT_NAME);
String expStrategyName = jsonObject.optString(STRATEGY_NAME);
abTestResponse.abExperiment.setExperimentNames(expLayerName, expName, expStrategyName);
return abTestResponse;
} catch (JSONException e) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@ internal class JsonFactoryGenerator(
ClassName.get(
ProcessUtils.JSON_SERIALIZABLE_PACKAGE,
ProcessUtils.JSON_SERIALIZABLE_CLASS,
), // rawType
ClassName.get(eventType), // the value for T
builderType, // the value for R
),
ClassName.get(eventType),
builderType,
)

val jonSerialBuilder = TypeSpec.classBuilder(generateClass).addJavadoc(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,9 @@ internal class JsonSerializerGenerator(
val builderType = ClassName.get(eventBuilderType)

val superinterface = ParameterizedTypeName.get(
ClassName.get(JSON_SERIALIZABLE_PACKAGE, JSON_SERIALIZABLE_CLASS), // rawType
ClassName.get(eventType), // the value for T
builderType, // the value for R
ClassName.get(JSON_SERIALIZABLE_PACKAGE, JSON_SERIALIZABLE_CLASS),
ClassName.get(eventType),
builderType,
)

val jonSerialBuilder = TypeSpec.classBuilder(generateClass).addJavadoc(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
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.EventBuilderProvider;
import com.growingio.android.sdk.track.providers.TrackerLifecycleProvider;
import com.growingio.android.sdk.track.utils.ActivityUtil;

Expand Down Expand Up @@ -60,6 +61,7 @@ private static class SingleInstance {
private static final PageProvider INSTANCE = new PageProvider();
}

private EventBuilderProvider eventBuilderProvider;
private ActivityStateProvider activityStateProvider;
private PageConfig pageConfig;

Expand All @@ -71,6 +73,7 @@ private PageProvider() {
@Override
public void setup(TrackerContext context) {
activityStateProvider = context.getActivityStateProvider();
eventBuilderProvider = context.getEventBuilderProvider();

ConfigurationProvider configurationProvider = context.getConfigurationProvider();
AutotrackConfig autotrackConfig = configurationProvider.getConfiguration(AutotrackConfig.class);
Expand Down Expand Up @@ -229,6 +232,12 @@ private void sendPage(Page<?> page) {
}

private void generatePageEvent(Page<?> page) {
Page<?> activePage = page.lastActivePage();
if (activePage != null) {
eventBuilderProvider.setCustomEventReferPage(activePage.path(), activePage.getShowTimestamp());
} else {
eventBuilderProvider.setCustomEventReferPage("/", 0);
}
String orientation = TrackMainThread.trackMain().getContext().getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT
? PageEvent.ORIENTATION_PORTRAIT : PageEvent.ORIENTATION_LANDSCAPE;
TrackMainThread.trackMain().postEventToTrackMain(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,15 @@ public void setup() {
Application application = ApplicationProvider.getApplicationContext();

Map<Class<? extends Configurable>, Configurable> modules = new HashMap<>();
modules.put(AutotrackConfig.class, new AutotrackConfig().setImpressionScale(0.5f));
modules.put(AutotrackConfig.class,
new AutotrackConfig().setImpressionScale(0.5f)
.setWebViewBridgeEnabled(true)
.setPageRuleXml(0)
.addPageRule("MainActivity", "com.growingio.android.sdk.autotrack.RobolectricActivity")
.addPageMatchRule(".*")
.enableFragmentTag(false)

);
TrackerLifecycleProviderFactory.create().createConfigurationProviderWithConfig(new CoreConfiguration("AutotrackTest", "growingio://autotrack"), modules);
autotracker = new Autotracker(application);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,9 @@ private static EventV3Protocol.EventV3Dto protocol(GEvent gEvent) {
if (gEvent instanceof PageLevelCustomEvent) {
PageLevelCustomEvent plEvent = (PageLevelCustomEvent) gEvent;
eventBuilder.setPath(plEvent.getPath()); //10
eventBuilder.setPageShowTimestamp(plEvent.getPageShowTimestamp()); //23
if (plEvent.getPageShowTimestamp() > 0) {
eventBuilder.setPageShowTimestamp(plEvent.getPageShowTimestamp());//23
}
}
if (gEvent instanceof VisitEvent) {
VisitEvent visitEvent = (VisitEvent) gEvent;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,20 @@ public class HybridBridgeProvider extends ListenerContainer<OnDomChangedListener
HybridBridgeProvider() {
}


private ConfigurationProvider configurationProvider;
private AppInfoProvider appInfoProvider;
private UserInfoProvider userInfoProvider;
private boolean autoJsSdkInject = false;

@Override
public void setup(TrackerContext context) {
configurationProvider = context.getConfigurationProvider();
appInfoProvider = context.getProvider(AppInfoProvider.class);
userInfoProvider = context.getUserInfoProvider();
HybridConfig hybridConfig = configurationProvider.getConfiguration(HybridConfig.class);
if (hybridConfig != null) {
autoJsSdkInject = hybridConfig.isAutoGrowingJsSdk();
}
}

@Override
Expand All @@ -62,10 +66,11 @@ private WebViewJavascriptBridgeConfiguration getJavascriptBridgeConfiguration()
String projectId = configurationProvider.core().getProjectId();
String dataSourceId = configurationProvider.core().getDataSourceId();
String appId = configurationProvider.core().getUrlScheme();
String serverUrl = configurationProvider.core().getDataCollectionServerHost();
String appPackage = appInfoProvider.getPackageName();
String nativeSdkVersion = configurationProvider.isDowngrade() ? SDKConfig.SDK_VERSION_DOWNGRADE : SDKConfig.SDK_VERSION;
int nativeSdkVersionCode = configurationProvider.isDowngrade() ? SDKConfig.SDK_VERSION_CODE_DOWNGRADE : SDKConfig.SDK_VERSION_CODE;
return new WebViewJavascriptBridgeConfiguration(projectId, dataSourceId, appId, appPackage, nativeSdkVersion, nativeSdkVersionCode);
return new WebViewJavascriptBridgeConfiguration(projectId, dataSourceId, serverUrl, appId, appPackage, nativeSdkVersion, nativeSdkVersionCode);
}

public void onDomChanged() {
Expand All @@ -81,8 +86,11 @@ public void unregisterDomChangedListener(OnDomChangedListener listener) {
}

@SuppressLint("SetJavaScriptEnabled")
public void bridgeForWebView(SuperWebView<?> webView) {
public void bridgeForWebView(SuperWebView webView) {
webView.setJavaScriptEnabled(true);
if (autoJsSdkInject) {
webView.wrapperWebChromeClient(getJavascriptBridgeConfiguration());
}
if (webView.hasAddJavaScripted()) {
Logger.d(TAG, "JavascriptInterface has already been added to the WebView");
return;
Expand All @@ -93,7 +101,7 @@ public void bridgeForWebView(SuperWebView<?> webView) {
webView.setAddJavaScript();
}

public void getWebViewDomTree(SuperWebView<?> webView, final Callback<JSONObject> callback) {
public void getWebViewDomTree(SuperWebView webView, final Callback<JSONObject> callback) {
Logger.d(TAG, "getWebViewDomTree");
if (callback == null) {
return;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* 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.hybrid;

import com.growingio.android.sdk.Configurable;

public class HybridConfig implements Configurable {

private boolean autoJsSdkInject = false;

public boolean isAutoGrowingJsSdk() {
return autoJsSdkInject;
}

public HybridConfig setAutoJsSdkInject(boolean autoJsSdkInject) {
this.autoJsSdkInject = autoJsSdkInject;
return this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ public void onFailed() {
});
}

public SuperWebView<? extends View> getSuperWebView() {
public SuperWebView getSuperWebView() {
if (dom.getView() instanceof WebView) {
return SuperWebView.make((WebView) dom.getView());
} else if (ClassExistHelper.instanceOfX5WebView(dom.getView())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
*
* @author cpacm 5/19/21
*/
@GIOLibraryModule
@GIOLibraryModule(config = HybridConfig.class)
public class HybridLibraryGioModule extends LibraryGioModule {
@Override
public void registerComponents(TrackerContext context) {
Expand Down
Loading

0 comments on commit 72a2c82

Please sign in to comment.