Skip to content

Commit

Permalink
Global analytics clients
Browse files Browse the repository at this point in the history
  • Loading branch information
budowski committed Dec 12, 2023
1 parent 06c4c38 commit 706b154
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 11 deletions.
Original file line number Diff line number Diff line change
@@ -1,31 +1,35 @@
package org.inaturalist.android;

import android.app.Activity;
import android.app.ActivityManager;
import android.app.Application;
import android.content.ComponentName;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;

import org.json.JSONException;
import org.json.JSONObject;
import org.tinylog.Logger;

import java.util.UUID;

/**
* Encapsulates the analytics client and adds some extra functionality (singleton class)
*/
public class AnalyticsClient {

public static final String EVENT_PARAM_CURRENT_USER = "Current User";

public static final String EVENT_PARAM_VIA = "Via";

public static final String EVENT_PARAM_VALUE_YES = "Yes";
public static final String EVENT_PARAM_VALUE_NO = "No";
public static final String EVENT_PARAM_NEW_SCREEN = "New Screen";

public static final String EVENT_NAME_APP_LAUNCH = "AppLaunch";

public static final String EVENT_NAME_MENU = "Menu";

public static final String EVENT_NAME_CHANGED_SCREEN = "Changed Screen";
public static final String EVENT_NAME_ME = "Me";
public static final String EVENT_NAME_EXPLORE_MAP = "Explore - Map";
public static final String EVENT_NAME_USER_ACTIVITY = "User Activity";
Expand Down Expand Up @@ -170,26 +174,57 @@ public class AnalyticsClient {

// Viewing obs details
public static final String EVENT_NAME_NAVIGATE_OBS_DETAILS = "Navigate - Observations - Details";
public static final String EVENT_NAME_EXPLORE_VIEW_SPECIES = "Explore - View - Species";
public static final String EVENT_NAME_EXPLORE_VIEW_OBSERVER = "Explore - View - Observer";
public static final String EVENT_NAME_EXPLORE_VIEW_IDENTIFIER = "Explore - View - Identifier";
public static final String EVENT_NAME_EXPLORE_VIEW_OBSERVATION = "Explore - View - Observation";
public static final String EVENT_VALUE_EXPLORE_GRID = "Explore Grid";
public static final String EVENT_VALUE_EXPLORE_LIST = "Explore List";
public static final String EVENT_VALUE_UPDATES = "Updates";
public static final String EVENT_VALUE_EXPLORE_MAP = "Explore Map";
public static final String EVENT_VALUE_ME_TAB = "Me Tab";
public static final String EVENT_VALUE_IDENTIFICATIONS_TAB = "Identifications Tab";
public static final String EVENT_VALUE_PROJECT_DETAILS = "Project Details";
public static final String EVENT_NAME_EXPLORE_TAB_OBSERVATIONS = "Explore - Tab - Observations";
public static final String EVENT_NAME_EXPLORE_TAB_SPECIES = "Explore - Tab - Species";
public static final String EVENT_NAME_EXPLORE_TAB_OBSERVERS = "Explore - Tab - Observers";
public static final String EVENT_NAME_EXPLORE_TAB_IDENTIFIERS = "Explore - Tab - Identifiers";
public static final String EVENT_NAME_TAXON_VIEW_MAP = "Taxon - View Map";
public static final String EVENT_NAME_TAXON_VIEW_OBSERVATIONS = "Taxon - View Observations";
public static final String EVENT_NAME_TAXON_VIEW_ON_INAT = "Taxon - View On iNat";
public static final String EVENT_NAME_USER_PROFILE_SEND_MESSAGE = "User Profile - Send Message";
public static final String EVENT_NAME_USER_PROFILE_VIEW_SPECIES = "User Profile - View Species";
public static final String EVENT_NAME_USER_PROFILE_VIEW_TAXON = "User Profile - View Taxon";
public static final String EVENT_NAME_USER_PROFILE_VIEW_OBSERVATIONS = "User Profile - View Observations";
public static final String EVENT_NAME_USER_PROFILE_VIEW_IDENTIFICATIONS = "User Profile - View Identifications";
public static final String EVENT_NAME_USER_PROFILE_VIEW_OBSERVATION = "User Profile - View Observation";
public static final String EVENT_NAME_USER_PROFILE_VIEW_OBSERVATION_VIA_IDENTIFICATION = "User Profile - View Observation Via Identification";

private static final String TAG = "AnalyticsClient";

// Singleton instance
private static AnalyticsClient mAnalyticsClient = null;

private Application mApplication;
private INaturalistApp mApplication;
private Activity mCurrentActivity;
private boolean mDisabled;

private AnalyticsClient(Application application, boolean disabled) {
private String mAnalyticsID;

private AnalyticsClient(INaturalistApp application, boolean disabled) {
mApplication = application;
mDisabled = disabled;

// Generate a random unique ID, to identify the user in an anonymous way
SharedPreferences settings = mApplication.getPrefs();
if (!settings.contains("analytics_id")) {
String analyticsID = UUID.randomUUID().toString();
settings.edit().putString("analytics_id", analyticsID).commit();
}

mAnalyticsID = settings.getString("analytics_id", null);


if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
// Modern way of getting current activity
application.registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
Expand All @@ -205,6 +240,21 @@ public void onActivityStarted(Activity activity) {

@Override
public void onActivityResumed(Activity activity) {

// Log every time the user switches screens (and log via which screen was it made)
if (mCurrentActivity != null) {
try {
JSONObject params = new JSONObject();
String prevActivityName = getActivityName(activity);
String newActivityName = getActivityName(mCurrentActivity);
params.put(EVENT_PARAM_NEW_SCREEN, newActivityName);
params.put(EVENT_PARAM_VIA, prevActivityName);
logEvent(EVENT_NAME_CHANGED_SCREEN, params);
} catch (JSONException e) {
throw new RuntimeException(e);
}
}

mCurrentActivity = activity;
}

Expand Down Expand Up @@ -232,7 +282,7 @@ public void onActivityDestroyed(Activity activity) {
}

// Initializes the analytics client - should be called from the main activity or application class
public static void initAnalyticsClient(Application application, boolean disabled) {
public static void initAnalyticsClient(INaturalistApp application, boolean disabled) {
mAnalyticsClient = new AnalyticsClient(application, disabled);
}

Expand All @@ -259,20 +309,24 @@ public void logEvent(String eventName, JSONObject parameters) {
try {
if (mCurrentActivity != null) {
// Add the via parameter (which indicates the current screen the event was initiated from)
String currentActivityName = getCurrentActivityName();
String currentActivityName = getActivityName(mCurrentActivity);
if (!parameters.has(EVENT_PARAM_VIA)) parameters.put(EVENT_PARAM_VIA, currentActivityName);
}

// Currently we've removed all analytics events (not using a tracker like Mixpanel, etc.)
parameters.put(EVENT_PARAM_CURRENT_USER, mAnalyticsID);

// TODO - in the future, send this event forward

Logger.tag(TAG).info(String.format("Event: %s - params: %s", eventName, parameters));

} catch (JSONException e) {
Logger.tag(TAG).error(e);
}
}

// Returns current activity name
private String getCurrentActivityName() {
String className = mCurrentActivity.getClass().getName();
private String getActivityName(Activity activity) {
String className = activity.getClass().getName();

// Extract just the activity class name (not including the package namespace)
String[] parts = className.split("\\.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -802,6 +802,7 @@ public static void signOut(Context context) {
prefEditor.remove("user_unread_messages");
prefEditor.remove("user_privileges");
prefEditor.remove("muted_users");
prefEditor.remove("analytics_id");
prefEditor.commit();

shouldRestart = !prevLocale.equals("");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,15 @@ public void onPageScrolled(int position, float positionOffset, int positionOffse
@Override
public void onPageSelected(int position) {
mActiveViewType = position;
if (mActiveViewType == VIEW_TYPE_IDENTIFIERS) {
AnalyticsClient.getInstance().logEvent(AnalyticsClient.EVENT_NAME_EXPLORE_TAB_IDENTIFIERS);
} else if (mActiveViewType == VIEW_TYPE_OBSERVATIONS) {
AnalyticsClient.getInstance().logEvent(AnalyticsClient.EVENT_NAME_EXPLORE_TAB_OBSERVATIONS);
} else if (mActiveViewType == VIEW_TYPE_OBSERVERS) {
AnalyticsClient.getInstance().logEvent(AnalyticsClient.EVENT_NAME_EXPLORE_TAB_OBSERVERS);
} else if (mActiveViewType == VIEW_TYPE_SPECIES) {
AnalyticsClient.getInstance().logEvent(AnalyticsClient.EVENT_NAME_EXPLORE_TAB_SPECIES);
}
}

@Override
Expand Down Expand Up @@ -1046,6 +1055,8 @@ public void onItemClick(AdapterView<?> arg0, View view, int position, long arg3)
eventParams.put(AnalyticsClient.EVENT_PARAM_VIA, AnalyticsClient.EVENT_VALUE_EXPLORE_GRID);

AnalyticsClient.getInstance().logEvent(AnalyticsClient.EVENT_NAME_NAVIGATE_OBS_DETAILS, eventParams);

AnalyticsClient.getInstance().logEvent(AnalyticsClient.EVENT_NAME_EXPLORE_VIEW_OBSERVATION);
} catch (JSONException e) {
Logger.tag(TAG).error(e);
}
Expand Down Expand Up @@ -1493,6 +1504,8 @@ public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
intent.putExtra(TaxonActivity.TAXON, new BetterJSONObject(item));
intent.putExtra(TaxonActivity.DOWNLOAD_TAXON, true);
startActivity(intent);

AnalyticsClient.getInstance().logEvent(AnalyticsClient.EVENT_NAME_EXPLORE_VIEW_SPECIES);
}
};

Expand All @@ -1510,6 +1523,8 @@ public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Intent intent = new Intent(ExploreActivity.this, UserProfile.class);
intent.putExtra("user", new BetterJSONObject(item));
startActivity(intent);

AnalyticsClient.getInstance().logEvent(AnalyticsClient.EVENT_NAME_EXPLORE_VIEW_OBSERVER);
}
};
break;
Expand All @@ -1527,6 +1542,8 @@ public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Intent intent = new Intent(ExploreActivity.this, UserProfile.class);
intent.putExtra("user", new BetterJSONObject(item));
startActivity(intent);

AnalyticsClient.getInstance().logEvent(AnalyticsClient.EVENT_NAME_EXPLORE_VIEW_IDENTIFIER);
}
};
break;
Expand Down Expand Up @@ -1604,6 +1621,8 @@ public void run() {
eventParams.put(AnalyticsClient.EVENT_PARAM_VIA, AnalyticsClient.EVENT_VALUE_EXPLORE_MAP);

AnalyticsClient.getInstance().logEvent(AnalyticsClient.EVENT_NAME_NAVIGATE_OBS_DETAILS, eventParams);

AnalyticsClient.getInstance().logEvent(AnalyticsClient.EVENT_NAME_EXPLORE_VIEW_OBSERVATION);
}
} catch (IOException e) {
Logger.tag(TAG).error(e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
import com.viewpagerindicator.CirclePageIndicator;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.tinylog.Logger;

Expand Down Expand Up @@ -727,6 +728,8 @@ public void onMapClick(LatLng latLng) {
intent.putExtra(TaxonMapActivity.MAP_ZOOM, position.zoom);
if (mObservation != null) intent.putExtra(TaxonMapActivity.OBSERVATION, new BetterJSONObject(ObservationUtils.getMinimalObservation(mObservation.getJSONObject())));
startActivity(intent);

AnalyticsClient.getInstance().logEvent(AnalyticsClient.EVENT_NAME_TAXON_VIEW_MAP);
}
});

Expand Down Expand Up @@ -791,6 +794,8 @@ public void onClick(View v) {
intent1.putExtra(ExploreActivity.SEARCH_FILTERS, searchFilters);
intent1.putExtra(ExploreActivity.ACTIVE_TAB, ExploreActivity.VIEW_TYPE_OBSERVATIONS);
startActivity(intent1);

AnalyticsClient.getInstance().logEvent(AnalyticsClient.EVENT_NAME_TAXON_VIEW_OBSERVATIONS);
});


Expand All @@ -804,6 +809,8 @@ public void onClick(View v) {
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(taxonUrl));
startActivity(i);

AnalyticsClient.getInstance().logEvent(AnalyticsClient.EVENT_NAME_TAXON_VIEW_ON_INAT);
}
});

Expand Down
11 changes: 11 additions & 0 deletions iNaturalist/src/main/java/org/inaturalist/android/UserProfile.java
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ protected void onCreate(Bundle savedInstanceState) {
intent1.putExtra(NewMessageActivity.USER_ID, mUser.getInt("id"));
intent1.putExtra(NewMessageActivity.USERNAME, mUser.getString("login"));
startActivityForResult(intent1, NEW_MESSAGE_REQUEST_CODE);

AnalyticsClient.getInstance().logEvent(AnalyticsClient.EVENT_NAME_USER_PROFILE_SEND_MESSAGE);
});

mSpeciesList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
Expand All @@ -187,6 +189,8 @@ public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
intent.putExtra(TaxonActivity.TAXON, new BetterJSONObject(item));
intent.putExtra(TaxonActivity.DOWNLOAD_TAXON, true);
startActivity(intent);

AnalyticsClient.getInstance().logEvent(AnalyticsClient.EVENT_NAME_USER_PROFILE_VIEW_TAXON);
}
});

Expand All @@ -205,6 +209,8 @@ public void onItemClick(AdapterView<?> arg0, View view, int position, long arg3)
intent.putExtra("read_only", true);
intent.putExtra("reload", true);
startActivity(intent);

AnalyticsClient.getInstance().logEvent(AnalyticsClient.EVENT_NAME_USER_PROFILE_VIEW_OBSERVATION);
}
});

Expand Down Expand Up @@ -259,10 +265,13 @@ public void onClick(View view) {

if (view == mShowMoreObservations) {
activeTab = ExploreActivity.VIEW_TYPE_OBSERVATIONS;
AnalyticsClient.getInstance().logEvent(AnalyticsClient.EVENT_NAME_USER_PROFILE_VIEW_OBSERVATIONS);
} else if (view == mShowMoreSpecies) {
activeTab = ExploreActivity.VIEW_TYPE_SPECIES;
AnalyticsClient.getInstance().logEvent(AnalyticsClient.EVENT_NAME_USER_PROFILE_VIEW_SPECIES);
} else if (view == mShowMoreIdentifications) {
activeTab = ExploreActivity.VIEW_TYPE_IDENTIFIERS;
AnalyticsClient.getInstance().logEvent(AnalyticsClient.EVENT_NAME_USER_PROFILE_VIEW_IDENTIFICATIONS);
}

intent.putExtra(ExploreActivity.ACTIVE_TAB, activeTab);
Expand Down Expand Up @@ -714,6 +723,8 @@ public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
intent.putExtra("read_only", true);
intent.putExtra("reload", true);
startActivity(intent);

AnalyticsClient.getInstance().logEvent(AnalyticsClient.EVENT_NAME_USER_PROFILE_VIEW_OBSERVATION_VIA_IDENTIFICATION);
}
});

Expand Down

0 comments on commit 706b154

Please sign in to comment.