forked from organicmaps/organicmaps
[android] Statistics refactored.
* TODO add translations for preference "Allow Stat"
This commit is contained in:
parent
1b1ca9f18b
commit
6302a98d6e
19 changed files with 484 additions and 376 deletions
|
@ -22,8 +22,8 @@ import com.mapswithme.maps.base.MapsWithMeBaseActivity;
|
|||
import com.mapswithme.maps.location.LocationService;
|
||||
import com.mapswithme.maps.state.SuppotedState;
|
||||
import com.mapswithme.util.ConnectionState;
|
||||
import com.mapswithme.util.Statistics;
|
||||
import com.mapswithme.util.Utils;
|
||||
import com.mapswithme.util.statistics.Statistics;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
|
|
|
@ -24,7 +24,7 @@ import android.widget.TextView;
|
|||
import com.mapswithme.maps.MapStorage.Index;
|
||||
import com.mapswithme.maps.base.MapsWithMeBaseListActivity;
|
||||
import com.mapswithme.util.ConnectionState;
|
||||
import com.mapswithme.util.Statistics;
|
||||
import com.mapswithme.util.statistics.Statistics;
|
||||
|
||||
|
||||
public class DownloadUI extends MapsWithMeBaseListActivity implements MapStorage.Listener
|
||||
|
|
|
@ -25,8 +25,8 @@ import android.widget.TextView;
|
|||
import com.mapswithme.maps.base.MapsWithMeBaseListActivity;
|
||||
import com.mapswithme.maps.location.LocationService;
|
||||
import com.mapswithme.util.Language;
|
||||
import com.mapswithme.util.Statistics;
|
||||
import com.mapswithme.util.Utils;
|
||||
import com.mapswithme.util.statistics.Statistics;
|
||||
|
||||
|
||||
public class SearchActivity extends MapsWithMeBaseListActivity implements LocationService.Listener
|
||||
|
|
|
@ -2,7 +2,6 @@ package com.mapswithme.maps.base;
|
|||
|
||||
import android.app.ActionBar;
|
||||
import android.app.Activity;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.view.MenuItem;
|
||||
|
@ -10,8 +9,8 @@ import android.view.inputmethod.InputMethodManager;
|
|||
|
||||
import com.mapswithme.maps.MWMApplication;
|
||||
import com.mapswithme.maps.state.SuppotedState;
|
||||
import com.mapswithme.util.Statistics;
|
||||
import com.mapswithme.util.Utils;
|
||||
import com.mapswithme.util.statistics.Statistics;
|
||||
|
||||
public class MapsWithMeBaseActivity extends FragmentActivity
|
||||
{
|
||||
|
|
|
@ -2,8 +2,8 @@ package com.mapswithme.maps.base;
|
|||
|
||||
import com.mapswithme.maps.MWMApplication;
|
||||
import com.mapswithme.maps.state.SuppotedState;
|
||||
import com.mapswithme.util.Statistics;
|
||||
import com.mapswithme.util.Utils;
|
||||
import com.mapswithme.util.statistics.Statistics;
|
||||
|
||||
import android.app.ActionBar;
|
||||
import android.app.Activity;
|
||||
|
|
|
@ -20,8 +20,8 @@ import com.mapswithme.maps.R;
|
|||
import com.mapswithme.maps.bookmarks.data.Bookmark;
|
||||
import com.mapswithme.maps.bookmarks.data.Icon;
|
||||
import com.mapswithme.maps.bookmarks.data.ParcelablePoint;
|
||||
import com.mapswithme.util.Statistics;
|
||||
import com.mapswithme.util.Utils;
|
||||
import com.mapswithme.util.statistics.Statistics;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ import android.widget.TextView;
|
|||
import com.mapswithme.maps.R;
|
||||
import com.mapswithme.maps.bookmarks.data.Bookmark;
|
||||
import com.mapswithme.maps.bookmarks.data.ParcelablePoint;
|
||||
import com.mapswithme.util.Statistics;
|
||||
import com.mapswithme.util.statistics.Statistics;
|
||||
|
||||
public class ChooseBookmarkCategoryActivity extends AbstractBookmarkCategoryActivity
|
||||
{
|
||||
|
|
|
@ -3,7 +3,7 @@ package com.mapswithme.maps.bookmarks.data;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.mapswithme.util.Statistics;
|
||||
import com.mapswithme.util.statistics.Statistics;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Point;
|
||||
|
|
|
@ -15,8 +15,8 @@ import android.widget.TextView;
|
|||
|
||||
import com.mapswithme.maps.R;
|
||||
import com.mapswithme.maps.promo.request.PromoActivationRequest;
|
||||
import com.mapswithme.util.Statistics;
|
||||
import com.mapswithme.util.Utils;
|
||||
import com.mapswithme.util.statistics.Statistics;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
|
|
|
@ -16,8 +16,8 @@ import android.view.MenuItem;
|
|||
import android.view.inputmethod.InputMethodManager;
|
||||
|
||||
import com.mapswithme.maps.R;
|
||||
import com.mapswithme.util.Statistics;
|
||||
import com.mapswithme.util.Utils;
|
||||
import com.mapswithme.util.statistics.Statistics;
|
||||
|
||||
public class SettingsActivity extends PreferenceActivity
|
||||
{
|
||||
|
|
|
@ -13,6 +13,7 @@ import com.mapswithme.maps.Framework;
|
|||
import com.mapswithme.maps.MapObjectFragment.MapObjectType;
|
||||
import com.mapswithme.maps.R;
|
||||
import com.mapswithme.maps.bookmarks.data.MapObject;
|
||||
import com.mapswithme.util.statistics.Statistics;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
|
|
@ -1,327 +0,0 @@
|
|||
package com.mapswithme.util;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.Editor;
|
||||
import android.media.MediaPlayer.TrackInfo;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
|
||||
import com.flurry.android.FlurryAgent;
|
||||
import com.mapswithme.maps.MWMApplication;
|
||||
import com.mapswithme.maps.R;
|
||||
import com.mapswithme.maps.api.MWMRequest;
|
||||
import com.mapswithme.maps.bookmarks.data.BookmarkManager;
|
||||
|
||||
public enum Statistics
|
||||
{
|
||||
INSTANCE;
|
||||
|
||||
private final static String TAG_PROMO_DE = "PROMO-DE: ";
|
||||
private static String TAG_API = "API: ";
|
||||
|
||||
private final static String FILE_STAT_DATA = "statistics.wtf";
|
||||
private final static String PARAM_SESSIONS = "sessions";
|
||||
private final static String PARAM_STAT_ENABLED = "stat_enabled";
|
||||
private final static String PARAM_STAT_COLLECTED = "collected";
|
||||
private final static String PARAM_STAT_COLLECTED_TIME = "collected_time";
|
||||
|
||||
private final static int ACTIVE_USER_MIN_SESSION = 2;
|
||||
private final static long ACTIVE_USER_MIN_TIME = 30*24*3600;
|
||||
|
||||
private boolean DEBUG = true;
|
||||
private boolean mNewSession = true;
|
||||
// Statistics counters
|
||||
private int mBookmarksCreated= 0;
|
||||
private int mSharedTimes = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
private Statistics()
|
||||
{
|
||||
Log.d(TAG, "Created Statistics instance.");
|
||||
|
||||
FlurryAgent.setUseHttps(true);
|
||||
FlurryAgent.setCaptureUncaughtExceptions(true);
|
||||
|
||||
if (DEBUG)
|
||||
{
|
||||
FlurryAgent.setLogLevel(Log.DEBUG);
|
||||
FlurryAgent.setLogEnabled(true);
|
||||
FlurryAgent.setLogEvents(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
FlurryAgent.setLogLevel(Log.ERROR);
|
||||
FlurryAgent.setLogEnabled(true);
|
||||
FlurryAgent.setLogEvents(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void trackIfEnabled(Context context, String event)
|
||||
{
|
||||
|
||||
if (isStatisticsEnabled(context))
|
||||
{
|
||||
FlurryAgent.logEvent(event);
|
||||
Log.d(TAG, String.format("Logged: %s", event));
|
||||
}
|
||||
else
|
||||
Log.d(TAG, String.format("Not logged: %s", event));
|
||||
|
||||
}
|
||||
|
||||
public void trackIfEnabled(Context context, String event, Map<String, String> params)
|
||||
{
|
||||
if (isStatisticsEnabled(context))
|
||||
{
|
||||
FlurryAgent.logEvent(event, params);
|
||||
Log.d(TAG, String.format("Logged: %s with %s", event, Utils.mapPrettyPrint(params)));
|
||||
}
|
||||
else
|
||||
Log.d(TAG, String.format("Not logged: %s", event));
|
||||
|
||||
}
|
||||
|
||||
public void trackCountryDownload(Context context)
|
||||
{
|
||||
trackIfEnabled(context, "Country download");
|
||||
}
|
||||
|
||||
public void trackCountryUpdate(Context context)
|
||||
{
|
||||
trackIfEnabled(context, "Country update");
|
||||
}
|
||||
|
||||
public void trackCountryDeleted(Context context)
|
||||
{
|
||||
trackIfEnabled(context, "Country deleted");
|
||||
}
|
||||
|
||||
public void trackSearchCategoryClicked(Context context, String category)
|
||||
{
|
||||
final String EVENT = "Search category clicked";
|
||||
|
||||
final Map<String, String> params = new HashMap<String, String>(1);
|
||||
params.put("category", category);
|
||||
|
||||
trackIfEnabled(context, EVENT, params);
|
||||
}
|
||||
|
||||
public void trackGroupChanged(Context context)
|
||||
{
|
||||
trackIfEnabled(context, "Bookmark group changed");
|
||||
}
|
||||
|
||||
public void trackDescriptionChanged(Context context)
|
||||
{
|
||||
trackIfEnabled(context, "Description changed");
|
||||
}
|
||||
|
||||
public void trackGroupCreated(Context context)
|
||||
{
|
||||
trackIfEnabled(context, "Group Created");
|
||||
}
|
||||
|
||||
public void trackSearchContextChanged(Context context, String from, String to)
|
||||
{
|
||||
final String EVENT = "Search context changed";
|
||||
|
||||
final Map<String, String> params = new HashMap<String, String>(2);
|
||||
params.put("from", from);
|
||||
params.put("to", to);
|
||||
|
||||
trackIfEnabled(context, EVENT, params);
|
||||
}
|
||||
|
||||
public void trackColorChanged(Context context, String from, String to)
|
||||
{
|
||||
final String EVENT = "Color changed";
|
||||
|
||||
final Map<String, String> params = new HashMap<String, String>(2);
|
||||
params.put("from", from);
|
||||
params.put("to", to);
|
||||
|
||||
trackIfEnabled(context, EVENT, params);
|
||||
}
|
||||
|
||||
public void trackBookmarkCreated(Context context)
|
||||
{
|
||||
final String EVENT = "Bookmark created";
|
||||
|
||||
final Map<String, String> params = new HashMap<String, String>(1);
|
||||
params.put("Count", String.valueOf(++mBookmarksCreated));
|
||||
|
||||
trackIfEnabled(context, EVENT, params);
|
||||
}
|
||||
|
||||
public void trackPlaceShared(Context context, String channel)
|
||||
{
|
||||
final String EVENT = "Place Shared";
|
||||
|
||||
final Map<String, String> params = new HashMap<String, String>(2);
|
||||
params.put("Channel", channel);
|
||||
params.put("Total Count", String.valueOf(++mSharedTimes));
|
||||
|
||||
trackIfEnabled(context, EVENT, params);
|
||||
}
|
||||
|
||||
public void trackPromocodeDialogOpenedEvent()
|
||||
{
|
||||
FlurryAgent.logEvent(TAG_PROMO_DE + "opened promo code dialog");
|
||||
}
|
||||
|
||||
public void trackPromocodeActivatedEvent()
|
||||
{
|
||||
FlurryAgent.logEvent(TAG_PROMO_DE + "promo code activated");
|
||||
}
|
||||
|
||||
public void trackApiCall(MWMRequest request)
|
||||
{
|
||||
final String text = "used by " + request.getCallerInfo().packageName;
|
||||
FlurryAgent.logEvent(TAG_API + text);
|
||||
}
|
||||
|
||||
public void startActivity(Activity activity)
|
||||
{
|
||||
// CITATION
|
||||
// Insert a call to FlurryAgent.onStartSession(Context, String), passing it
|
||||
// a reference to a Context object (such as an Activity or Service), and
|
||||
// your project's API key. We recommend using the onStart method of each
|
||||
// Activity in your application, and passing the Activity (or Service)
|
||||
// itself as the Context object - passing the global Application context is
|
||||
// not recommended.
|
||||
FlurryAgent.onStartSession(activity, activity.getResources().getString(R.string.flurry_app_key));
|
||||
|
||||
if (mNewSession)
|
||||
{
|
||||
final int currentSessionNumber = incAndGetSessionsNumber(activity);
|
||||
if (isStatisticsEnabled(activity) && isActiveUser(activity, currentSessionNumber))
|
||||
{
|
||||
Log.d(TAG, "Trying to collect on time stat.");
|
||||
// TODO do it in separate thread?
|
||||
if (!isStatisticsCollected(activity))
|
||||
{
|
||||
collectOneTimeStatistics(activity);
|
||||
}
|
||||
else
|
||||
Log.d(TAG, "One time is already collected.");
|
||||
}
|
||||
mNewSession = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void stopActivity(Activity activity)
|
||||
{
|
||||
// CITATION
|
||||
// Insert a call to FlurryAgent.onEndSession(Context) when a session is
|
||||
// complete. We recommend using the onStop method of each Activity in your
|
||||
// application. Make sure to match up a call to onEndSession for each call
|
||||
// of onStartSession, passing in the same Context object that was used to
|
||||
// call onStartSession.
|
||||
FlurryAgent.onEndSession(activity);
|
||||
}
|
||||
|
||||
private void collectOneTimeStatistics(Activity activity)
|
||||
{
|
||||
// Only for PRO
|
||||
if (((MWMApplication)activity.getApplication()).isProVersion())
|
||||
{
|
||||
final Map<String, String> params = new HashMap<String, String>(2);
|
||||
// Number of sets
|
||||
BookmarkManager manager = BookmarkManager.getBookmarkManager(activity);
|
||||
final int categoriesCount = manager.getCategoriesCount();
|
||||
if (categoriesCount > 0)
|
||||
{
|
||||
// Calculate average num of bmks in category
|
||||
double[] sizes = new double[categoriesCount];
|
||||
for (int catIndex = 0; catIndex < categoriesCount; catIndex++)
|
||||
sizes[catIndex] = manager.getCategoryById(catIndex).getSize();
|
||||
final double average = MathUtils.average(sizes);
|
||||
|
||||
params.put("Average number of bmks", String.valueOf(average));
|
||||
}
|
||||
params.put("Categories count", String.valueOf(categoriesCount));
|
||||
|
||||
trackIfEnabled(activity, "One time PRO stat", params);
|
||||
}
|
||||
// For all version
|
||||
// TODO add number of maps
|
||||
|
||||
setStatisticsCollected(activity, true);
|
||||
}
|
||||
|
||||
|
||||
private boolean isStatisticsCollected(Context context)
|
||||
{
|
||||
return getStatPrefs(context).getBoolean(PARAM_STAT_COLLECTED, false);
|
||||
}
|
||||
|
||||
private long getLastStatCollectionTime(Context context)
|
||||
{
|
||||
return getStatPrefs(context).getLong(PARAM_STAT_COLLECTED_TIME, 0);
|
||||
}
|
||||
|
||||
@SuppressLint("CommitPrefEdits")
|
||||
private void setStatisticsCollected(Context context, boolean isCollected)
|
||||
{
|
||||
final Editor editStat = getStatPrefs(context).edit().putBoolean(PARAM_STAT_COLLECTED, isCollected);
|
||||
if (isCollected)
|
||||
editStat.putLong(PARAM_STAT_COLLECTED_TIME, System.currentTimeMillis());
|
||||
|
||||
Utils.applyPrefs(editStat);
|
||||
}
|
||||
|
||||
public boolean isStatisticsEnabled(Context context)
|
||||
{
|
||||
// We don't track old devices (< 10%)
|
||||
// as there is no reliable way to
|
||||
// get installation time there.
|
||||
if (Utils.apiLowerThan(9))
|
||||
return false;
|
||||
|
||||
return getStatPrefs(context).getBoolean(PARAM_STAT_ENABLED, true);
|
||||
}
|
||||
|
||||
public void setStatEnabled(Context context, boolean isEnabled)
|
||||
{
|
||||
Utils.applyPrefs(getStatPrefs(context).edit().putBoolean(PARAM_STAT_ENABLED, isEnabled));
|
||||
// We track if user turned on/off
|
||||
// statistics to understand data better.
|
||||
final Map<String, String> params = new HashMap<String, String>(1);
|
||||
params.put("Enabled", String.valueOf(isEnabled));
|
||||
FlurryAgent.logEvent("Statistics status changed", params);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
|
||||
private boolean isActiveUser(Context context, int currentSessionNumber)
|
||||
{
|
||||
return currentSessionNumber >= ACTIVE_USER_MIN_SESSION
|
||||
|| System.currentTimeMillis() - Utils.getInstallationTime(context) >= ACTIVE_USER_MIN_TIME;
|
||||
}
|
||||
|
||||
private int incAndGetSessionsNumber(Context context)
|
||||
{
|
||||
final SharedPreferences statPrefs = getStatPrefs(context);
|
||||
final int currentSessionNumber = statPrefs.getInt(PARAM_SESSIONS, 0) + 1;
|
||||
Utils.applyPrefs(statPrefs.edit().putInt(PARAM_SESSIONS, currentSessionNumber));
|
||||
|
||||
return currentSessionNumber;
|
||||
}
|
||||
|
||||
private SharedPreferences getStatPrefs(Context context)
|
||||
{
|
||||
return context.getSharedPreferences(FILE_STAT_DATA, Context.MODE_PRIVATE);
|
||||
}
|
||||
|
||||
private final static String TAG = "MWMStat";
|
||||
}
|
|
@ -71,42 +71,6 @@ final public class Utils
|
|||
return value.getDimension(metrics);
|
||||
}
|
||||
|
||||
/*
|
||||
public static String toTitleCase(String str)
|
||||
{
|
||||
if (str == null)
|
||||
return null;
|
||||
|
||||
boolean space = true;
|
||||
StringBuilder builder = new StringBuilder(str);
|
||||
|
||||
final int len = builder.length();
|
||||
for (int i = 0; i < len; ++i)
|
||||
{
|
||||
char c = builder.charAt(i);
|
||||
if (space)
|
||||
{
|
||||
if (!Character.isWhitespace(c))
|
||||
{
|
||||
// Convert to title case and switch out of whitespace mode.
|
||||
builder.setCharAt(i, Character.toTitleCase(c));
|
||||
space = false;
|
||||
}
|
||||
}
|
||||
else if (Character.isWhitespace(c))
|
||||
{
|
||||
space = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.setCharAt(i, Character.toLowerCase(c));
|
||||
}
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
*/
|
||||
|
||||
public static void setStringAndCursorToEnd(EditText edit, String s)
|
||||
{
|
||||
edit.setText(s);
|
||||
|
@ -162,7 +126,7 @@ final public class Utils
|
|||
|
||||
public static <K,V> String mapPrettyPrint(Map<K, V> map)
|
||||
{
|
||||
checkNotNull(map);
|
||||
if (map == null) return "[null]";
|
||||
if (map.isEmpty()) return "[]";
|
||||
|
||||
StringBuilder sb = new StringBuilder("[");
|
||||
|
|
43
android/src/com/mapswithme/util/statistics/Event.java
Normal file
43
android/src/com/mapswithme/util/statistics/Event.java
Normal file
|
@ -0,0 +1,43 @@
|
|||
package com.mapswithme.util.statistics;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.mapswithme.util.Utils;
|
||||
|
||||
public class Event
|
||||
{
|
||||
protected String mName;
|
||||
protected Map<String, String> mParams;
|
||||
protected StatisticsEngine mEngine;
|
||||
|
||||
public void setName(String name) { mName = name; }
|
||||
public void setParams(Map<String, String> params) { mParams = params; }
|
||||
public void setEngine(StatisticsEngine engine) { mEngine = engine; }
|
||||
|
||||
public String getName() { return mName; }
|
||||
public Map<String, String> getParams() { return mParams; }
|
||||
public StatisticsEngine getEngine() { return mEngine; }
|
||||
|
||||
public boolean hasParams()
|
||||
{
|
||||
return mParams != null && !mParams.isEmpty();
|
||||
}
|
||||
|
||||
public void post()
|
||||
{
|
||||
mEngine.postEvent(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
final StringBuilder sb = new StringBuilder(getClass().getSimpleName());
|
||||
sb.append("[name = ")
|
||||
.append(getName())
|
||||
.append(", params: ")
|
||||
.append(Utils.mapPrettyPrint(getParams()))
|
||||
.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
53
android/src/com/mapswithme/util/statistics/EventBuilder.java
Normal file
53
android/src/com/mapswithme/util/statistics/EventBuilder.java
Normal file
|
@ -0,0 +1,53 @@
|
|||
package com.mapswithme.util.statistics;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class EventBuilder
|
||||
{
|
||||
protected Event mEvent = new Event();
|
||||
protected StatisticsEngine mEngine;
|
||||
|
||||
public EventBuilder(StatisticsEngine engine)
|
||||
{
|
||||
mEngine = engine;
|
||||
}
|
||||
|
||||
public EventBuilder setName(String name)
|
||||
{
|
||||
mEvent.setName(name);
|
||||
return this;
|
||||
}
|
||||
|
||||
public EventBuilder addParam(String key, String value)
|
||||
{
|
||||
Map<String, String> params = mEvent.getParams();
|
||||
if (params == null)
|
||||
params = new HashMap<String, String>();
|
||||
params.put(key, value);
|
||||
mEvent.setParams(params);
|
||||
return this;
|
||||
}
|
||||
|
||||
public EventBuilder reset()
|
||||
{
|
||||
mEvent = new Event();
|
||||
return this;
|
||||
}
|
||||
|
||||
public Event getEvent()
|
||||
{
|
||||
mEvent.setEngine(mEngine);
|
||||
return mEvent;
|
||||
}
|
||||
|
||||
public Event getSimpleNamedEvent(String name)
|
||||
{
|
||||
return reset().setName(name).getEvent();
|
||||
}
|
||||
|
||||
public void setEngine(StatisticsEngine engine)
|
||||
{
|
||||
mEngine = engine;
|
||||
}
|
||||
}
|
65
android/src/com/mapswithme/util/statistics/FlurryEngine.java
Normal file
65
android/src/com/mapswithme/util/statistics/FlurryEngine.java
Normal file
|
@ -0,0 +1,65 @@
|
|||
package com.mapswithme.util.statistics;
|
||||
|
||||
import com.flurry.android.FlurryAgent;
|
||||
import com.mapswithme.util.Utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
public class FlurryEngine extends StatisticsEngine
|
||||
{
|
||||
|
||||
private boolean mDebug = false;
|
||||
private String mKey;
|
||||
|
||||
public FlurryEngine(boolean isDebug, String key)
|
||||
{
|
||||
mKey = key;
|
||||
mDebug = isDebug;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(Context context, Bundle params)
|
||||
{
|
||||
FlurryAgent.setUseHttps(true);
|
||||
FlurryAgent.setCaptureUncaughtExceptions(true);
|
||||
|
||||
if (mDebug)
|
||||
{
|
||||
FlurryAgent.setLogLevel(Log.DEBUG);
|
||||
FlurryAgent.setLogEnabled(true);
|
||||
FlurryAgent.setLogEvents(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
FlurryAgent.setLogLevel(Log.ERROR);
|
||||
FlurryAgent.setLogEnabled(true);
|
||||
FlurryAgent.setLogEvents(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartSession(Context context)
|
||||
{
|
||||
FlurryAgent.onStartSession(context, mKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEndSession(Context context)
|
||||
{
|
||||
FlurryAgent.onEndSession(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postEvent(Event event)
|
||||
{
|
||||
Utils.checkNotNull(event);
|
||||
if (event.hasParams())
|
||||
FlurryAgent.logEvent(event.getName());
|
||||
else
|
||||
FlurryAgent.logEvent(event.getName(), event.getParams());
|
||||
// TODO add logging?
|
||||
}
|
||||
|
||||
}
|
297
android/src/com/mapswithme/util/statistics/Statistics.java
Normal file
297
android/src/com/mapswithme/util/statistics/Statistics.java
Normal file
|
@ -0,0 +1,297 @@
|
|||
package com.mapswithme.util.statistics;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.Editor;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
|
||||
import com.mapswithme.maps.MWMApplication;
|
||||
import com.mapswithme.maps.R;
|
||||
import com.mapswithme.maps.api.MWMRequest;
|
||||
import com.mapswithme.maps.bookmarks.data.BookmarkManager;
|
||||
import com.mapswithme.util.MathUtils;
|
||||
import com.mapswithme.util.Utils;
|
||||
|
||||
public enum Statistics
|
||||
{
|
||||
INSTANCE;
|
||||
|
||||
private final static String TAG_PROMO_DE = "PROMO-DE: ";
|
||||
private static String TAG_API = "API: ";
|
||||
|
||||
private final static String FILE_STAT_DATA = "statistics.wtf";
|
||||
private final static String PARAM_SESSIONS = "sessions";
|
||||
private final static String PARAM_STAT_ENABLED = "stat_enabled";
|
||||
private final static String PARAM_STAT_COLLECTED = "collected";
|
||||
private final static String PARAM_STAT_COLLECTED_TIME = "collected_time";
|
||||
|
||||
private final static int ACTIVE_USER_MIN_SESSION = 2;
|
||||
private final static long ACTIVE_USER_MIN_TIME = 30*24*3600;
|
||||
|
||||
// Statistics
|
||||
private EventBuilder mEventBuilder;
|
||||
private StatisticsEngine mStatisticsEngine;
|
||||
// Statistics params
|
||||
private boolean DEBUG = true;
|
||||
private boolean mNewSession = true;
|
||||
// Statistics counters
|
||||
private int mBookmarksCreated= 0;
|
||||
private int mSharedTimes = 0;
|
||||
|
||||
|
||||
private Statistics()
|
||||
{
|
||||
Log.d(TAG, "Created Statistics instance.");
|
||||
}
|
||||
|
||||
private EventBuilder getEventBuilder()
|
||||
{
|
||||
return mEventBuilder;
|
||||
}
|
||||
|
||||
public void trackIfEnabled(Context context, Event event)
|
||||
{
|
||||
if (isStatisticsEnabled(context))
|
||||
event.post();
|
||||
}
|
||||
|
||||
public void trackCountryDownload(Context context)
|
||||
{
|
||||
trackIfEnabled(context, getEventBuilder().getSimpleNamedEvent("Country download"));
|
||||
}
|
||||
|
||||
public void trackCountryUpdate(Context context)
|
||||
{
|
||||
trackIfEnabled(context, getEventBuilder().getSimpleNamedEvent("Country update"));
|
||||
}
|
||||
|
||||
public void trackCountryDeleted(Context context)
|
||||
{
|
||||
trackIfEnabled(context, getEventBuilder().getSimpleNamedEvent("Country deleted"));
|
||||
}
|
||||
|
||||
public void trackSearchCategoryClicked(Context context, String category)
|
||||
{
|
||||
final Event event = getEventBuilder().reset()
|
||||
.setName("Search category clicked")
|
||||
.addParam("category", category)
|
||||
.getEvent();
|
||||
|
||||
trackIfEnabled(context, event);
|
||||
}
|
||||
|
||||
public void trackGroupChanged(Context context)
|
||||
{
|
||||
trackIfEnabled(context, getEventBuilder().getSimpleNamedEvent("Bookmark group changed"));
|
||||
}
|
||||
|
||||
public void trackDescriptionChanged(Context context)
|
||||
{
|
||||
trackIfEnabled(context, getEventBuilder().getSimpleNamedEvent("Description changed"));
|
||||
}
|
||||
|
||||
public void trackGroupCreated(Context context)
|
||||
{
|
||||
trackIfEnabled(context, getEventBuilder().getSimpleNamedEvent("Group Created"));
|
||||
}
|
||||
|
||||
public void trackSearchContextChanged(Context context, String from, String to)
|
||||
{
|
||||
final Event event = getEventBuilder().reset()
|
||||
.setName("Search context changed")
|
||||
.addParam("from", from)
|
||||
.addParam("to", to)
|
||||
.getEvent();
|
||||
|
||||
trackIfEnabled(context, event);
|
||||
}
|
||||
|
||||
public void trackColorChanged(Context context, String from, String to)
|
||||
{
|
||||
final Event event = getEventBuilder().reset()
|
||||
.setName("Color changed")
|
||||
.addParam("from", from)
|
||||
.addParam("to", to)
|
||||
.getEvent();
|
||||
|
||||
trackIfEnabled(context, event);
|
||||
}
|
||||
|
||||
public void trackBookmarkCreated(Context context)
|
||||
{
|
||||
final Event event = getEventBuilder().reset()
|
||||
.setName("Bookmark created")
|
||||
.addParam("Count", String.valueOf(++mBookmarksCreated))
|
||||
.getEvent();
|
||||
|
||||
trackIfEnabled(context, event);
|
||||
}
|
||||
|
||||
public void trackPlaceShared(Context context, String channel)
|
||||
{
|
||||
final Event event = getEventBuilder().reset()
|
||||
.setName("Place Shared")
|
||||
.addParam("Channel", channel)
|
||||
.addParam("Count", String.valueOf(++mSharedTimes))
|
||||
.getEvent();
|
||||
|
||||
trackIfEnabled(context, event);
|
||||
}
|
||||
|
||||
public void trackPromocodeDialogOpenedEvent()
|
||||
{
|
||||
getEventBuilder().getSimpleNamedEvent(TAG_PROMO_DE + "opened promo code dialog").post();
|
||||
}
|
||||
|
||||
public void trackPromocodeActivatedEvent()
|
||||
{
|
||||
getEventBuilder().getSimpleNamedEvent(TAG_PROMO_DE + "promo code activated").post();
|
||||
}
|
||||
|
||||
public void trackApiCall(MWMRequest request)
|
||||
{
|
||||
final String eventName = "used by " + request.getCallerInfo().packageName;
|
||||
getEventBuilder().getSimpleNamedEvent(TAG_API + eventName).post();
|
||||
}
|
||||
|
||||
public void startActivity(Activity activity)
|
||||
{
|
||||
ensureConfigured(activity);
|
||||
mStatisticsEngine.onStartSession(activity);
|
||||
registerSession(activity);
|
||||
}
|
||||
|
||||
private void registerSession(Activity activity)
|
||||
{
|
||||
if (mNewSession)
|
||||
{
|
||||
final int currentSessionNumber = incAndGetSessionsNumber(activity);
|
||||
if (isStatisticsEnabled(activity) && isActiveUser(activity, currentSessionNumber))
|
||||
{
|
||||
// If we haven't collected yet
|
||||
// do it now.
|
||||
if (!isStatisticsCollected(activity))
|
||||
collectOneTimeStatistics(activity);
|
||||
}
|
||||
mNewSession = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureConfigured(Activity activity)
|
||||
{
|
||||
if (mEventBuilder == null || mStatisticsEngine == null)
|
||||
{
|
||||
// Engine
|
||||
final String key = activity.getResources().getString(R.string.flurry_app_key);
|
||||
mStatisticsEngine = new FlurryEngine(DEBUG, key);
|
||||
mStatisticsEngine.configure(null, null);
|
||||
// Builder
|
||||
mEventBuilder = new EventBuilder(mStatisticsEngine);
|
||||
}
|
||||
}
|
||||
|
||||
public void stopActivity(Activity activity)
|
||||
{
|
||||
mStatisticsEngine.onEndSession(activity);
|
||||
}
|
||||
|
||||
private void collectOneTimeStatistics(Activity activity)
|
||||
{
|
||||
final EventBuilder eventBuilder = getEventBuilder().reset();
|
||||
// Only for PRO
|
||||
if (((MWMApplication)activity.getApplication()).isProVersion())
|
||||
{
|
||||
// Number of sets
|
||||
BookmarkManager manager = BookmarkManager.getBookmarkManager(activity);
|
||||
final int categoriesCount = manager.getCategoriesCount();
|
||||
if (categoriesCount > 0)
|
||||
{
|
||||
// Calculate average num of bmks in category
|
||||
double[] sizes = new double[categoriesCount];
|
||||
for (int catIndex = 0; catIndex < categoriesCount; catIndex++)
|
||||
sizes[catIndex] = manager.getCategoryById(catIndex).getSize();
|
||||
final double average = MathUtils.average(sizes);
|
||||
|
||||
eventBuilder.addParam("Average number of bmks", String.valueOf(average));
|
||||
}
|
||||
eventBuilder.addParam("Categories count", String.valueOf(categoriesCount))
|
||||
.setName("One time PRO stat");
|
||||
|
||||
trackIfEnabled(activity, eventBuilder.getEvent());
|
||||
}
|
||||
// TODO add number of maps
|
||||
setStatisticsCollected(activity, true);
|
||||
}
|
||||
|
||||
|
||||
private boolean isStatisticsCollected(Context context)
|
||||
{
|
||||
return getStatPrefs(context).getBoolean(PARAM_STAT_COLLECTED, false);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private long getLastStatCollectionTime(Context context)
|
||||
{
|
||||
return getStatPrefs(context).getLong(PARAM_STAT_COLLECTED_TIME, 0);
|
||||
}
|
||||
|
||||
@SuppressLint("CommitPrefEdits")
|
||||
private void setStatisticsCollected(Context context, boolean isCollected)
|
||||
{
|
||||
final Editor editStat = getStatPrefs(context).edit().putBoolean(PARAM_STAT_COLLECTED, isCollected);
|
||||
if (isCollected)
|
||||
editStat.putLong(PARAM_STAT_COLLECTED_TIME, System.currentTimeMillis());
|
||||
|
||||
Utils.applyPrefs(editStat);
|
||||
}
|
||||
|
||||
public boolean isStatisticsEnabled(Context context)
|
||||
{
|
||||
// We don't track old devices (< 10%)
|
||||
// as there is no reliable way to
|
||||
// get installation time there.
|
||||
if (Utils.apiLowerThan(9))
|
||||
return false;
|
||||
|
||||
return getStatPrefs(context).getBoolean(PARAM_STAT_ENABLED, true);
|
||||
}
|
||||
|
||||
public void setStatEnabled(Context context, boolean isEnabled)
|
||||
{
|
||||
Utils.applyPrefs(getStatPrefs(context).edit().putBoolean(PARAM_STAT_ENABLED, isEnabled));
|
||||
// We track if user turned on/off
|
||||
// statistics to understand data better.
|
||||
getEventBuilder().reset()
|
||||
.setName("Statistics status changed")
|
||||
.addParam("Enabled", String.valueOf(isEnabled))
|
||||
.getEvent()
|
||||
.post();
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
|
||||
private boolean isActiveUser(Context context, int currentSessionNumber)
|
||||
{
|
||||
return currentSessionNumber >= ACTIVE_USER_MIN_SESSION
|
||||
|| System.currentTimeMillis() - Utils.getInstallationTime(context) >= ACTIVE_USER_MIN_TIME;
|
||||
}
|
||||
|
||||
private int incAndGetSessionsNumber(Context context)
|
||||
{
|
||||
final SharedPreferences statPrefs = getStatPrefs(context);
|
||||
final int currentSessionNumber = statPrefs.getInt(PARAM_SESSIONS, 0) + 1;
|
||||
Utils.applyPrefs(statPrefs.edit().putInt(PARAM_SESSIONS, currentSessionNumber));
|
||||
|
||||
return currentSessionNumber;
|
||||
}
|
||||
|
||||
private SharedPreferences getStatPrefs(Context context)
|
||||
{
|
||||
return context.getSharedPreferences(FILE_STAT_DATA, Context.MODE_PRIVATE);
|
||||
}
|
||||
|
||||
private final static String TAG = "MWMStat";
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package com.mapswithme.util.statistics;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
|
||||
public abstract class StatisticsEngine
|
||||
{
|
||||
public void configure(Context context, Bundle params) {}
|
||||
|
||||
abstract public void onStartSession(Context context);
|
||||
abstract public void onEndSession(Context context);
|
||||
abstract public void postEvent(Event event);
|
||||
}
|
|
@ -10,7 +10,7 @@ import android.view.SurfaceView;
|
|||
|
||||
import com.mapswithme.maps.R;
|
||||
import com.mapswithme.maps.base.MapsWithMeBaseActivity;
|
||||
import com.mapswithme.util.Statistics;
|
||||
import com.mapswithme.util.statistics.Statistics;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
|
|
Loading…
Add table
Reference in a new issue