Java tutorial
/** * Copyright 2014 ArcBees 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.arcbees.analytics.client; import java.util.HashMap; import java.util.Map; import java.util.logging.Logger; import com.arcbees.analytics.shared.AnalyticsImpl; import com.arcbees.analytics.shared.AnalyticsPlugin; import com.arcbees.analytics.shared.GaAccount; import com.arcbees.analytics.shared.HitType; import com.arcbees.analytics.shared.ProtocolTranslator; import com.arcbees.analytics.shared.options.AnalyticsOptions; import com.arcbees.analytics.shared.options.CreateOptions; import com.arcbees.analytics.shared.options.GeneralOptions; import com.arcbees.analytics.shared.options.TimingOptions; import com.google.gwt.core.client.Duration; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.client.JsArrayMixed; import com.google.gwt.http.client.Request; import com.google.gwt.http.client.RequestBuilder; import com.google.gwt.http.client.RequestCallback; import com.google.gwt.http.client.RequestException; import com.google.gwt.http.client.Response; import com.google.gwt.http.client.URL; import com.google.gwt.json.client.JSONArray; import com.google.gwt.json.client.JSONObject; import com.google.gwt.json.client.JSONString; import com.google.gwt.json.client.JSONValue; import com.google.gwt.user.client.Timer; import com.google.inject.Inject; public class ClientAnalytics extends AnalyticsImpl { private static final Logger LOGGER = Logger.getLogger(ClientAnalytics.class.getName()); private final Map<String, Double> timingEvents = new HashMap<>(); private final String fallbackPath; private final Timer fallbackInitTimer = new Timer() { @Override public void run() { if (loadFallback()) { LOGGER.info("Universal analytics not loaded after 10 seconds, using fallback"); } } }; @Inject ClientAnalytics(@GaAccount String userAccount, @AutoCreate boolean autoCreate, @AutoInject boolean autoInject, @TrackInitialPageView boolean trackInitialPageView, @FallbackPath String fallbackPath) { super(userAccount); this.fallbackPath = fallbackPath; if (autoInject) { init(); } if (autoCreate) { create().go(); if (trackInitialPageView) { sendPageView().go(); } } } private void call(JSONValue... params) { final JSONArray aryParams = new JSONArray(); for (JSONValue p : params) { aryParams.set(aryParams.size(), p); } nativeCall(aryParams.getJavaScriptObject()); } @Override public CreateOptions create(final String userAccount) { return new AnalyticsOptions(new JsonOptionsCallback() { @Override public void onCallback(JSONObject options) { call(new JSONString("create"), new JSONString(userAccount), options); setGlobalSettings().forceSsl(true).go(); } }).createOptions(); } @Override public void enablePlugin(AnalyticsPlugin plugin) { if (plugin.getJsName() != null) { call(new JSONString("require"), new JSONString(plugin.getFieldName()), new JSONString(plugin.getJsName())); } else { call(new JSONString("require"), new JSONString(plugin.getFieldName())); } } @Override public TimingOptions endTimingEvent(String trackerName, String timingCategory, String timingVariableName) { final String key = getTimingKey(timingCategory, timingVariableName); if (timingEvents.containsKey(key)) { return sendTiming(trackerName, timingCategory, timingVariableName, (int) (Duration.currentTimeMillis() - timingEvents.remove(key))); } return new AnalyticsOptions(new JsonOptionsCallback() { @Override public void onCallback(JSONObject options) { // Do nothing a timing event was ended before it was started. // This is here just to stop a crash. } }).timingOptions(timingCategory, timingVariableName, 0); } private void init() { nativeInit(); if (!fallbackPath.isEmpty()) { fallbackInitTimer.schedule(10000); } } public void fallback(JsArrayMixed arguments) { if ("send".equals(arguments.getString(0))) { JSONObject jsonOptions = new JSONObject(arguments.getObject(arguments.length() - 1)); StringBuilder url = new StringBuilder(); url.append(fallbackPath).append("?"); url.append(ProtocolTranslator.getFieldName("hitType")).append("=") .append(URL.encodeQueryString(arguments.getString(1))); for (String key : jsonOptions.keySet()) { if (!"hitCallback".equals(key)) { JSONValue jsonValue = jsonOptions.get(key); String strValue = ""; if (jsonValue.isBoolean() != null) { strValue = jsonValue.isBoolean().booleanValue() + ""; } else if (jsonValue.isNumber() != null) { strValue = jsonValue.isNumber().doubleValue() + ""; } else if (jsonValue.isString() != null) { strValue = jsonValue.isString().stringValue(); } url.append("&").append(ProtocolTranslator.getFieldName(key)).append("=") .append(URL.encodeQueryString(strValue)); } } try { RequestBuilder requestBuilder = new RequestBuilder(RequestBuilder.GET, url.toString()); requestBuilder.setCallback(new RequestCallback() { @Override public void onResponseReceived(Request request, Response response) { // TODO call hitcallback if needed. } @Override public void onError(Request request, Throwable exception) { // TODO Auto-generated method stub } }); requestBuilder.send(); } catch (RequestException e) { } } } private native boolean loadFallback() /*-{ var name = $wnd['GoogleAnalyticsObject']; var preCalled = $wnd[name].q; if (preCalled !== undefined) { var that = this; $wnd[name] = function() { // CHECKSTYLE_OFF $entry(that.@com.arcbees.analytics.client.ClientAnalytics::fallback(Lcom/google/gwt/core/client/JsArrayMixed;)(arguments)); // CHECKSTYLE_ON }; for (var i = 0; i < preCalled.length; i++) { $wnd[name].apply(null, preCalled[i]); } return true; } return false; }-*/; private native void nativeInit() /*-{ (function(i, s, o, g, r, a, m) { i['GoogleAnalyticsObject'] = r; i[r] = i[r] || function() { (i[r].q = i[r].q || []).push(arguments) }, i[r].l = 1 * new Date(); a = s.createElement(o), m = s.getElementsByTagName(o)[0]; a.async = 1; a.src = g; m.parentNode.insertBefore(a, m) })($wnd, $doc, 'script', '//www.google-analytics.com/analytics.js', '__ua'); }-*/; private native void nativeCall(JavaScriptObject params) /*-{ $wnd.__ua.apply(null, params); }-*/; @Override public AnalyticsOptions send(final String trackerName, final HitType hitType) { return new AnalyticsOptions(new JsonOptionsCallback() { @Override public void onCallback(JSONObject options) { call(new JSONString(trackerName == null ? "send" : trackerName + ".send"), new JSONString(hitType.getFieldName()), options); } }); } @Override public GeneralOptions setGlobalSettings() { return new AnalyticsOptions(new JsonOptionsCallback() { @Override public void onCallback(JSONObject options) { call(new JSONString("set"), options); } }).generalOptions(); } @Override public void startTimingEvent(String timingCategory, String timingVariableName) { timingEvents.put(getTimingKey(timingCategory, timingVariableName), Duration.currentTimeMillis()); } }