diff --git a/src/main/java/com/amplitude/api/AmplitudeLog.java b/src/main/java/com/amplitude/api/AmplitudeLog.java index 52c215a4..2db1b4ef 100644 --- a/src/main/java/com/amplitude/api/AmplitudeLog.java +++ b/src/main/java/com/amplitude/api/AmplitudeLog.java @@ -76,17 +76,17 @@ int v(String tag, String msg, Throwable tr) { return 0; } - int w(String tag, String msg) { + public int w(String tag, String msg) { if (enableLogging && logLevel <= Log.WARN) return Log.w(tag, msg); return 0; } - int w(String tag, Throwable tr) { + public int w(String tag, Throwable tr) { if (enableLogging && logLevel <= Log.WARN) return Log.w(tag, tr); return 0; } - int w(String tag, String msg, Throwable tr) { + public int w(String tag, String msg, Throwable tr) { if (enableLogging && logLevel <= Log.WARN) return Log.w(tag, msg, tr); return 0; } diff --git a/src/main/java/com/amplitude/identitymanager/Identity.java b/src/main/java/com/amplitude/identitymanager/Identity.java new file mode 100644 index 00000000..ac3e2121 --- /dev/null +++ b/src/main/java/com/amplitude/identitymanager/Identity.java @@ -0,0 +1,84 @@ +package com.amplitude.identitymanager; + +import com.amplitude.api.AmplitudeLog; + +public class Identity { + private String userId; + private String deviceId; + private boolean shouldUseAdvertisingIdForDeviceId = false; + private IdentityListener listener; + + public interface IdentityListener { + void onUserIdChanged(String userId); + void onDeviceIdChanged(String deviceId); + } + + public Identity() { + this(false, null); + } + + public Identity(boolean useAdvertisingId) { + this(useAdvertisingId, null); + } + + public Identity(boolean useAdvertisingId, String userId) { + this.userId = userId; + this.shouldUseAdvertisingIdForDeviceId = useAdvertisingId; + + initializeDeviceId(); + } + + public String initializeDeviceId(String deviceId) { + if (this.deviceId == null) { + String deviceIdToUse = ""; + if (shouldUseAdvertisingIdForDeviceId) { + deviceIdToUse = IdentityDeviceInfo.getAdvertisingId(); + } else { + if (deviceId.length() > 0) { + deviceIdToUse = deviceId; + } else { + deviceIdToUse = IdentityUtils.generateBase36Id(); + } + } + this.deviceId = deviceIdToUse; + } else { + AmplitudeLog.getLogger().w(Identity.class.getName(), "Cannot set device ID twice for same identity. Skipping operation."); + } + return this.deviceId; + } + + public String initializeDeviceId() { + return initializeDeviceId(null); + } + + public String getDeviceId() { + return deviceId; + } + + // Should this exist? Otherwise, when would we call the onDeviceIdChanged listener? + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + if (listener != null) { + listener.onDeviceIdChanged(deviceId); + } + } + + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + if (listener != null) { + listener.onUserIdChanged(userId); + } + } + + public void addIdentityChangedListener(IdentityListener listener){ + this.listener = listener; + } + + public void useAdvertisingIdForDeviceId() { + shouldUseAdvertisingIdForDeviceId = true; + } +} diff --git a/src/main/java/com/amplitude/identitymanager/IdentityDeviceInfo.java b/src/main/java/com/amplitude/identitymanager/IdentityDeviceInfo.java new file mode 100644 index 00000000..bf3b6b6d --- /dev/null +++ b/src/main/java/com/amplitude/identitymanager/IdentityDeviceInfo.java @@ -0,0 +1,27 @@ +package com.amplitude.identitymanager; + +import android.os.Build; + +public class IdentityDeviceInfo { + public static String getAdvertisingId() { + // This should not be called on the main thread. + if ("Amazon".equals(getManufacturer())) { + return getAndCacheAmazonAdvertisingId(); + } else { + return getAndCacheGoogleAdvertisingId(); + } + } + + private static String getManufacturer() { + return Build.MANUFACTURER; + } + + private static String getAndCacheAmazonAdvertisingId() { + return "amazonadvertisingid"; + } + + private static String getAndCacheGoogleAdvertisingId() { + return "advertisingid"; + } +} + diff --git a/src/main/java/com/amplitude/identitymanager/IdentityManager.java b/src/main/java/com/amplitude/identitymanager/IdentityManager.java new file mode 100644 index 00000000..3125d78e --- /dev/null +++ b/src/main/java/com/amplitude/identitymanager/IdentityManager.java @@ -0,0 +1,23 @@ +package com.amplitude.identitymanager; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class IdentityManager { + static final Map instanceMap = new ConcurrentHashMap(); + private final static String DEFAULT_INSTANCE = "$default_instance"; + + public Identity getInstance(String instanceName) { + if (instanceMap.containsKey(instanceName)) { + return instanceMap.get(instanceName); + } else { + Identity identityToSet = new Identity(); + instanceMap.put(instanceName, identityToSet); + return identityToSet; + } + } + + public Identity getInstance() { + return getInstance(DEFAULT_INSTANCE); + } +} diff --git a/src/main/java/com/amplitude/identitymanager/IdentityUtils.java b/src/main/java/com/amplitude/identitymanager/IdentityUtils.java new file mode 100644 index 00000000..92457789 --- /dev/null +++ b/src/main/java/com/amplitude/identitymanager/IdentityUtils.java @@ -0,0 +1,21 @@ +package com.amplitude.identitymanager; + +import java.util.Random; + +public class IdentityUtils { + static private final int device_id_length = 25; + static private final String base_36_char_set = "abcdefghijklmnopqrstuvwxyz0123456789"; + static private final int base_36_radix = 36; + + static String generateBase36Id() { + String stringBuilder = ""; + Random rand = new Random(); + for (int idx = 0; idx < device_id_length; idx++) { + int randomIdx = rand.nextInt(base_36_radix); + char nextChar = base_36_char_set.charAt(randomIdx); + stringBuilder += nextChar; + } + + return stringBuilder; + } +}