mirror of https://github.com/tasks/tasks
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
325 lines
12 KiB
Java
325 lines
12 KiB
Java
/**
|
|
* DatapointHelper.java
|
|
* Copyright (C) 2009 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.
|
|
*/
|
|
|
|
package com.localytics.android;
|
|
|
|
import java.math.BigInteger;
|
|
import java.security.MessageDigest;
|
|
import java.security.NoSuchAlgorithmException;
|
|
import java.text.SimpleDateFormat;
|
|
import java.util.Date;
|
|
import java.util.TimeZone;
|
|
|
|
import android.content.Context;
|
|
import android.content.pm.PackageManager;
|
|
import android.net.wifi.WifiManager;
|
|
import android.provider.Settings.System;
|
|
import android.telephony.TelephonyManager;
|
|
import android.util.Log;
|
|
/**
|
|
* Provides a number of static functions to aid in the collection and formatting
|
|
* of datapoints.
|
|
* @author Localytics
|
|
*/
|
|
@SuppressWarnings("nls")
|
|
public final class DatapointHelper
|
|
{
|
|
// This class should never be instantiated
|
|
private DatapointHelper() { /**/ }
|
|
|
|
private static final String LOG_PREFIX = "(DatapointHelper) ";
|
|
private static final String DROID2_ANDROID_ID = "9774d56d682e549c";
|
|
|
|
// Each YAML entry either goes to the session controller, the event controller
|
|
// or the optin controller
|
|
public static final String CONTROLLER_SESSION = "- c: se\n";
|
|
public static final String CONTROLLER_EVENT = "- c: ev\n";
|
|
public static final String CONTROLLER_OPT = "- c: optin\n";
|
|
|
|
// Each entry is either a create action, or an update action
|
|
public static final String ACTION_CREATE = " a: c\n";
|
|
public static final String ACTION_UPDATE = " a: u\n";
|
|
public static final String ACTION_OPTIN = " a: optin\n";
|
|
|
|
// The target object for the data being set up.
|
|
public static final String OBJECT_SESSION_DP = " se:\n";
|
|
public static final String OBJECT_EVENT_DP = " ev:\n";
|
|
public static final String OBJECT_OPT = " optin:\n";
|
|
|
|
// Events can have attributes
|
|
public static final String EVENT_ATTRIBUTE = " attrs:\n";
|
|
|
|
/*******************************
|
|
* WEBSERVICE PARAMENTER NAMES *
|
|
* *****************************
|
|
*/
|
|
|
|
// Every object has a UUID
|
|
public static final String PARAM_UUID = "u";
|
|
|
|
// The identifier for this application, generated by the user on the webservice
|
|
public static final String PARAM_APP_UUID = "au";
|
|
|
|
// The version of this application, taken from the application's manifest.
|
|
public static final String PARAM_APP_VERSION = "av";
|
|
|
|
// A session's UUID as previously created.
|
|
public static final String PARAM_SESSION_UUID = "su";
|
|
|
|
// A hashed identifier unique to this device
|
|
public static final String PARAM_DEVICE_UUID = "du";
|
|
|
|
// android, iphone, blackberry, windowsmobile
|
|
public static final String PARAM_DEVICE_PLATFORM = "dp";
|
|
|
|
// maker of this device (currently not supported by Android)
|
|
public static final String PARAM_DEVICE_MAKE = "dma";
|
|
|
|
// model of the device
|
|
public static final String PARAM_DEVICE_MODEL = "dmo";
|
|
|
|
// version of the OS on this device
|
|
public static final String PARAM_OS_VERSION = "dov";
|
|
|
|
// country device is from (obtained by querying the SIM card)
|
|
public static final String PARAM_DEVICE_COUNTRY = "dc";
|
|
|
|
// country the current locale is set to
|
|
public static final String PARAM_LOCALE_COUNTRY = "dlc";
|
|
|
|
// country the language is set to
|
|
public static final String PARAM_LOCALE_LANGUAGE = "dll";
|
|
|
|
// Locale as a language_country string. (Not collected because this info
|
|
// is already provided by LOCALE_LANGUAGE and LOCALE_COUNTRY.
|
|
public static final String PARAM_LOCALE = "dl";
|
|
|
|
// Country the user is currently in (comes from Sim card)
|
|
public static final String PARAM_NETWORK_COUNTRY = "nc";
|
|
|
|
// Current carrier (comes from sim card)
|
|
public static final String PARAM_NETWORK_CARRIER = "nca";
|
|
|
|
// Current mobile network code (comes from sim card)
|
|
public static final String PARAM_NETWORK_MNC = "mnc";
|
|
|
|
// current mobile country code (comes from sim card)
|
|
public static final String PARAM_NETWORK_MCC = "mcc";
|
|
|
|
// type of data connection (wifi, umts, gprs, evdo, ...)
|
|
public static final String PARAM_DATA_CONNECTION = "dac";
|
|
|
|
// the version of this Localytics client library
|
|
public static final String PARAM_LIBRARY_VERSION = "lv";
|
|
|
|
// The source where the location came from
|
|
public static final String PARAM_LOCATION_SOURCE = "ls";
|
|
|
|
// the latitude returned by the location provider
|
|
public static final String PARAM_LOCATION_LAT = "lat";
|
|
|
|
// the longitude from the location provider
|
|
public static final String PARAM_LOCATION_LNG = "lng";
|
|
|
|
// the current time on the user's device
|
|
public static final String PARAM_CLIENT_TIME = "ct";
|
|
|
|
// sent at closing time, the current time on the users's device
|
|
public static final String PARAM_CLIENT_CLOSED_TIME = "ctc";
|
|
|
|
// The name an event that occured
|
|
public static final String PARAM_EVENT_NAME = "n";
|
|
|
|
// the optin value sent in if a user opts in or out.
|
|
public static final String PARAM_OPT_VALUE = "optin";
|
|
|
|
/**
|
|
* Returns the given key/value pair as a YAML string. This string is intended to be
|
|
* used to define values for the first level of data in the YAML file. This is
|
|
* different from the datapoints which belong another level in.
|
|
* @param paramName The name of the parameter
|
|
* @param paramValue The value of the parameter
|
|
* @param paramIndent The indent level of the parameter
|
|
* @return a YAML string which can be dumped to the YAML file
|
|
*/
|
|
public static String formatYAMLLine(String paramName,String paramValue, int paramIndent)
|
|
{
|
|
if (paramName.length() > LocalyticsSession.MAX_NAME_LENGTH)
|
|
{
|
|
Log.v(DatapointHelper.LOG_PREFIX, "Parameter name exceeds "
|
|
+ LocalyticsSession.MAX_NAME_LENGTH + " character limit. Truncating.");
|
|
paramName = paramName.substring(0, LocalyticsSession.MAX_NAME_LENGTH);
|
|
}
|
|
if (paramValue.length() > LocalyticsSession.MAX_NAME_LENGTH)
|
|
{
|
|
Log.v(DatapointHelper.LOG_PREFIX, "Parameter value exceeds "
|
|
+ LocalyticsSession.MAX_NAME_LENGTH + " character limit. Truncating.");
|
|
paramValue = paramValue.substring(0, LocalyticsSession.MAX_NAME_LENGTH);
|
|
}
|
|
// The params are stored in the second tier of the YAML data.
|
|
// so with spacing, the expected result is: " paramname:paramvalue\n"
|
|
StringBuffer formattedString = new StringBuffer();
|
|
for (int currentIndent = 0; currentIndent < paramIndent; currentIndent++)
|
|
{
|
|
formattedString.append(" ");
|
|
}
|
|
|
|
formattedString.append(escapeString(paramName));
|
|
formattedString.append(": ");
|
|
|
|
// Escape the string.
|
|
formattedString.append(escapeString(paramValue));
|
|
|
|
formattedString.append("\n");
|
|
|
|
return formattedString.toString();
|
|
}
|
|
|
|
/**
|
|
* Gets a 1-way hashed value of the device's unique ID. This value is encoded using a SHA-256
|
|
* one way hash and cannot be used to determine what device this data came from.
|
|
* @param appContext The context used to access the settings resolver
|
|
* @return An 1-way hashed identifier unique to this device or null if an ID, or the hashing
|
|
* algorithm is not available.
|
|
*/
|
|
public static String getGlobalDeviceId(final Context appContext)
|
|
{
|
|
String systemId = System.getString(appContext.getContentResolver(), System.ANDROID_ID);
|
|
if(systemId == null || systemId.toLowerCase().equals(DROID2_ANDROID_ID))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
try
|
|
{
|
|
MessageDigest md = MessageDigest.getInstance("SHA-256");
|
|
byte[] digest = md.digest(systemId.getBytes());
|
|
BigInteger hashedNumber = new BigInteger(1, digest);
|
|
return new String(hashedNumber.toString(16));
|
|
|
|
}
|
|
catch(NoSuchAlgorithmException e)
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Determines the type of network this device is connected to.
|
|
* @param appContext 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 appContext,
|
|
TelephonyManager telephonyManager)
|
|
{
|
|
WifiManager wifiManager = (WifiManager)appContext.getSystemService(Context.WIFI_SERVICE);
|
|
|
|
// this will only work for apps which already have wifi permissions.
|
|
try
|
|
{
|
|
if(wifiManager.isWifiEnabled())
|
|
{
|
|
return "wifi";
|
|
}
|
|
}
|
|
catch (Exception e) { /**/ }
|
|
|
|
switch (telephonyManager.getNetworkType())
|
|
{
|
|
case TelephonyManager.NETWORK_TYPE_EDGE : return "edge";
|
|
case TelephonyManager.NETWORK_TYPE_GPRS : return "GPRS";
|
|
case TelephonyManager.NETWORK_TYPE_UMTS : return "UMTS";
|
|
case TelephonyManager.NETWORK_TYPE_UNKNOWN : return "unknown";
|
|
}
|
|
|
|
return "none";
|
|
}
|
|
|
|
/**
|
|
* Gets the pretty string for this application's version.
|
|
* @param appContext The context used to examine packages
|
|
* @return The application's version as a pretty string
|
|
*/
|
|
public static String getAppVersion(final Context appContext)
|
|
{
|
|
PackageManager pm = appContext.getPackageManager();
|
|
|
|
try
|
|
{
|
|
return pm.getPackageInfo(appContext.getPackageName(), 0).versionName;
|
|
}
|
|
catch (PackageManager.NameNotFoundException e)
|
|
{
|
|
return "unknown";
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets the current time, along with local timezone, formatted as a DateTime for the webservice.
|
|
* @return a DateTime of the current local time and timezone.
|
|
*/
|
|
public static String getTimeAsDatetime()
|
|
{
|
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss-00:00");
|
|
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
|
|
return sdf.format(new Date());
|
|
}
|
|
|
|
/***************************
|
|
* Private Helper Functions *
|
|
***************************/
|
|
|
|
/**
|
|
* Escapes strings for YAML parser
|
|
* @param rawString The string we want to escape.
|
|
* @return An escaped string ready for YAML
|
|
*/
|
|
private static String escapeString(String rawString)
|
|
{
|
|
StringBuffer parseString = new StringBuffer("\"");
|
|
|
|
int startRead = 0; // Index to start reading at
|
|
int stopRead = 0; // Index characters get read from and where the substring ends
|
|
int bufferLength = rawString == null ? 0 : rawString.length();
|
|
|
|
if (rawString == null)
|
|
{
|
|
return "";
|
|
}
|
|
|
|
// Every time we come across a " or \, append what we have so far, append a \,
|
|
// then manage our indexes to continue where we left off.
|
|
while (stopRead < bufferLength)
|
|
{
|
|
if (rawString.charAt(stopRead) == '\"' || rawString.charAt(stopRead) == '\\')
|
|
{
|
|
parseString.append(rawString.substring(startRead, stopRead));
|
|
parseString.append('\\');
|
|
startRead = stopRead;
|
|
}
|
|
// Skip null characters.
|
|
else if (rawString.charAt(stopRead) == '\0')
|
|
{
|
|
parseString.append(rawString.substring(startRead, stopRead));
|
|
startRead = stopRead + 1;
|
|
}
|
|
stopRead++;
|
|
}
|
|
// Append whatever is left after parsing
|
|
parseString.append(rawString.substring(startRead, stopRead));
|
|
// and finish with a closing "
|
|
parseString.append('\"');
|
|
return parseString.toString();
|
|
}
|
|
}
|