diff --git a/astrid/common-src/com/localytics/android/Constants.java b/astrid/common-src/com/localytics/android/Constants.java index 0f97701cd..e21c1f90a 100644 --- a/astrid/common-src/com/localytics/android/Constants.java +++ b/astrid/common-src/com/localytics/android/Constants.java @@ -21,7 +21,7 @@ import android.text.format.DateUtils; * 2.0: New upload format. */ //@formatter:on - public static final String LOCALYTICS_CLIENT_LIBRARY_VERSION = "2.0"; //$NON-NLS-1$ + public static final String LOCALYTICS_CLIENT_LIBRARY_VERSION = "android_2.1"; //$NON-NLS-1$ /** * The package name of the Localytics library. @@ -72,6 +72,8 @@ import android.text.format.DateUtils; */ public static boolean ENABLE_PARAMETER_CHECKING = true; + /*package*/ static final int CURRENT_API_LEVEL = DatapointHelper.getApiLevel(); + /** * Private constructor prevents instantiation * diff --git a/astrid/common-src/com/localytics/android/DatapointHelper.java b/astrid/common-src/com/localytics/android/DatapointHelper.java index 1167d8967..2d322e077 100755 --- a/astrid/common-src/com/localytics/android/DatapointHelper.java +++ b/astrid/common-src/com/localytics/android/DatapointHelper.java @@ -8,6 +8,15 @@ package com.localytics.android; +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; + import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; @@ -18,15 +27,6 @@ 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. *

@@ -46,7 +46,7 @@ import android.util.Log; /** * Private constructor prevents instantiation - * + * * @throws UnsupportedOperationException because this class cannot be instantiated. */ private DatapointHelper() @@ -54,10 +54,34 @@ import android.util.Log; throw new UnsupportedOperationException("This class is non-instantiable"); //$NON-NLS-1$ } + public 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. + Class buildClass = Build.VERSION.class; + String sdkString = (String) buildClass.getField("SDK").get(null); // $NON-NLS-1$ + return Integer.valueOf(sdkString); + } + catch (Exception e) + { + // Although probably not necessary, protects from the aforementioned deprecation + try + { + Class buildClass = Build.VERSION.class; + return buildClass.getField("SDK_INT").getInt(null); // $NON-NLS-1$ + } + catch (Exception ignore) { } + } + + 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. @@ -112,7 +136,7 @@ import android.util.Log; * therefore cannot be used to determine what device this data came from. *

* 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. */ @@ -126,7 +150,7 @@ import android.util.Log; * Obtain the device serial number using reflection, since serial number was added in SDK 9 */ String serialNumber = null; - if (Build.VERSION.SDK_INT >= 9) + if (Constants.CURRENT_API_LEVEL >= 9) { try { @@ -154,17 +178,16 @@ import android.util.Log; *

* 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 (Build.VERSION.SDK_INT >= 8) + if (Constants.CURRENT_API_LEVEL >= 8) { - final Boolean hasTelephony = ReflectionUtils.tryInvokeInstance(context.getPackageManager(), "hasSystemFeature", //$NON-NLS-1$ - new Class[] { String.class }, new Object[] { "android.hardware.telephony" }); //$NON-NLS-1$ + 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) { @@ -205,17 +228,16 @@ import android.util.Log; * Note: this method will return null if this is a non-telephony device. *

* 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) { - if (Build.VERSION.SDK_INT >= 8) + if (Constants.CURRENT_API_LEVEL >= 8) { - final Boolean hasTelephony = ReflectionUtils.tryInvokeInstance(context.getPackageManager(), "hasSystemFeature", //$NON-NLS-1$ - new Class[] { String.class }, new Object[] { "android.hardware.telephony" }); //$NON-NLS-1$ + 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) { @@ -256,7 +278,7 @@ import android.util.Log; /** * 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 @@ -283,8 +305,28 @@ import android.util.Log; } /** - * Gets the versionName of the application. + * Gets the device manufacturer's name * + * @return A string naming the manufacturer + */ + public static String getManufacturer() + { + String mfg = "unknown"; // $NON-NLS-1$ + if (Constants.CURRENT_API_LEVEL > 3) + { + try + { + Class buildClass = Build.class; + mfg = (String) buildClass.getField("MANUFACTURER").get(null); // $NON-NLS-1$ + } + catch (Exception ignore) {} + } + return mfg; + } + + /** + * Gets the versionName of the application. + * * @param context {@link Context}. Cannot be null. * @return The application's version */ @@ -322,7 +364,7 @@ import android.util.Log; /** * 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. */ @@ -352,4 +394,4 @@ import android.util.Log; throw new RuntimeException(e); } } -} \ No newline at end of file +} diff --git a/astrid/common-src/com/localytics/android/LocalyticsSession.java b/astrid/common-src/com/localytics/android/LocalyticsSession.java index d0bea045a..b4170887e 100755 --- a/astrid/common-src/com/localytics/android/LocalyticsSession.java +++ b/astrid/common-src/com/localytics/android/LocalyticsSession.java @@ -272,7 +272,7 @@ public final class LocalyticsSession * Note that getting the application context may have unpredictable results for apps sharing a process running Android 2.1 * and earlier. See for details. */ - mContext = !(context.getClass().getName().equals("android.test.RenamingDelegatingContext")) && Build.VERSION.SDK_INT >= 8 ? context.getApplicationContext() : context; //$NON-NLS-1$ + mContext = !(context.getClass().getName().equals("android.test.RenamingDelegatingContext")) && Constants.CURRENT_API_LEVEL >= 8 ? context.getApplicationContext() : context; //$NON-NLS-1$ mLocalyticsKey = key; mSessionHandler = new SessionHandler(mContext, mLocalyticsKey, sSessionHandlerThread.getLooper()); @@ -287,7 +287,7 @@ public final class LocalyticsSession /** * Sets the Localytics opt-out state for this application. This call is not necessary and is provided for people who wish to - * allow their users the ability to opt out of data collection. It can be called at any time. Passing false causes all further + * allow their users the ability to opt out of data collection. It can be called at any time. Passing true causes all further * data collection to stop, and an opt-out event to be sent to the server so the user's data is removed from the charts.
* There are very serious implications to the quality of your data when providing an opt out option. For example, users who * have opted out will appear as never returning, causing your new/returning chart to skew.
@@ -1148,7 +1148,7 @@ public final class LocalyticsSession values.put(SessionsDbColumns.SESSION_START_WALL_TIME, Long.valueOf(System.currentTimeMillis())); values.put(SessionsDbColumns.UUID, UUID.randomUUID().toString()); values.put(SessionsDbColumns.APP_VERSION, DatapointHelper.getAppVersion(mContext)); - values.put(SessionsDbColumns.ANDROID_SDK, Integer.valueOf(VERSION.SDK_INT)); + values.put(SessionsDbColumns.ANDROID_SDK, Integer.valueOf(Constants.CURRENT_API_LEVEL)); values.put(SessionsDbColumns.ANDROID_VERSION, VERSION.RELEASE); // Try and get the deviceId. If it is unavailable (or invalid) use the installation ID instead. @@ -1176,7 +1176,7 @@ public final class LocalyticsSession values.put(SessionsDbColumns.DEVICE_ANDROID_ID_HASH, deviceId); values.put(SessionsDbColumns.DEVICE_COUNTRY, telephonyManager.getSimCountryIso()); - values.put(SessionsDbColumns.DEVICE_MANUFACTURER, Build.MANUFACTURER); + values.put(SessionsDbColumns.DEVICE_MANUFACTURER, DatapointHelper.getManufacturer()); values.put(SessionsDbColumns.DEVICE_MODEL, Build.MODEL); values.put(SessionsDbColumns.DEVICE_SERIAL_NUMBER_HASH, DatapointHelper.getSerialNumberHashOrNull()); values.put(SessionsDbColumns.DEVICE_TELEPHONY_ID, DatapointHelper.getTelephonyDeviceIdOrNull(mContext));