mirror of https://github.com/tasks/tasks
Remove analytics
* Remove findbugs * Remove localytics * Remove crittercism * Remove anonymous statistics menu entry * Remove coarse location permissionpull/14/head
parent
d0ee6fe1ff
commit
79313d1b0d
@ -1,9 +0,0 @@
|
||||
<component name="libraryTable">
|
||||
<library name="crittercism">
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/astrid/libs/crittercism_v3_0_7_sdkonly.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
@ -1,9 +0,0 @@
|
||||
<component name="libraryTable">
|
||||
<library name="findbugs-annotations">
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/astrid/libs/findbugs-annotations.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
@ -1,96 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2012 Todoroo Inc
|
||||
*
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
package com.localytics.android;
|
||||
|
||||
import android.text.format.DateUtils;
|
||||
|
||||
/**
|
||||
* Build constants for the Localytics library.
|
||||
* <p>
|
||||
* This is not a public API.
|
||||
*/
|
||||
/* package */final class Constants
|
||||
{
|
||||
|
||||
/**
|
||||
* Version number of this library. This number is primarily important in terms of changes to the upload format.
|
||||
*/
|
||||
//@formatter:off
|
||||
/*
|
||||
* Version history:
|
||||
*
|
||||
* 1.6: Fixed network type reporting. Added reporting of app signature, device SDK level, device manufacturer, serial number.
|
||||
* 2.0: New upload format.
|
||||
*/
|
||||
//@formatter:on
|
||||
public static final String LOCALYTICS_CLIENT_LIBRARY_VERSION = "android_2.2"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* The package name of the Localytics library.
|
||||
*/
|
||||
/*
|
||||
* Note: This value cannot be changed without significant consequences to the data in the database.
|
||||
*/
|
||||
public static final String LOCALYTICS_PACKAGE_NAME = "com.localytics.android"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Maximum number of sessions to store on disk.
|
||||
*/
|
||||
public static final int MAX_NUM_SESSIONS = 10;
|
||||
|
||||
/**
|
||||
* Maximum number of attributes per event session.
|
||||
*/
|
||||
public static final int MAX_NUM_ATTRIBUTES = 10;
|
||||
|
||||
/**
|
||||
* Maximum characters in an event name or attribute key/value.
|
||||
*/
|
||||
public static final int MAX_NAME_LENGTH = 128;
|
||||
|
||||
/**
|
||||
* Milliseconds after which a session is considered closed and cannot be reattached to.
|
||||
* <p>
|
||||
* For example, if the user opens an app, presses home, and opens the app again in less than {@link #SESSION_EXPIRATION}
|
||||
* milliseconds, that will count as one session rather than two sessions.
|
||||
*/
|
||||
public static long SESSION_EXPIRATION = 15 * DateUtils.SECOND_IN_MILLIS;
|
||||
|
||||
/**
|
||||
* logcat log tag
|
||||
*/
|
||||
public static final String LOG_TAG = "Localytics"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Boolean indicating whether logcat messages are enabled.
|
||||
* <p>
|
||||
* Before releasing a production version of an app, this should be set to false for privacy and performance reasons. When
|
||||
* logging is enabled, sensitive information such as the device ID may be printed to the log.
|
||||
*/
|
||||
public static boolean IS_LOGGABLE = false;
|
||||
|
||||
/**
|
||||
* Flag indicating whether runtime method parameter checking is performed.
|
||||
*/
|
||||
public static boolean ENABLE_PARAMETER_CHECKING = true;
|
||||
|
||||
/**
|
||||
* Cached copy of the current Android API level
|
||||
*
|
||||
* @see DatapointHelper#getApiLevel()
|
||||
*/
|
||||
/*package*/ static final int CURRENT_API_LEVEL = DatapointHelper.getApiLevel();
|
||||
|
||||
/**
|
||||
* Private constructor prevents instantiation
|
||||
*
|
||||
* @throws UnsupportedOperationException because this class cannot be instantiated.
|
||||
*/
|
||||
private Constants()
|
||||
{
|
||||
throw new UnsupportedOperationException("This class is non-instantiable"); //$NON-NLS-1$
|
||||
}
|
||||
}
|
@ -1,392 +0,0 @@
|
||||
//@formatter:off
|
||||
/**
|
||||
* DatapointHelper.java Copyright (C) 2011 Char Software Inc., DBA Localytics This code is provided under the Localytics Modified
|
||||
* BSD License. A copy of this license has been distributed in a file called LICENSE with this source code. Please visit
|
||||
* www.localytics.com for more information.
|
||||
*/
|
||||
//@formatter:on
|
||||
|
||||
package com.localytics.android;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.math.BigInteger;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import android.Manifest.permission;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo;
|
||||
import android.os.Build;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Provides a number of static functions to aid in the collection and formatting of datapoints.
|
||||
* <p>
|
||||
* Note: this is not a public API.
|
||||
*/
|
||||
/* package */final class DatapointHelper
|
||||
{
|
||||
/**
|
||||
* AndroidID known to be duplicated across many devices due to manufacturer bugs.
|
||||
*/
|
||||
private static final String INVALID_ANDROID_ID = "9774d56d682e549c"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* The path to the device_id file in previous versions of the Localytics library
|
||||
*/
|
||||
private static final String LEGACY_DEVICE_ID_FILE = "/localytics/device_id"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Private constructor prevents instantiation
|
||||
*
|
||||
* @throws UnsupportedOperationException because this class cannot be instantiated.
|
||||
*/
|
||||
private DatapointHelper()
|
||||
{
|
||||
throw new UnsupportedOperationException("This class is non-instantiable"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* @return current Android API level.
|
||||
*/
|
||||
/* package */static int getApiLevel()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Although the Build.VERSION.SDK field has existed since API 1, it is deprecated and could be removed
|
||||
// in the future. Therefore use reflection to retrieve it for maximum forward compatibility.
|
||||
final Class<?> buildClass = Build.VERSION.class;
|
||||
final String sdkString = (String) buildClass.getField("SDK").get(null); //$NON-NLS-1$
|
||||
return Integer.parseInt(sdkString);
|
||||
}
|
||||
catch (final Exception e)
|
||||
{
|
||||
Log.w(Constants.LOG_TAG, "Caught exception", e); //$NON-NLS-1$
|
||||
|
||||
// Although probably not necessary, protects from the aforementioned deprecation
|
||||
try
|
||||
{
|
||||
final Class<?> buildClass = Build.VERSION.class;
|
||||
return buildClass.getField("SDK_INT").getInt(null); //$NON-NLS-1$
|
||||
}
|
||||
catch (final Exception ignore)
|
||||
{
|
||||
if (Constants.IS_LOGGABLE)
|
||||
{
|
||||
Log.w(Constants.LOG_TAG, "Caught exception", ignore); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Worse-case scenario, assume Cupcake
|
||||
return 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a 1-way hashed value of the device's Android ID. This value is encoded using a SHA-256 one way hash and therefore
|
||||
* cannot be used to determine what device this data came from.
|
||||
*
|
||||
* @param context The context used to access the settings resolver
|
||||
* @return An 1-way hashed version of the {@link android.provider.Settings.Secure#ANDROID_ID}. May return null if an Android
|
||||
* ID or the hashing algorithm is not available.
|
||||
*/
|
||||
public static String getAndroidIdHashOrNull(final Context context)
|
||||
{
|
||||
// Make sure a legacy version of the SDK didn't leave behind a device ID.
|
||||
// If it did, this ID must be used to keep user counts accurate
|
||||
final File fp = new File(context.getFilesDir() + LEGACY_DEVICE_ID_FILE);
|
||||
if (fp.exists() && fp.length() > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
BufferedReader reader = null;
|
||||
try
|
||||
{
|
||||
final char[] buf = new char[100];
|
||||
int numRead;
|
||||
reader = new BufferedReader(new FileReader(fp), 128);
|
||||
numRead = reader.read(buf);
|
||||
final String deviceId = String.copyValueOf(buf, 0, numRead);
|
||||
reader.close();
|
||||
return deviceId;
|
||||
}
|
||||
catch (final FileNotFoundException e)
|
||||
{
|
||||
if (Constants.IS_LOGGABLE)
|
||||
{
|
||||
Log.w(Constants.LOG_TAG, "Caught exception", e); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (null != reader)
|
||||
{
|
||||
reader.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (final IOException e)
|
||||
{
|
||||
if (Constants.IS_LOGGABLE)
|
||||
{
|
||||
Log.w(Constants.LOG_TAG, "Caught exception", e); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final String androidId = android.provider.Settings.Secure.getString(context.getContentResolver(), android.provider.Settings.Secure.ANDROID_ID);
|
||||
if (androidId == null || androidId.toLowerCase().equals(INVALID_ANDROID_ID))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return getSha256(androidId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a 1-way hashed value of the device's unique serial number. This value is encoded using a SHA-256 one way hash and
|
||||
* therefore cannot be used to determine what device this data came from.
|
||||
* <p>
|
||||
* Note: {@link android.os.Build#SERIAL} was introduced in SDK 9. For older SDKs, this method will return null.
|
||||
*
|
||||
* @return An 1-way hashed version of the {@link android.os.Build#SERIAL}. May return null if a serial or the hashing
|
||||
* algorithm is not available.
|
||||
*/
|
||||
/*
|
||||
* Suppress JavaDoc warnings because the {@link android.os.Build#SERIAL} fails when built with SDK 4.
|
||||
*/
|
||||
public static String getSerialNumberHashOrNull()
|
||||
{
|
||||
/*
|
||||
* Obtain the device serial number using reflection, since serial number was added in SDK 9
|
||||
*/
|
||||
String serialNumber = null;
|
||||
if (Constants.CURRENT_API_LEVEL >= 9)
|
||||
{
|
||||
try
|
||||
{
|
||||
serialNumber = (String) Build.class.getField("SERIAL").get(null); //$NON-NLS-1$
|
||||
}
|
||||
catch (final Exception e)
|
||||
{
|
||||
/*
|
||||
* This should never happen, as SERIAL is a public field added in SDK 9.
|
||||
*/
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
if (serialNumber == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return getSha256(serialNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the device's telephony ID (e.g. IMEI/MEID).
|
||||
* <p>
|
||||
* Note: this method will return null if {@link permission#READ_PHONE_STATE} is not available. This method will also return
|
||||
* null on devices that do not have telephony.
|
||||
*
|
||||
* @param context The context used to access the phone state.
|
||||
* @return An the {@link TelephonyManager#getDeviceId()}. Null if an ID is not available, or if
|
||||
* {@link permission#READ_PHONE_STATE} is not available.
|
||||
*/
|
||||
public static String getTelephonyDeviceIdOrNull(final Context context)
|
||||
{
|
||||
if (Constants.CURRENT_API_LEVEL >= 8)
|
||||
{
|
||||
final Boolean hasTelephony = ReflectionUtils.tryInvokeInstance(context.getPackageManager(), "hasSystemFeature", new Class<?>[] { String.class }, new Object[] { "android.hardware.telephony" }); //$NON-NLS-1$//$NON-NLS-2$
|
||||
|
||||
if (!hasTelephony.booleanValue())
|
||||
{
|
||||
if (Constants.IS_LOGGABLE)
|
||||
{
|
||||
Log.i(Constants.LOG_TAG, "Device does not have telephony; cannot read telephony id"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: Sometimes Android will deny a package READ_PHONE_STATE permissions, even if the package has the permission. It
|
||||
* appears to be a race condition that occurs during installation.
|
||||
*/
|
||||
String id = null;
|
||||
if (context.getPackageManager().checkPermission(permission.READ_PHONE_STATE, context.getPackageName()) == PackageManager.PERMISSION_GRANTED)
|
||||
{
|
||||
final TelephonyManager manager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
|
||||
id = manager.getDeviceId();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Constants.IS_LOGGABLE)
|
||||
{
|
||||
Log.w(Constants.LOG_TAG, "Application does not have permission READ_PHONE_STATE; determining device id is not possible. Please consider requesting READ_PHONE_STATE in the AndroidManifest"); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a 1-way hashed value of the device's IMEI/MEID ID. This value is encoded using a SHA-256 one way hash and cannot be
|
||||
* used to determine what device this data came from.
|
||||
* <p>
|
||||
* Note: this method will return null if this is a non-telephony device.
|
||||
* <p>
|
||||
* Note: this method will return null if {@link permission#READ_PHONE_STATE} is not available.
|
||||
*
|
||||
* @param context The context used to access the phone state.
|
||||
* @return An 1-way hashed version of the {@link TelephonyManager#getDeviceId()}. Null if an ID or the hashing algorithm is
|
||||
* not available, or if {@link permission#READ_PHONE_STATE} is not available.
|
||||
*/
|
||||
public static String getTelephonyDeviceIdHashOrNull(final Context context)
|
||||
{
|
||||
final String id = getTelephonyDeviceIdOrNull(context);
|
||||
|
||||
if (null == id)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return getSha256(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the type of network this device is connected to.
|
||||
*
|
||||
* @param context the context used to access the device's WIFI
|
||||
* @param telephonyManager The manager used to access telephony info
|
||||
* @return The type of network, or unknown if the information is unavailable
|
||||
*/
|
||||
public static String getNetworkType(final Context context, final TelephonyManager telephonyManager)
|
||||
{
|
||||
if (context.getPackageManager().checkPermission(permission.ACCESS_WIFI_STATE, context.getPackageName()) == PackageManager.PERMISSION_GRANTED)
|
||||
{
|
||||
final NetworkInfo wifiInfo = ((ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE)).getNetworkInfo(ConnectivityManager.TYPE_WIFI);
|
||||
if (wifiInfo != null && wifiInfo.isConnectedOrConnecting())
|
||||
{
|
||||
return "wifi"; //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Constants.IS_LOGGABLE)
|
||||
{
|
||||
Log.w(Constants.LOG_TAG, "Application does not have permission ACCESS_WIFI_STATE; determining Wi-Fi connectivity is unavailable"); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
return "android_network_type_" + telephonyManager.getNetworkType(); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the device manufacturer's name. This is only available on SDK 4 or greater, so on SDK 3 this method returns the
|
||||
* constant string "unknown".
|
||||
*
|
||||
* @return A string naming the manufacturer
|
||||
*/
|
||||
public static String getManufacturer()
|
||||
{
|
||||
String mfg = "unknown"; //$NON-NLS-1$
|
||||
if (Constants.CURRENT_API_LEVEL > 3)
|
||||
{
|
||||
try
|
||||
{
|
||||
final Class<?> buildClass = Build.class;
|
||||
mfg = (String) buildClass.getField("MANUFACTURER").get(null); //$NON-NLS-1$
|
||||
}
|
||||
catch (final Exception ignore)
|
||||
{
|
||||
if (Constants.IS_LOGGABLE)
|
||||
{
|
||||
Log.w(Constants.LOG_TAG, "Caught exception", ignore); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
}
|
||||
return mfg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the versionName of the application.
|
||||
*
|
||||
* @param context {@link Context}. Cannot be null.
|
||||
* @return The application's version
|
||||
*/
|
||||
public static String getAppVersion(final Context context)
|
||||
{
|
||||
final PackageManager pm = context.getPackageManager();
|
||||
|
||||
try
|
||||
{
|
||||
final String versionName = pm.getPackageInfo(context.getPackageName(), 0).versionName;
|
||||
|
||||
/*
|
||||
* If there is no versionName in the Android Manifest, the versionName will be null.
|
||||
*/
|
||||
if (versionName == null)
|
||||
{
|
||||
if (Constants.IS_LOGGABLE)
|
||||
{
|
||||
Log.w(Constants.LOG_TAG, "versionName was null--is a versionName attribute set in the Android Manifest?"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
return "unknown"; //$NON-NLS-1$
|
||||
}
|
||||
|
||||
return versionName;
|
||||
}
|
||||
catch (final PackageManager.NameNotFoundException e)
|
||||
{
|
||||
/*
|
||||
* This should never occur--our own package must exist for this code to be running
|
||||
*/
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to generate a SHA-256 hash of a given String
|
||||
*
|
||||
* @param string String to hash. Cannot be null.
|
||||
* @return hashed version of the string using SHA-256.
|
||||
*/
|
||||
/* package */static String getSha256(final String string)
|
||||
{
|
||||
if (Constants.ENABLE_PARAMETER_CHECKING)
|
||||
{
|
||||
if (null == string)
|
||||
{
|
||||
throw new IllegalArgumentException("string cannot be null"); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
final MessageDigest md = MessageDigest.getInstance("SHA-256"); //$NON-NLS-1$
|
||||
final byte[] digest = md.digest(string.getBytes("UTF-8")); //$NON-NLS-1$
|
||||
final BigInteger hashedNumber = new BigInteger(1, digest);
|
||||
return hashedNumber.toString(16);
|
||||
}
|
||||
catch (final NoSuchAlgorithmException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
catch (final UnsupportedEncodingException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2012 Todoroo Inc
|
||||
*
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
package com.localytics.android;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Exception handler for background threads used by the Localytics library.
|
||||
* <p>
|
||||
* Analytics are secondary to any other functions performed by an app, which means that analytics should never cause an app to
|
||||
* crash. This handler therefore suppresses all uncaught exceptions from the Localytics library.
|
||||
*/
|
||||
/* package */final class ExceptionHandler implements Thread.UncaughtExceptionHandler
|
||||
{
|
||||
@Override
|
||||
public void uncaughtException(final Thread thread, final Throwable throwable)
|
||||
{
|
||||
/*
|
||||
* Wrap all the work done by the exception handler in a try-catch. It would be ironic if this exception handler itself
|
||||
* caused the parent process to crash.
|
||||
*/
|
||||
try
|
||||
{
|
||||
if (Constants.IS_LOGGABLE)
|
||||
{
|
||||
Log.e(Constants.LOG_TAG, "Localytics library threw an uncaught exception", throwable); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
// TODO: Upload uncaught exceptions so that we can fix them
|
||||
}
|
||||
catch (final Exception e)
|
||||
{
|
||||
if (Constants.IS_LOGGABLE)
|
||||
{
|
||||
Log.e(Constants.LOG_TAG, "Exception handler threw an exception", e); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,574 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2012 Todoroo Inc
|
||||
*
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
package com.localytics.android;
|
||||
|
||||
import org.json.JSONArray;
|
||||
|
||||
import android.Manifest.permission;
|
||||
|
||||
/**
|
||||
* Set of constants for building JSON objects that get sent to the Localytics web service.
|
||||
*/
|
||||
/* package */final class JsonObjects
|
||||
{
|
||||
/**
|
||||
* Private constructor prevents instantiation
|
||||
*
|
||||
* @throws UnsupportedOperationException because this class cannot be instantiated.
|
||||
*/
|
||||
private JsonObjects()
|
||||
{
|
||||
throw new UnsupportedOperationException("This class is non-instantiable"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Set of constants for the blob header JSON object.
|
||||
*/
|
||||
public static final class BlobHeader
|
||||
{
|
||||
/**
|
||||
* Private constructor prevents instantiation
|
||||
*
|
||||
* @throws UnsupportedOperationException because this class cannot be instantiated.
|
||||
*/
|
||||
private BlobHeader()
|
||||
{
|
||||
throw new UnsupportedOperationException("This class is non-instantiable"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Data type for the JSON object.
|
||||
*
|
||||
* @see #VALUE_DATA_TYPE
|
||||
*/
|
||||
public static final String KEY_DATA_TYPE = "dt"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* @see #KEY_DATA_TYPE
|
||||
*/
|
||||
public static final String VALUE_DATA_TYPE = "h"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Timestamp when the app was first launched and the persistent storage was created. Represented as seconds since the Unix
|
||||
* Epoch. (Note: This is SECONDS and not milliseconds. This requires care, because Android represents time as
|
||||
* milliseconds).
|
||||
*/
|
||||
public static final String KEY_PERSISTENT_STORAGE_CREATION_TIME_SECONDS = "pa"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Sequence number. A monotonically increasing count for each new blob.
|
||||
*/
|
||||
public static final String KEY_SEQUENCE_NUMBER = "seq"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* A UUID for the blob.
|
||||
*/
|
||||
public static final String KEY_UNIQUE_ID = "u"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* A JSON Object for attributes for the session.
|
||||
*/
|
||||
public static final String KEY_ATTRIBUTES = "attrs"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Attributes under {@link BlobHeader#KEY_ATTRIBUTES}
|
||||
*/
|
||||
public static final class Attributes
|
||||
{
|
||||
/**
|
||||
* Private constructor prevents instantiation
|
||||
*
|
||||
* @throws UnsupportedOperationException because this class cannot be instantiated.
|
||||
*/
|
||||
private Attributes()
|
||||
{
|
||||
throw new UnsupportedOperationException("This class is non-instantiable"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Type: {@code String}
|
||||
* <p>
|
||||
* Data connection type.
|
||||
*/
|
||||
public static final String KEY_DATA_CONNECTION = "dac"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Type: {@code String}
|
||||
* <p>
|
||||
* Version name of the application, taken from the Android Manifest.
|
||||
*/
|
||||
public static final String KEY_CLIENT_APP_VERSION = "av"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Key which maps to the SHA-256 of the device's {@link android.provider.Settings.Secure#ANDROID_ID}.
|
||||
*/
|
||||
public static final String KEY_DEVICE_ANDROID_ID_HASH = "du"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Type: {@code String}
|
||||
* <p>
|
||||
*/
|
||||
public static final String KEY_DEVICE_COUNTRY = "dc"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Type: {@code String}
|
||||
* <p>
|
||||
* Manufacturer of the device (e.g. HTC, Samsung, Motorola, Kyocera, etc.)
|
||||
*/
|
||||
public static final String KEY_DEVICE_MANUFACTURER = "dma"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Type: {@code String}
|
||||
* <p>
|
||||
* Model of the device (e.g. dream,
|
||||
*/
|
||||
public static final String KEY_DEVICE_MODEL = "dmo"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Type: {@code String}
|
||||
* <p>
|
||||
* Android version (e.g. 1.6 or 2.3.4).
|
||||
*/
|
||||
public static final String KEY_DEVICE_OS_VERSION = "dov"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Type: {@code String}
|
||||
* <p>
|
||||
* Telephony ID of the device, if the device has telephony and the app has {@link permission#READ_PHONE_STATE}.
|
||||
* Otherwise null.
|
||||
*/
|
||||
public static final String KEY_DEVICE_TELEPHONY_ID = "tdid"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Type: {@code String}
|
||||
* <p>
|
||||
* Platform of the device. For Android devices, this is always "android"
|
||||
*/
|
||||
public static final String KEY_DEVICE_PLATFORM = "dp"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Type: {@code String}
|
||||
* <p>
|
||||
* SHA-256 hash of the device's serial number. Only reported for Android 2.3 or later. Otherwise null.
|
||||
*/
|
||||
public static final String KEY_DEVICE_SERIAL_HASH = "dms"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Type: {@code int}
|
||||
* <p>
|
||||
* SDK compatibility level of the device.
|
||||
*
|
||||
* @see android.os.Build.VERSION#SDK
|
||||
*/
|
||||
public static final String KEY_DEVICE_SDK_LEVEL = "dsdk"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Type: {@code String}
|
||||
* <p>
|
||||
* SHA-256 hash of the device's Telephony ID, if the device has telephony and the app has
|
||||
* {@link permission#READ_PHONE_STATE}. Otherwise null.
|
||||
*/
|
||||
public static final String KEY_DEVICE_TELEPHONY_ID_HASH = "dtidh"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Type: {@code String}
|
||||
* <p>
|
||||
* Country for the device's current locale settings
|
||||
*/
|
||||
public static final String KEY_LOCALE_COUNTRY = "dlc"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Type: {@code String}
|
||||
* <p>
|
||||
* Language for the device's current locale settings
|
||||
*/
|
||||
public static final String KEY_LOCALE_LANGUAGE = "dll"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Type: {@code String}
|
||||
* <p>
|
||||
* Api key
|
||||
*/
|
||||
public static final String KEY_LOCALYTICS_API_KEY = "au"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Type: {@code String}
|
||||
* <p>
|
||||
* Localytics library version
|
||||
*
|
||||
* @see Constants#LOCALYTICS_CLIENT_LIBRARY_VERSION
|
||||
*/
|
||||
public static final String KEY_LOCALYTICS_CLIENT_LIBRARY_VERSION = "lv"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Type: {@code String}
|
||||
* <p>
|
||||
* Data type for the JSON object.
|
||||
*
|
||||
* @see #VALUE_DATA_TYPE
|
||||
*/
|
||||
public static final String KEY_LOCALYTICS_DATA_TYPE = "dt"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Type: {@code String}
|
||||
* <p>
|
||||
* Network carrier of the device
|
||||
*/
|
||||
public static final String KEY_NETWORK_CARRIER = "nca"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Type: {@code String}
|
||||
* <p>
|
||||
*/
|
||||
public static final String KEY_NETWORK_COUNTRY = "nc"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* @see #KEY_LOCALYTICS_DATA_TYPE
|
||||
*/
|
||||
@SuppressWarnings("hiding")
|
||||
public static final String VALUE_DATA_TYPE = "a"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Value for the platform.
|
||||
*
|
||||
* @see #KEY_DEVICE_PLATFORM
|
||||
*/
|
||||
public static final String VALUE_PLATFORM = "Android"; //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set of constants for the session open event.
|
||||
*/
|
||||
/* package */static final class SessionOpen
|
||||
{
|
||||
/**
|
||||
* Private constructor prevents instantiation
|
||||
*
|
||||
* @throws UnsupportedOperationException because this class cannot be instantiated.
|
||||
*/
|
||||
private SessionOpen()
|
||||
{
|
||||
throw new UnsupportedOperationException("This class is non-instantiable"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Type: {@code String}
|
||||
* <p>
|
||||
* Data type for the JSON object.
|
||||
*
|
||||
* @see #VALUE_DATA_TYPE
|
||||
*/
|
||||
public static final String KEY_DATA_TYPE = "dt"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* @see #KEY_DATA_TYPE
|
||||
*/
|
||||
public static final String VALUE_DATA_TYPE = "s"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Type: {@code long}
|
||||
* <p>
|
||||
* Epoch timestamp when the session was started in seconds.
|
||||
*/
|
||||
public static final String KEY_WALL_TIME_SECONDS = "ct"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Type: {@code long}
|
||||
* <p>
|
||||
* UUID of the event, which is the same thing as the session UUID
|
||||
*/
|
||||
public static final String KEY_EVENT_UUID = "u"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Type: {@code long}
|
||||
* <p>
|
||||
* Count for the number of sessions
|
||||
*/
|
||||
public static final String KEY_COUNT = "nth"; //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Set of constants for the session close event.
|
||||
*/
|
||||
/* package */static final class SessionClose
|
||||
{
|
||||
/**
|
||||
* Private constructor prevents instantiation
|
||||
*
|
||||
* @throws UnsupportedOperationException because this class cannot be instantiated.
|
||||
*/
|
||||
private SessionClose()
|
||||
{
|
||||
throw new UnsupportedOperationException("This class is non-instantiable"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Type: {@code String}
|
||||
* <p>
|
||||
* Data type for the JSON object.
|
||||
*
|
||||
* @see #VALUE_DATA_TYPE
|
||||
*/
|
||||
public static final String KEY_DATA_TYPE = "dt"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Type: {@code String}
|
||||
* <p>
|
||||
* UUID of the event.
|
||||
*/
|
||||
public static final String KEY_EVENT_UUID = "u"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Type: {@code String[]} (technically, a JSON array of strings)
|
||||
* <p>
|
||||
* Ordered list of flow events that occurred
|
||||
*/
|
||||
public static final String KEY_FLOW_ARRAY = "fl"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Type: {@code long}
|
||||
* <p>
|
||||
* Epoch timestamp when the session was started
|
||||
*/
|
||||
public static final String KEY_SESSION_LENGTH_SECONDS = "ctl"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Type: {@code long}
|
||||
* <p>
|
||||
* Start time of the parent session
|
||||
*/
|
||||
public static final String KEY_SESSION_START_TIME = "ss"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Type: {@code String}
|
||||
* <p>
|
||||
* UUID of the session.
|
||||
*/
|
||||
public static final String KEY_SESSION_UUID = "su"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Type: {@code long}
|
||||
* <p>
|
||||
* Epoch timestamp when the session was started in seconds.
|
||||
*/
|
||||
public static final String KEY_WALL_TIME_SECONDS = "ct"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Data type for close events.
|
||||
*
|
||||
* @see #KEY_DATA_TYPE
|
||||
*/
|
||||
public static final String VALUE_DATA_TYPE = "c"; //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Set of constants for the session event event.
|
||||
*/
|
||||
/* package */static final class SessionEvent
|
||||
{
|
||||
/**
|
||||
* Private constructor prevents instantiation
|
||||
*
|
||||
* @throws UnsupportedOperationException because this class cannot be instantiated.
|
||||
*/
|
||||
private SessionEvent()
|
||||
{
|
||||
throw new UnsupportedOperationException("This class is non-instantiable"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Type: {@code String}
|
||||
* <p>
|
||||
* Data type for the JSON object.
|
||||
*
|
||||
* @see #VALUE_DATA_TYPE
|
||||
*/
|
||||
public static final String KEY_DATA_TYPE = "dt"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Data type for application events.
|
||||
*
|
||||
* @see #KEY_DATA_TYPE
|
||||
*/
|
||||
public static final String VALUE_DATA_TYPE = "e"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Type: {@code long}
|
||||
* <p>
|
||||
* Epoch timestamp when the session was started in seconds.
|
||||
*/
|
||||
public static final String KEY_WALL_TIME_SECONDS = "ct"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Type: {@code String}
|
||||
* <p>
|
||||
* UUID of the session.
|
||||
*/
|
||||
public static final String KEY_SESSION_UUID = "su"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Type: {@code String}
|
||||
* <p>
|
||||
* UUID of the event.
|
||||
*/
|
||||
public static final String KEY_EVENT_UUID = "u"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Type: {@code String}
|
||||
* <p>
|
||||
* Name of the event.
|
||||
*/
|
||||
public static final String KEY_NAME = "n"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Type: {@code JSONObject}.
|
||||
* <p>
|
||||
* Maps to the attributes of the event.
|
||||
* <p>
|
||||
* Note that this key is optional. If it is present, it will point to a non-null value representing the attributes of the
|
||||
* event. Otherwise the key will not exist, indicating the event had no attributes.
|
||||
*/
|
||||
public static final String KEY_ATTRIBUTES = "attrs"; //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Set of constants for the session opt in/out event
|
||||
*/
|
||||
/* package */static final class OptEvent
|
||||
{
|
||||
/**
|
||||
* Private constructor prevents instantiation
|
||||
*
|
||||
* @throws UnsupportedOperationException because this class cannot be instantiated.
|
||||
*/
|
||||
private OptEvent()
|
||||
{
|
||||
throw new UnsupportedOperationException("This class is non-instantiable"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Type: {@code String}
|
||||
* <p>
|
||||
* Data type for the JSON object.
|
||||
*
|
||||
* @see #VALUE_DATA_TYPE
|
||||
*/
|
||||
public static final String KEY_DATA_TYPE = "dt"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Data type for opt in/out events.
|
||||
*
|
||||
* @see #KEY_DATA_TYPE
|
||||
*/
|
||||
public static final String VALUE_DATA_TYPE = "o"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Type: {@code long}
|
||||
* <p>
|
||||
* Epoch timestamp when the session was started in seconds.
|
||||
*/
|
||||
public static final String KEY_WALL_TIME_SECONDS = "ct"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Type: {@code String}
|
||||
* <p>
|
||||
* API key
|
||||
*/
|
||||
public static final String KEY_API_KEY = "u"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Type: {@code boolean}
|
||||
* <p>
|
||||
* True to opt-out. False to opt-in
|
||||
*/
|
||||
public static final String KEY_OPT = "out"; //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Set of constants for the session flow event.
|
||||
*/
|
||||
/* package */static final class EventFlow
|
||||
{
|
||||
/**
|
||||
* Private constructor prevents instantiation
|
||||
*
|
||||
* @throws UnsupportedOperationException because this class cannot be instantiated.
|
||||
*/
|
||||
private EventFlow()
|
||||
{
|
||||
throw new UnsupportedOperationException("This class is non-instantiable"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Type: {@code String}
|
||||
* <p>
|
||||
* Data type for the JSON object.
|
||||
*
|
||||
* @see #VALUE_DATA_TYPE
|
||||
*/
|
||||
public static final String KEY_DATA_TYPE = "dt"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Type: {@code long}
|
||||
* <p>
|
||||
* UUID of the event, which is the same thing as the session UUID
|
||||
*/
|
||||
public static final String KEY_EVENT_UUID = "u"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Type: {@code long}
|
||||
* <p>
|
||||
* Start time of the parents session.
|
||||
*/
|
||||
public static final String KEY_SESSION_START_TIME = "ss"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Type: {@code Element[]} (technically a {@link JSONArray} of {@link Element} objects)
|
||||
* <p>
|
||||
* Ordered set of new flow elements that occurred since the last upload for this session.
|
||||
*/
|
||||
public static final String KEY_FLOW_NEW = "nw"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Type: {@code Element[]} (technically a {@link JSONArray} of {@link Element} objects)
|
||||
* <p>
|
||||
* Ordered set of old flow elements that occurred during all previous uploads for this session.
|
||||
*/
|
||||
public static final String KEY_FLOW_OLD = "od"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* @see #KEY_DATA_TYPE
|
||||
*/
|
||||
public static final String VALUE_DATA_TYPE = "f"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Flow event element that indicates the type and name of the flow event.
|
||||
*/
|
||||
/* package */static final class Element
|
||||
{
|
||||
/**
|
||||
* Private constructor prevents instantiation
|
||||
*
|
||||
* @throws UnsupportedOperationException because this class cannot be instantiated.
|
||||
*/
|
||||
private Element()
|
||||
{
|
||||
throw new UnsupportedOperationException("This class is non-instantiable"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* A flow event that was due to an {@link SessionEvent}.
|
||||
*/
|
||||
public static final String TYPE_EVENT = "e"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* A flow event that was due to a screen event.
|
||||
*/
|
||||
public static final String TYPE_SCREEN = "s"; //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,114 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2012 Todoroo Inc
|
||||
*
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
package com.localytics.android;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
/**
|
||||
* Static utilities for performing reflection against newer Android SDKs.
|
||||
* <p>
|
||||
* This is not a general-purpose reflection class but is rather specifically designed for calling methods that must exist in newer
|
||||
* versions of Android.
|
||||
*/
|
||||
public final class ReflectionUtils
|
||||
{
|
||||
/**
|
||||
* Private constructor prevents instantiation
|
||||
*
|
||||
* @throws UnsupportedOperationException because this class cannot be instantiated.
|
||||
*/
|
||||
private ReflectionUtils()
|
||||
{
|
||||
throw new UnsupportedOperationException("This class is non-instantiable"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Use reflection to invoke a static method for a class object and method name
|
||||
*
|
||||
* @param <T> Type that the method should return
|
||||
* @param classObject Class on which to invoke {@code methodName}. Cannot be null.
|
||||
* @param methodName Name of the method to invoke. Cannot be null.
|
||||
* @param types explicit types for the objects. This is useful if the types are primitives, rather than objects.
|
||||
* @param args arguments for the method. May be null if the method takes no arguments.
|
||||
* @return The result of invoking the named method on the given class for the args
|
||||
* @throws RuntimeException if the class or method doesn't exist
|
||||
*/
|
||||
public static <T> T tryInvokeStatic(final Class<?> classObject, final String methodName, final Class<?>[] types, final Object[] args)
|
||||
{
|
||||
return (T) helper(null, classObject, null, methodName, types, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use reflection to invoke a static method for a class object and method name
|
||||
*
|
||||
* @param <T> Type that the method should return
|
||||
* @param className Name of the class on which to invoke {@code methodName}. Cannot be null.
|
||||
* @param methodName Name of the method to invoke. Cannot be null.
|
||||
* @param types explicit types for the objects. This is useful if the types are primitives, rather than objects.
|
||||
* @param args arguments for the method. May be null if the method takes no arguments.
|
||||
* @return The result of invoking the named method on the given class for the args
|
||||
* @throws RuntimeException if the class or method doesn't exist
|
||||
*/
|
||||
public static <T> T tryInvokeStatic(final String className, final String methodName, final Class<?>[] types, final Object[] args)
|
||||
{
|
||||
return (T) helper(className, null, null, methodName, types, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use reflection to invoke a static method for a class object and method name
|
||||
*
|
||||
* @param <T> Type that the method should return
|
||||
* @param target Object instance on which to invoke {@code methodName}. Cannot be null.
|
||||
* @param methodName Name of the method to invoke. Cannot be null.
|
||||
* @param types explicit types for the objects. This is useful if the types are primitives, rather than objects.
|
||||
* @param args arguments for the method. May be null if the method takes no arguments.
|
||||
* @return The result of invoking the named method on the given class for the args
|
||||
* @throws RuntimeException if the class or method doesn't exist
|
||||
*/
|
||||
public static <T> T tryInvokeInstance(final Object target, final String methodName, final Class<?>[] types, final Object[] args)
|
||||
{
|
||||
return (T) helper(target, null, null, methodName, types, args);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <T> T helper(final Object target, final Class<?> classObject, final String className, final String methodName, final Class<?>[] argTypes, final Object[] args)
|
||||
{
|
||||
try
|
||||
{
|
||||
Class<?> cls;
|
||||
if (classObject != null)
|
||||
{
|
||||
cls = classObject;
|
||||
}
|
||||
else if (target != null)
|
||||
{
|
||||
cls = target.getClass();
|
||||
}
|
||||
else
|
||||
{
|
||||
cls = Class.forName(className);
|
||||
}
|
||||
|
||||
return (T) cls.getMethod(methodName, argTypes).invoke(target, args);
|
||||
}
|
||||
catch (final NoSuchMethodException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
catch (final IllegalAccessException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
catch (final InvocationTargetException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
catch (final ClassNotFoundException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
Binary file not shown.
@ -1,113 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2012 Todoroo Inc
|
||||
*
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
|
||||
package com.todoroo.astrid.service;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
|
||||
import com.localytics.android.LocalyticsSession;
|
||||
import com.timsu.astrid.R;
|
||||
import com.todoroo.andlib.utility.Preferences;
|
||||
import com.todoroo.astrid.utility.Constants;
|
||||
|
||||
public class StatisticsService {
|
||||
|
||||
private static LocalyticsSession localyticsSession;
|
||||
|
||||
/**
|
||||
* Indicate session started
|
||||
*
|
||||
* @param context
|
||||
*/
|
||||
public static void sessionStart(Context context) {
|
||||
if(dontCollectStatistics()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(localyticsSession != null) {
|
||||
localyticsSession.open(); // Multiple calls to open are ok, we just need to make sure it gets reopened after pause
|
||||
} else {
|
||||
localyticsSession = new LocalyticsSession(context.getApplicationContext(),
|
||||
Constants.LOCALYTICS_KEY);
|
||||
localyticsSession.open();
|
||||
localyticsSession.upload();
|
||||
}
|
||||
|
||||
if (context instanceof Activity) {
|
||||
localyticsSession.tagScreen(context.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate session ended
|
||||
*
|
||||
* @param context
|
||||
*/
|
||||
public static void sessionStop(Context context) {
|
||||
if(dontCollectStatistics()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(localyticsSession != null) {
|
||||
localyticsSession.upload();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate session was paused
|
||||
*/
|
||||
public static void sessionPause() {
|
||||
if(dontCollectStatistics()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(localyticsSession != null) {
|
||||
localyticsSession.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates an error occurred
|
||||
* @param name
|
||||
* @param message
|
||||
* @param trace
|
||||
*/
|
||||
public static void reportError(String name, String message, String trace) {
|
||||
// no reports yet
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates an event should be reported
|
||||
* @param event
|
||||
*/
|
||||
public static void reportEvent(String event, String... attributes) {
|
||||
if(dontCollectStatistics()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(localyticsSession != null) {
|
||||
if(attributes.length > 0) {
|
||||
HashMap<String, String> attrMap = new HashMap<String, String>();
|
||||
for(int i = 1; i < attributes.length; i += 2) {
|
||||
if(attributes[i] != null) {
|
||||
attrMap.put(attributes[i - 1], attributes[i]);
|
||||
}
|
||||
}
|
||||
localyticsSession.tagEvent(event, attrMap);
|
||||
} else {
|
||||
localyticsSession.tagEvent(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean dontCollectStatistics() {
|
||||
return !Preferences.getBoolean(R.string.p_statistics, true);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue