mirror of
https://github.com/scratchfoundation/scratchjr.git
synced 2024-11-28 18:15:37 -05:00
Switch to firebase analytics
* Remove ScratchJrApplication class - it was only being used to initialize the old Google Analytics. * Change AppUsage (home, school, other, noanswer) from being a prefix on `label` to being a Firebase user property. * Set the user property when loading the index page - it shouldn’t change for the rest of the session.
This commit is contained in:
parent
1be3feb791
commit
b965440709
9 changed files with 61 additions and 60 deletions
|
@ -30,9 +30,10 @@ android {
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||||
|
implementation 'com.google.firebase:firebase-core:17.2.0'
|
||||||
|
implementation 'com.google.firebase:firebase-analytics:17.2.0'
|
||||||
implementation 'com.google.android.gms:play-services-location:17.0.0'
|
implementation 'com.google.android.gms:play-services-location:17.0.0'
|
||||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||||
implementation 'com.google.android.gms:play-services-analytics:17.0.0'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def appModuleRootFolder = '.'
|
def appModuleRootFolder = '.'
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:theme="@style/AppTheme"
|
android:theme="@style/AppTheme"
|
||||||
android:name="ScratchJrApplication"
|
|
||||||
android:hardwareAccelerated="true">
|
android:hardwareAccelerated="true">
|
||||||
<provider android:name="ShareContentProvider"
|
<provider android:name="ShareContentProvider"
|
||||||
android:grantUriPermissions="true"
|
android:grantUriPermissions="true"
|
||||||
|
|
|
@ -30,9 +30,6 @@ import android.webkit.JavascriptInterface;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
|
|
||||||
import com.google.android.gms.analytics.HitBuilders;
|
|
||||||
import com.google.android.gms.analytics.Tracker;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The methods in this inner class are exposed directly to JavaScript in the HTML5 pages
|
* The methods in this inner class are exposed directly to JavaScript in the HTML5 pages
|
||||||
* as AndroidInterface.
|
* as AndroidInterface.
|
||||||
|
@ -44,7 +41,6 @@ public class JavaScriptDirectInterface {
|
||||||
|
|
||||||
/** Activity hosting the webview running the JavaScript */
|
/** Activity hosting the webview running the JavaScript */
|
||||||
private final ScratchJrActivity _activity;
|
private final ScratchJrActivity _activity;
|
||||||
private final ScratchJrApplication _application;
|
|
||||||
|
|
||||||
/** Current camera view, if active */
|
/** Current camera view, if active */
|
||||||
private CameraView _cameraView;
|
private CameraView _cameraView;
|
||||||
|
@ -55,9 +51,8 @@ public class JavaScriptDirectInterface {
|
||||||
/**
|
/**
|
||||||
* @param scratchJrActivity
|
* @param scratchJrActivity
|
||||||
*/
|
*/
|
||||||
JavaScriptDirectInterface(ScratchJrActivity scratchJrActivity, ScratchJrApplication application) {
|
JavaScriptDirectInterface(ScratchJrActivity scratchJrActivity) {
|
||||||
_activity = scratchJrActivity;
|
_activity = scratchJrActivity;
|
||||||
_application = application;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@JavascriptInterface
|
@JavascriptInterface
|
||||||
|
@ -623,7 +618,13 @@ public class JavaScriptDirectInterface {
|
||||||
// Analytics
|
// Analytics
|
||||||
@JavascriptInterface
|
@JavascriptInterface
|
||||||
public void analyticsEvent(String category, String action, String label, long value) {
|
public void analyticsEvent(String category, String action, String label, long value) {
|
||||||
_application.getDefaultTracker().send(new HitBuilders.EventBuilder()
|
_activity.logAnalyticsEvent(category, action, label);
|
||||||
.setCategory(category).setAction(action).setLabel(label).setValue(value).build());
|
}
|
||||||
|
|
||||||
|
@JavascriptInterface
|
||||||
|
public void setAnalyticsUser(String place) {
|
||||||
|
if (place != null) {
|
||||||
|
_activity.setAnalyticsUser(place);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,8 +33,7 @@ import android.webkit.WebView;
|
||||||
import android.webkit.WebViewClient;
|
import android.webkit.WebViewClient;
|
||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
|
|
||||||
import com.google.android.gms.analytics.HitBuilders;
|
import com.google.firebase.analytics.FirebaseAnalytics;
|
||||||
import com.google.android.gms.analytics.Tracker;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
|
@ -104,8 +103,8 @@ public class ScratchJrActivity
|
||||||
public int cameraPermissionResult = PackageManager.PERMISSION_DENIED;
|
public int cameraPermissionResult = PackageManager.PERMISSION_DENIED;
|
||||||
public int micPermissionResult = PackageManager.PERMISSION_DENIED;
|
public int micPermissionResult = PackageManager.PERMISSION_DENIED;
|
||||||
|
|
||||||
/** Analytics tracker */
|
/* Firebase analytics tracking */
|
||||||
private Tracker _tracker;
|
private FirebaseAnalytics _FirebaseAnalytics;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
@ -153,8 +152,7 @@ public class ScratchJrActivity
|
||||||
receiveProject(it.getData());
|
receiveProject(it.getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
ScratchJrApplication application = (ScratchJrApplication) getApplication();
|
_FirebaseAnalytics = FirebaseAnalytics.getInstance(this);
|
||||||
_tracker = application.getDefaultTracker();
|
|
||||||
|
|
||||||
// When System UI bar is displayed, wait one second and then re-assert immersive mode.
|
// When System UI bar is displayed, wait one second and then re-assert immersive mode.
|
||||||
getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(new OnSystemUiVisibilityChangeListener() {
|
getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(new OnSystemUiVisibilityChangeListener() {
|
||||||
|
@ -381,7 +379,7 @@ public class ScratchJrActivity
|
||||||
CookieSyncManager.createInstance(this);
|
CookieSyncManager.createInstance(this);
|
||||||
|
|
||||||
/* Object exposed to the JavaScript that makes it easy to bridge JavaScript and Java */
|
/* Object exposed to the JavaScript that makes it easy to bridge JavaScript and Java */
|
||||||
JavaScriptDirectInterface javaScriptDirectInterface = new JavaScriptDirectInterface(this, (ScratchJrApplication) getApplication());
|
JavaScriptDirectInterface javaScriptDirectInterface = new JavaScriptDirectInterface(this);
|
||||||
_webView.addJavascriptInterface(javaScriptDirectInterface, "AndroidInterface");
|
_webView.addJavascriptInterface(javaScriptDirectInterface, "AndroidInterface");
|
||||||
_webView.setWebViewClient(new WebViewClient() {
|
_webView.setWebViewClient(new WebViewClient() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -406,8 +404,8 @@ public class ScratchJrActivity
|
||||||
|
|
||||||
// Track page load
|
// Track page load
|
||||||
String[] parts = url.split("/");
|
String[] parts = url.split("/");
|
||||||
_tracker.setScreenName(parts[parts.length - 1]);
|
String page = parts[parts.length - 1].split("\\?")[0];
|
||||||
_tracker.send(new HitBuilders.ScreenViewBuilder().build());
|
_FirebaseAnalytics.setCurrentScreen((Activity) view.getContext(), page, null);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
_webView.requestFocus(View.FOCUS_DOWN);
|
_webView.requestFocus(View.FOCUS_DOWN);
|
||||||
|
@ -478,6 +476,28 @@ public class ScratchJrActivity
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* log a Firebase analytics event for the app
|
||||||
|
* @param category
|
||||||
|
* @param action
|
||||||
|
* @param label
|
||||||
|
*/
|
||||||
|
public void logAnalyticsEvent(String category, String action, String label) {
|
||||||
|
Bundle params = new Bundle();
|
||||||
|
params.putString(FirebaseAnalytics.Param.ITEM_ID, action);
|
||||||
|
params.putString(FirebaseAnalytics.Param.ITEM_CATEGORY, category);
|
||||||
|
params.putString(FirebaseAnalytics.Param.ITEM_NAME, label);
|
||||||
|
_FirebaseAnalytics.logEvent(FirebaseAnalytics.Event.VIEW_ITEM, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Record the preferred place for the user: home, school, other, noanswer
|
||||||
|
* @param place
|
||||||
|
*/
|
||||||
|
public void setAnalyticsUser(String place) {
|
||||||
|
_FirebaseAnalytics.setUserProperty("place_preference", place);
|
||||||
|
}
|
||||||
|
|
||||||
public void translateAndScaleRectToContainerCoords(RectF rect, float devicePixelRatio) {
|
public void translateAndScaleRectToContainerCoords(RectF rect, float devicePixelRatio) {
|
||||||
float wx = _webView.getX();
|
float wx = _webView.getX();
|
||||||
float wy = _webView.getY();
|
float wy = _webView.getY();
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
package org.scratchjr.android;
|
|
||||||
|
|
||||||
import android.app.Application;
|
|
||||||
|
|
||||||
import com.google.android.gms.analytics.GoogleAnalytics;
|
|
||||||
import com.google.android.gms.analytics.Logger;
|
|
||||||
import com.google.android.gms.analytics.Tracker;
|
|
||||||
|
|
||||||
public class ScratchJrApplication extends Application {
|
|
||||||
private Tracker mTracker;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the default {@link Tracker} for this {@link Application}.
|
|
||||||
* @return tracker
|
|
||||||
*/
|
|
||||||
synchronized public Tracker getDefaultTracker() {
|
|
||||||
if (mTracker == null) {
|
|
||||||
GoogleAnalytics analytics = GoogleAnalytics.getInstance(this);
|
|
||||||
// To enable debug logging use: adb shell setprop log.tag.GAv4 DEBUG
|
|
||||||
mTracker = analytics.newTracker(R.xml.global_tracker);
|
|
||||||
}
|
|
||||||
return mTracker;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -23,5 +23,6 @@ allprojects {
|
||||||
url "https://maven.google.com"
|
url "https://maven.google.com"
|
||||||
}
|
}
|
||||||
jcenter()
|
jcenter()
|
||||||
|
google()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,6 +94,7 @@ function indexLoadStart (afterUsage) {
|
||||||
gn('usageOther').className = 'usageOther hide';
|
gn('usageOther').className = 'usageOther hide';
|
||||||
gn('usageNoanswer').className = 'usageNoanswer hide';
|
gn('usageNoanswer').className = 'usageNoanswer hide';
|
||||||
}
|
}
|
||||||
|
iOS.setAnalyticsUser(AppUsage.currentUsage);
|
||||||
}
|
}
|
||||||
gn('gettings').className = 'gettings show';
|
gn('gettings').className = 'gettings show';
|
||||||
gn('startcode').className = 'startcode show';
|
gn('startcode').className = 'startcode show';
|
||||||
|
|
|
@ -3,7 +3,6 @@ import IO from './IO';
|
||||||
import Lobby from '../lobby/Lobby';
|
import Lobby from '../lobby/Lobby';
|
||||||
import Alert from '../editor/ui/Alert';
|
import Alert from '../editor/ui/Alert';
|
||||||
import ScratchAudio from '../utils/ScratchAudio';
|
import ScratchAudio from '../utils/ScratchAudio';
|
||||||
import AppUsage from '../utils/AppUsage';
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////
|
//////////////////////////////////////////////////
|
||||||
// Tablet interface functions
|
// Tablet interface functions
|
||||||
|
@ -356,8 +355,11 @@ export default class iOS {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
value = 1;
|
value = 1;
|
||||||
}
|
}
|
||||||
let usageLabel = label ? AppUsage.currentUsage + label : AppUsage.currentUsage;
|
tabletInterface.analyticsEvent(category, action, label, value);
|
||||||
tabletInterface.analyticsEvent(category, action, usageLabel, value);
|
}
|
||||||
|
|
||||||
|
static setAnalyticsUser (preferredPlace) {
|
||||||
|
tabletInterface.setAnalyticsUser(preferredPlace);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Web Wiew delegate call backs
|
// Web Wiew delegate call backs
|
||||||
|
|
|
@ -14,7 +14,7 @@ export default class AppUsage {
|
||||||
*/
|
*/
|
||||||
static initUsage () {
|
static initUsage () {
|
||||||
const usageCookie = Cookie.get('usage');
|
const usageCookie = Cookie.get('usage');
|
||||||
currentUsage = (usageCookie) ? usageCookie + '::' : '';
|
currentUsage = (usageCookie) ? usageCookie : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -36,6 +36,6 @@ export default class AppUsage {
|
||||||
} else {
|
} else {
|
||||||
Cookie.set('usage', kind);
|
Cookie.set('usage', kind);
|
||||||
}
|
}
|
||||||
currentUsage = (kind === '') ? 'noanswer::' : kind + '::';
|
currentUsage = (kind === '') ? 'noanswer' : kind;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue