com.mapbox.mapboxsdk.telemetry.MapboxEventManager Maven / Gradle / Ivy
package com.mapbox.mapboxsdk.telemetry;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.location.Location;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.AsyncTask;
import android.os.BatteryManager;
import android.os.Build;
import android.support.annotation.NonNull;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.WindowManager;
import com.mapbox.mapboxsdk.BuildConfig;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.location.LocationServices;
import org.json.JSONArray;
import org.json.JSONObject;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Hashtable;
import java.util.List;
import java.util.Locale;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;
import java.util.Vector;
import okhttp3.CertificatePinner;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
/**
* Singleton control center for managing Telemetry Data.
* Primary access is via MapboxEventManager.getMapboxEventManager()
*/
public class MapboxEventManager {
private static final String TAG = "MapboxEventManager";
private static MapboxEventManager mapboxEventManager = null;
private boolean telemetryEnabled;
private final Vector> events = new Vector<>();
private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.US);
private Context context = null;
private String accessToken = null;
private String eventsURL = MapboxEvent.MAPBOX_EVENTS_BASE_URL;
private String userAgent = BuildConfig.MAPBOX_EVENTS_USER_AGENT_BASE;
private Intent batteryStatus = null;
private final String operatingSystem = "Android - " + Build.VERSION.RELEASE;
private DisplayMetrics displayMetrics = null;
private String mapboxVendorId = null;
private String mapboxSessionId = null;
private long mapboxSessionIdLastSet = 0;
private static long hourInMillis = 1000 * 60 * 60;
private static long flushDelayInitialInMillis = 1000 * 10; // 10 Seconds
private static long flushDelayInMillis = 1000 * 60 * 2; // 2 Minutes
private static final int SESSION_ID_ROTATION_HOURS = 24;
private static MessageDigest messageDigest = null;
private Timer timer = null;
/**
* Private Constructor for configuring the single instance per app.
*/
private MapboxEventManager() {
super();
}
/**
* Internal setup of MapboxEventsManager. It needs to be called once before @link MapboxEventManager#getMapboxEventManager
*
* This allows for a cleaner getMapboxEventManager() that doesn't require context and accessToken
*
* @param context The context associated with MapView
* @param accessToken The accessToken to load MapView
*/
public void initialize(@NonNull Context context, @NonNull String accessToken) {
this.context = context.getApplicationContext();
this.accessToken = accessToken;
// Setup Message Digest
try {
messageDigest = MessageDigest.getInstance("SHA-1");
} catch (NoSuchAlgorithmException e) {
Log.w(TAG, "Error getting Encryption Algorithm: " + e);
}
SharedPreferences prefs = context.getSharedPreferences(MapboxConstants.MAPBOX_SHARED_PREFERENCES_FILE, Context.MODE_PRIVATE);
// Determine if Telemetry Should Be Enabled
setTelemetryEnabled(prefs.getBoolean(MapboxConstants.MAPBOX_SHARED_PREFERENCE_KEY_TELEMETRY_ENABLED, true));
// Load / Create Vendor Id
if (prefs.contains(MapboxConstants.MAPBOX_SHARED_PREFERENCE_KEY_VENDORID)) {
mapboxVendorId = prefs.getString(MapboxConstants.MAPBOX_SHARED_PREFERENCE_KEY_VENDORID, "");
}
if (TextUtils.isEmpty(mapboxVendorId)) {
String vendorId = UUID.randomUUID().toString();
mapboxVendorId = encodeString(vendorId);
SharedPreferences.Editor editor = prefs.edit();
editor.putString(MapboxConstants.MAPBOX_SHARED_PREFERENCE_KEY_VENDORID, mapboxVendorId);
editor.apply();
editor.commit();
}
// Create Initial Session Id
rotateSessionId();
// Get DisplayMetrics Setup
displayMetrics = new DisplayMetrics();
((WindowManager)context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getMetrics(displayMetrics);
// Check for Staging Server Information
try {
ApplicationInfo appInfo = context.getPackageManager().getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA);
String stagingURL = appInfo.metaData.getString(MapboxConstants.KEY_META_DATA_STAGING_SERVER);
String stagingAccessToken = appInfo.metaData.getString(MapboxConstants.KEY_META_DATA_STAGING_ACCESS_TOKEN);
String appName = context.getPackageManager().getApplicationLabel(appInfo).toString();
PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
String versionName = packageInfo.versionName;
int versionCode = packageInfo.versionCode;
if (!TextUtils.isEmpty(stagingURL)) {
eventsURL = stagingURL;
}
if (!TextUtils.isEmpty(stagingAccessToken)) {
this.accessToken = stagingAccessToken;
}
// Build User Agent
if (TextUtils.equals(userAgent, BuildConfig.MAPBOX_EVENTS_USER_AGENT_BASE) && !TextUtils.isEmpty(appName) && !TextUtils.isEmpty(versionName)) {
userAgent = appName + "/" + versionName + "/" + versionCode + " " + userAgent;
}
} catch (Exception e) {
Log.e(TAG, "Error Trying to load Staging Credentials: " + e.toString());
}
// Register for battery updates
IntentFilter iFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
batteryStatus = context.registerReceiver(null, iFilter);
}
/**
* Primary Access method using Singleton pattern
*
* @return MapboxEventManager
*/
public static MapboxEventManager getMapboxEventManager() {
if (mapboxEventManager == null) {
mapboxEventManager = new MapboxEventManager();
}
return mapboxEventManager;
}
public static String generateCreateDate() {
return dateFormat.format(new Date());
}
public boolean isTelemetryEnabled() {
return telemetryEnabled;
}
/**
* Enables / Disables Telemetry
* @param telemetryEnabled True to start telemetry, false to stop it
*/
public void setTelemetryEnabled(boolean telemetryEnabled) {
if (this.telemetryEnabled == telemetryEnabled) {
Log.d(TAG, "No need to start / stop telemetry as it's already in that state.");
return;
}
if (telemetryEnabled) {
Log.d(TAG, "Starting Telemetry Up!");
// Start It Up
context.startService(new Intent(context, TelemetryService.class));
// Make sure Ambient Mode is started at a minimum
if (LocationServices.getLocationServices(context).isGPSEnabled()) {
LocationServices.getLocationServices(context).toggleGPS(false);
}
// Manage Timer Flush
timer = new Timer();
timer.schedule(new FlushEventsTimerTask(), flushDelayInitialInMillis, flushDelayInMillis);
} else {
Log.d(TAG, "Shutting Telemetry Down");
// Shut It Down
events.removeAllElements();
context.stopService(new Intent(context, TelemetryService.class));
if (timer != null) {
timer.cancel();
timer = null;
}
}
// Persist
this.telemetryEnabled = telemetryEnabled;
SharedPreferences prefs = context.getSharedPreferences(MapboxConstants.MAPBOX_SHARED_PREFERENCES_FILE, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean(MapboxConstants.MAPBOX_SHARED_PREFERENCE_KEY_TELEMETRY_ENABLED, telemetryEnabled);
editor.apply();
editor.commit();
}
/**
* Immediately attempt to send all events data in the queue to the server.
*
* NOTE: Permission set to package private to enable only telemetry code to use this.
*/
void flushEventsQueueImmediately() {
Log.i(TAG, "flushEventsQueueImmediately() called...");
new FlushTheEventsTask().execute();
}
/**
* Adds a Location Event to the system for processing
* @param location Location event
*/
public void addLocationEvent(Location location) {
// Add Location even to queue
Hashtable event = new Hashtable<>();
event.put(MapboxEvent.ATTRIBUTE_EVENT, MapboxEvent.TYPE_LOCATION);
event.put(MapboxEvent.ATTRIBUTE_CREATED, generateCreateDate());
event.put(MapboxEvent.ATTRIBUTE_SOURCE, MapboxEvent.SOURCE_MAPBOX);
event.put(MapboxEvent.ATTRIBUTE_SESSION_ID, encodeString(mapboxSessionId));
event.put(MapboxEvent.KEY_LATITUDE, location.getLatitude());
event.put(MapboxEvent.KEY_LONGITUDE, location.getLongitude());
event.put(MapboxEvent.KEY_ALTITUDE, location.getAltitude());
event.put(MapboxEvent.ATTRIBUTE_OPERATING_SYSTEM, operatingSystem);
event.put(MapboxEvent.ATTRIBUTE_APPLICATION_STATE, getApplicationState());
events.add(event);
rotateSessionId();
}
/**
* Push Interactive Events to the system for processing
*
* @param eventWithAttributes Event with attributes
*/
public void pushEvent(Hashtable eventWithAttributes) {
if (context == null || accessToken == null) {
return;
}
if (eventWithAttributes == null) {
return;
}
String eventType = (String) eventWithAttributes.get(MapboxEvent.ATTRIBUTE_EVENT);
if (TextUtils.isEmpty(eventType)) {
return;
}
if (eventType.equalsIgnoreCase(MapboxEvent.TYPE_MAP_LOAD)) {
// Map Load Data Model
eventWithAttributes.put(MapboxEvent.ATTRIBUTE_USERID, mapboxVendorId);
eventWithAttributes.put(MapboxEvent.ATTRIBUTE_MODEL, Build.MODEL);
eventWithAttributes.put(MapboxEvent.ATTRIBUTE_OPERATING_SYSTEM, operatingSystem);
eventWithAttributes.put(MapboxEvent.ATTRIBUTE_RESOLUTION, displayMetrics.density);
eventWithAttributes.put(MapboxEvent.ATTRIBUTE_ACCESSIBILITY_FONT_SCALE, getAccesibilityFontScaleSize());
eventWithAttributes.put(MapboxEvent.ATTRIBUTE_ORIENTATION, getOrientation());
eventWithAttributes.put(MapboxEvent.ATTRIBUTE_BATTERY_LEVEL, getBatteryLevel());
eventWithAttributes.put(MapboxEvent.ATTRIBUTE_PLUGGED_IN, isPluggedIn());
eventWithAttributes.put(MapboxEvent.ATTRIBUTE_CARRIER, getCellularCarrier());
eventWithAttributes.put(MapboxEvent.ATTRIBUTE_CELLULAR_NETWORK_TYPE, getCellularNetworkType());
eventWithAttributes.put(MapboxEvent.ATTRIBUTE_WIFI, getConnectedToWifi());
// Put Map Load on events before Turnstile clears it
events.add(eventWithAttributes);
// Turnstile
pushTurnstileEvent();
// Return immediately to avoid double adding of event
return;
} else if (eventType.equalsIgnoreCase(MapboxEvent.TYPE_MAP_CLICK)) {
eventWithAttributes.put(MapboxEvent.ATTRIBUTE_ORIENTATION, getOrientation());
eventWithAttributes.put(MapboxEvent.ATTRIBUTE_BATTERY_LEVEL, getBatteryLevel());
eventWithAttributes.put(MapboxEvent.ATTRIBUTE_PLUGGED_IN, isPluggedIn());
eventWithAttributes.put(MapboxEvent.ATTRIBUTE_CARRIER, getCellularCarrier());
eventWithAttributes.put(MapboxEvent.ATTRIBUTE_CELLULAR_NETWORK_TYPE, getCellularNetworkType());
eventWithAttributes.put(MapboxEvent.ATTRIBUTE_WIFI, getConnectedToWifi());
} else if (eventType.equalsIgnoreCase(MapboxEvent.TYPE_MAP_DRAGEND)) {
eventWithAttributes.put(MapboxEvent.ATTRIBUTE_ORIENTATION, getOrientation());
eventWithAttributes.put(MapboxEvent.ATTRIBUTE_BATTERY_LEVEL, getBatteryLevel());
eventWithAttributes.put(MapboxEvent.ATTRIBUTE_PLUGGED_IN, isPluggedIn());
eventWithAttributes.put(MapboxEvent.ATTRIBUTE_CARRIER, getCellularCarrier());
eventWithAttributes.put(MapboxEvent.ATTRIBUTE_CELLULAR_NETWORK_TYPE, getCellularNetworkType());
eventWithAttributes.put(MapboxEvent.ATTRIBUTE_WIFI, getConnectedToWifi());
} else {
Log.w(TAG, "This is not an event type in the Events Data Model.");
return;
}
events.add(eventWithAttributes);
}
/**
* Pushes turnstile event for internal billing purposes
*/
private void pushTurnstileEvent() {
Hashtable event = new Hashtable<>();
event.put(MapboxEvent.ATTRIBUTE_EVENT, MapboxEvent.TYPE_TURNSTILE);
event.put(MapboxEvent.ATTRIBUTE_CREATED, generateCreateDate());
event.put(MapboxEvent.ATTRIBUTE_USERID, mapboxVendorId);
event.put(MapboxEvent.ATTRIBUTE_ENABLED_TELEMETRY, telemetryEnabled);
events.add(event);
// Send to Server Immediately
flushEventsQueueImmediately();
Log.d(TAG, "turnstile event pushed.");
}
/**
* SHA-1 Encoding for strings
* @param string String to encode
* @return String encoded if no error, original string if error
*/
private String encodeString(String string) {
try {
if (messageDigest != null) {
messageDigest.reset();
messageDigest.update(string.getBytes("UTF-8"));
byte[] bytes = messageDigest.digest();
// Get the Hex version of the digest
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append( String.format("%02X", b) );
}
String hex = sb.toString();
return hex;
}
} catch (Exception e) {
Log.w(TAG, "Error encoding string, will return in original form." + e);
}
return string;
}
/**
* Changes Session Id based on time boundary
*/
private void rotateSessionId() {
long now = System.currentTimeMillis();
if (now - mapboxSessionIdLastSet > (SESSION_ID_ROTATION_HOURS * hourInMillis)) {
mapboxSessionId = UUID.randomUUID().toString();
mapboxSessionIdLastSet = System.currentTimeMillis();
}
}
private String getOrientation() {
switch (context.getResources().getConfiguration().orientation) {
case Configuration.ORIENTATION_LANDSCAPE:
return "Landscape";
case Configuration.ORIENTATION_PORTRAIT:
return "Portrait";
default:
return "";
}
}
private int getBatteryLevel() {
int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
return Math.round((level / (float)scale) * 100);
}
/**
* Determine if device is plugged in to power via USB or AC or not.
*
* http://developer.android.com/reference/android/os/BatteryManager.html#EXTRA_PLUGGED
* @return true if plugged in, false if not
*/
private boolean isPluggedIn() {
int chargePlug = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
if (chargePlug == BatteryManager.BATTERY_PLUGGED_USB || chargePlug == BatteryManager.BATTERY_PLUGGED_AC) {
return true;
}
return false;
}
private String getApplicationState() {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List appProcesses = activityManager.getRunningAppProcesses();
if (appProcesses == null) {
return "";
}
final String packageName = context.getPackageName();
for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
if (appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND && appProcess.processName.equals(packageName)) {
return "Foreground";
}
}
return "Background";
}
private float getAccesibilityFontScaleSize() {
// Values
// Small = 0.85
// Normal = 1.0
// Large = 1.15
// Huge = 1.3
return context.getResources().getConfiguration().fontScale;
}
private String getCellularCarrier() {
TelephonyManager manager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
String carrierName = manager.getNetworkOperatorName();
if (TextUtils.isEmpty(carrierName)) {
carrierName = "";
}
return carrierName;
}
private String getCellularNetworkType () {
TelephonyManager manager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
switch (manager.getNetworkType()) {
case TelephonyManager.NETWORK_TYPE_1xRTT:
return "1xRTT";
case TelephonyManager.NETWORK_TYPE_CDMA:
return "CDMA";
case TelephonyManager.NETWORK_TYPE_EDGE:
return "EDGE";
case TelephonyManager.NETWORK_TYPE_EHRPD:
return "EHRPD";
case TelephonyManager.NETWORK_TYPE_EVDO_0:
return "EVDO_0";
case TelephonyManager.NETWORK_TYPE_EVDO_A:
return "EVDO_A";
case TelephonyManager.NETWORK_TYPE_EVDO_B:
return "EVDO_B";
case TelephonyManager.NETWORK_TYPE_GPRS:
return "GPRS";
case TelephonyManager.NETWORK_TYPE_HSDPA:
return "HSDPA";
case TelephonyManager.NETWORK_TYPE_HSPA:
return "HSPA";
case TelephonyManager.NETWORK_TYPE_HSPAP:
return "HSPAP";
case TelephonyManager.NETWORK_TYPE_HSUPA:
return "HSUPA";
case TelephonyManager.NETWORK_TYPE_IDEN:
return "IDEN";
case TelephonyManager.NETWORK_TYPE_LTE:
return "LTE";
case TelephonyManager.NETWORK_TYPE_UMTS:
return "UMTS";
case TelephonyManager.NETWORK_TYPE_UNKNOWN:
return "Unknown";
default:
return "";
}
}
public Boolean getConnectedToWifi() {
Boolean status = false;
WifiManager wifiMgr = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
if (wifiMgr.isWifiEnabled()) {
try {
WifiInfo wifiInfo = wifiMgr.getConnectionInfo();
if (wifiInfo.getNetworkId() != -1){
status = true;
}
} catch (Exception e) {
Log.w(TAG, "Error getting Wifi Connection Status: " + e);
status = false;
}
}
return status;
}
/**
* Task responsible for converting stored events and sending them to the server
*/
private class FlushTheEventsTask extends AsyncTask {
@Override
protected Void doInBackground(Void... voids) {
if (events.size() < 1) {
Log.d(TAG, "No events in the queue to send so returning.");
return null;
}
// Check for NetworkConnectivity
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = cm.getActiveNetworkInfo();
if (networkInfo == null || !networkInfo.isConnected()) {
Log.w(TAG, "Not connected to network, so returning without attempting to send events");
return null;
}
try {
// Send data
// =========
JSONArray jsonArray = new JSONArray();
for (Hashtable evt : events) {
JSONObject jsonObject = new JSONObject();
// Build the JSON but only if there's a value for it in the evt
jsonObject.putOpt(MapboxEvent.ATTRIBUTE_EVENT, evt.get(MapboxEvent.ATTRIBUTE_EVENT));
jsonObject.putOpt(MapboxEvent.ATTRIBUTE_CREATED, evt.get(MapboxEvent.ATTRIBUTE_CREATED));
jsonObject.putOpt(MapboxEvent.ATTRIBUTE_USERID, evt.get(MapboxEvent.ATTRIBUTE_USERID));
jsonObject.putOpt(MapboxEvent.ATTRIBUTE_ENABLED_TELEMETRY, evt.get(MapboxEvent.ATTRIBUTE_ENABLED_TELEMETRY));
jsonObject.putOpt(MapboxEvent.ATTRIBUTE_SOURCE, evt.get(MapboxEvent.ATTRIBUTE_SOURCE));
jsonObject.putOpt(MapboxEvent.ATTRIBUTE_SESSION_ID, evt.get(MapboxEvent.ATTRIBUTE_SESSION_ID));
jsonObject.putOpt(MapboxEvent.KEY_LATITUDE, evt.get(MapboxEvent.KEY_LATITUDE));
jsonObject.putOpt(MapboxEvent.KEY_LONGITUDE, evt.get(MapboxEvent.KEY_LONGITUDE));
jsonObject.putOpt(MapboxEvent.KEY_ALTITUDE, evt.get(MapboxEvent.KEY_ALTITUDE));
jsonObject.putOpt(MapboxEvent.KEY_ZOOM, evt.get(MapboxEvent.KEY_ZOOM));
jsonObject.putOpt(MapboxEvent.ATTRIBUTE_OPERATING_SYSTEM, evt.get(MapboxEvent.ATTRIBUTE_OPERATING_SYSTEM));
jsonObject.putOpt(MapboxEvent.ATTRIBUTE_USERID, evt.get(MapboxEvent.ATTRIBUTE_USERID));
jsonObject.putOpt(MapboxEvent.ATTRIBUTE_MODEL, evt.get(MapboxEvent.ATTRIBUTE_MODEL));
jsonObject.putOpt(MapboxEvent.ATTRIBUTE_RESOLUTION, evt.get(MapboxEvent.ATTRIBUTE_RESOLUTION));
jsonObject.putOpt(MapboxEvent.ATTRIBUTE_ACCESSIBILITY_FONT_SCALE, evt.get(MapboxEvent.ATTRIBUTE_ACCESSIBILITY_FONT_SCALE));
jsonObject.putOpt(MapboxEvent.ATTRIBUTE_BATTERY_LEVEL, evt.get(MapboxEvent.ATTRIBUTE_BATTERY_LEVEL));
jsonObject.putOpt(MapboxEvent.ATTRIBUTE_PLUGGED_IN, evt.get(MapboxEvent.ATTRIBUTE_PLUGGED_IN));
jsonObject.putOpt(MapboxEvent.ATTRIBUTE_WIFI, evt.get(MapboxEvent.ATTRIBUTE_WIFI));
// Special Cases where empty string is denoting null and therefore should not be sent at all
// This arises as thread safe Hashtable does not accept null values (nor keys)
if (evt.containsKey(MapboxEvent.ATTRIBUTE_ORIENTATION)) {
String orientation = (String)evt.get(MapboxEvent.ATTRIBUTE_ORIENTATION);
if (!TextUtils.isEmpty(orientation)) {
jsonObject.putOpt(MapboxEvent.ATTRIBUTE_ORIENTATION, orientation);
}
}
if (evt.containsKey(MapboxEvent.ATTRIBUTE_CARRIER)) {
String carrier = (String)evt.get(MapboxEvent.ATTRIBUTE_CARRIER);
if (!TextUtils.isEmpty(carrier)) {
jsonObject.putOpt(MapboxEvent.ATTRIBUTE_CARRIER, carrier);
}
}
if (evt.containsKey(MapboxEvent.ATTRIBUTE_APPLICATION_STATE)) {
String appState = (String)evt.get(MapboxEvent.ATTRIBUTE_APPLICATION_STATE);
if (!TextUtils.isEmpty(appState)) {
jsonObject.putOpt(MapboxEvent.ATTRIBUTE_APPLICATION_STATE, evt.get(MapboxEvent.ATTRIBUTE_APPLICATION_STATE));
}
}
// Special Cases where null has to be passed if no value exists
// Requires using put() instead of putOpt()
String eventType = (String)evt.get(MapboxEvent.ATTRIBUTE_EVENT);
if (!TextUtils.isEmpty(eventType) && eventType.equalsIgnoreCase(MapboxEvent.TYPE_MAP_CLICK)) {
jsonObject.put(MapboxEvent.KEY_GESTURE_ID, evt.get(MapboxEvent.KEY_GESTURE_ID));
}
if (evt.containsKey(MapboxEvent.ATTRIBUTE_CELLULAR_NETWORK_TYPE)) {
String cellularNetworkType = (String)evt.get(MapboxEvent.ATTRIBUTE_CELLULAR_NETWORK_TYPE);
if (TextUtils.isEmpty(cellularNetworkType)) {
jsonObject.put(MapboxEvent.ATTRIBUTE_CELLULAR_NETWORK_TYPE, null);
} else {
jsonObject.put(MapboxEvent.ATTRIBUTE_CELLULAR_NETWORK_TYPE, evt.get(MapboxEvent.ATTRIBUTE_CELLULAR_NETWORK_TYPE));
}
}
jsonArray.put(jsonObject);
}
// Based on http://square.github.io/okhttp/3.x/okhttp/okhttp3/CertificatePinner.html
CertificatePinner certificatePinner = new CertificatePinner.Builder()
// Staging - Geotrust
.add("cloudfront-staging.tilestream.net", "sha256/kR9ysyN/lzBl/ecearDERV7qO7xqSN4jt6XuQjIVL0I=")
.add("cloudfront-staging.tilestream.net", "sha256/sPbNCVpVasMJxps3IqFfLTRKkVnRCLrTlZVc5kspqlkw=")
.add("cloudfront-staging.tilestream.net", "sha256/h6801m+z8v3zbgkRHpq6L29Esgfzhj89C1SyUCOQmqU=")
// Prod - Geotrust
.add("api.mapbox.com", "sha256/svaiYM/ZVIfxC+CMDe4kj1KsviQmzyZ9To8nQqUJwFI=")
.add("api.mapbox.com", "sha256/owrR9U9FWDWtrFF+myoRIu75JwU4sJwzvhCNLZoY37g=")
.add("api.mapbox.com", "sha256/SQVGZiOrQXi+kqxcvWWE96HhfydlLVqFr4lQTqI5qqo=")
// Prod - DigiCert
.add("api.mapbox.com", "sha256/JL+uwAwpA2U1UVl/AFdZy1ZnvkZJ1P1hRfmfPaPVSLU=")
.add("api.mapbox.com", "sha256/RRM1dGqnDFsCJXBTHky16vi1obOlCgFFn/yOhI/y+ho=")
.add("api.mapbox.com", "sha256/WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18=")
.build();
OkHttpClient client = new OkHttpClient.Builder().certificatePinner(certificatePinner).build();
RequestBody body = RequestBody.create(JSON, jsonArray.toString());
String url = eventsURL + "/events/v2?access_token=" + accessToken;
Request request = new Request.Builder()
.url(url)
.header("User-Agent", userAgent)
.post(body)
.build();
Response response = client.newCall(request).execute();
Log.d(TAG, "response code = " + response.code() + " for events " + events.size());
// Reset Events
// ============
events.removeAllElements();
} catch (Exception e) {
Log.e(TAG, "FlushTheEventsTask borked: " + e);
e.printStackTrace();
}
return null;
}
}
/**
* TimerTask responsible for sending event data to server
*/
private class FlushEventsTimerTask extends TimerTask {
/**
* The task to run should be specified in the implementation of the {@code run()}
* method.
*/
@Override
public void run() {
new FlushTheEventsTask().execute();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy