diff --git a/code/app/build.gradle b/code/app/build.gradle index 47354225..6fe46a51 100644 --- a/code/app/build.gradle +++ b/code/app/build.gradle @@ -58,13 +58,23 @@ dependencies { implementation 'androidx.navigation:navigation-ui-ktx:2.3.3' implementation project(':edgeidentity') - implementation 'com.adobe.marketing.mobile:core:1+' - implementation 'com.adobe.marketing.mobile:identity:1+' - implementation 'com.adobe.marketing.mobile:edgeconsent:1.+' - implementation('com.adobe.marketing.mobile:edge:1.3.2-SNAPSHOT') { - exclude group: 'com.adobe.marketing.mobile', module:'edgeidentity' + + // TODO: Uncomment next line when core 2.0 artifacts are published to maven + // implementation "com.adobe.marketing.mobile:core:${rootProject.mavenCoreVersion}" + implementation 'com.github.adobe.aepsdk-core-android:core:dev-v2.0.0-SNAPSHOT' + + implementation ('com.adobe.marketing.mobile:identity:1+') { + transitive = false + } + implementation('com.adobe.marketing.mobile:edgeconsent:1.+') { + transitive = false + } + implementation('com.adobe.marketing.mobile:edge:1.+') { + transitive = false + } + implementation ('com.adobe.marketing.mobile:assurance:1+') { + transitive = false } - implementation 'com.adobe.marketing.mobile:assurance:1+' /* Ad ID implementation (pt. 1/5) implementation("com.google.android.gms:play-services-ads-lite:20.6.0") diff --git a/code/edgeidentity/build.gradle b/code/edgeidentity/build.gradle index 0c7805e7..aef0c300 100644 --- a/code/edgeidentity/build.gradle +++ b/code/edgeidentity/build.gradle @@ -220,7 +220,11 @@ task platformFunctionalTestJacocoReport(type: JacocoReport, dependsOn: "createPh dependencies { // Adobe Mobile SDK Core - implementation "com.adobe.marketing.mobile:core:${rootProject.mavenCoreVersion}" + + // TODO: Uncomment next line when core 2.0 artifacts are published to maven + // implementation "com.adobe.marketing.mobile:core:${rootProject.mavenCoreVersion}" + implementation 'com.github.adobe.aepsdk-core-android:core:dev-v2.0.0-SNAPSHOT' + implementation 'androidx.annotation:annotation:1.3.0' testImplementation "androidx.test.ext:junit:${rootProject.ext.junitVersion}" testImplementation "org.mockito:mockito-core:${rootProject.ext.mockitoCoreVersion}" diff --git a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/AuthenticatedState.java b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/AuthenticatedState.java index cedfe712..47dc29fb 100644 --- a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/AuthenticatedState.java +++ b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/AuthenticatedState.java @@ -30,9 +30,9 @@ public enum AuthenticatedState { */ LOGGED_OUT("loggedOut"); - private String name; + private final String name; - private AuthenticatedState(final String name) { + AuthenticatedState(final String name) { this.name = name; } diff --git a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/ECID.java b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/ECID.java index 3bdf5c74..401a5376 100644 --- a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/ECID.java +++ b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/ECID.java @@ -13,6 +13,7 @@ import com.adobe.marketing.mobile.LoggingMode; import com.adobe.marketing.mobile.MobileCore; +import com.adobe.marketing.mobile.util.StringUtils; import java.util.Locale; import java.util.Objects; import java.util.UUID; @@ -41,7 +42,7 @@ final class ECID { * @param ecidString a valid (38-digit UUID) ECID string representation, if null or empty a new ECID will be generated */ ECID(final String ecidString) { - if (Utils.isNullOrEmpty(ecidString)) { + if (StringUtils.isNullOrEmpty(ecidString)) { MobileCore.log( LoggingMode.DEBUG, IdentityConstants.LOG_TAG, diff --git a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/EventUtils.java b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/EventUtils.java index 44dd1e9c..bc756f64 100644 --- a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/EventUtils.java +++ b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/EventUtils.java @@ -11,11 +11,9 @@ package com.adobe.marketing.mobile.edge.identity; -import static com.adobe.marketing.mobile.edge.identity.IdentityConstants.LOG_TAG; - import com.adobe.marketing.mobile.Event; -import com.adobe.marketing.mobile.LoggingMode; -import com.adobe.marketing.mobile.MobileCore; +import com.adobe.marketing.mobile.util.DataReader; +import com.adobe.marketing.mobile.util.StringUtils; import java.util.Map; /** @@ -34,62 +32,6 @@ static boolean isAdIdEvent(final Event event) { return data.containsKey(IdentityConstants.EventDataKeys.ADVERTISING_IDENTIFIER); } - /** - * Checks if the provided {@code event} is of type {@link IdentityConstants.EventType#EDGE_IDENTITY} and source {@link IdentityConstants.EventSource#REMOVE_IDENTITY} - * - * @param event the event to verify - * @return true if both type and source match - */ - static boolean isRemoveIdentityEvent(final Event event) { - return ( - event != null && - IdentityConstants.EventType.EDGE_IDENTITY.equalsIgnoreCase(event.getType()) && - IdentityConstants.EventSource.REMOVE_IDENTITY.equalsIgnoreCase(event.getSource()) - ); - } - - /** - * Checks if the provided {@code event} is of type {@link IdentityConstants.EventType#EDGE_IDENTITY} and source {@link IdentityConstants.EventSource#UPDATE_IDENTITY} - * - * @param event the event to verify - * @return true if both type and source match - */ - static boolean isUpdateIdentityEvent(final Event event) { - return ( - event != null && - IdentityConstants.EventType.EDGE_IDENTITY.equalsIgnoreCase(event.getType()) && - IdentityConstants.EventSource.UPDATE_IDENTITY.equalsIgnoreCase(event.getSource()) - ); - } - - /** - * Checks if the provided {@code event} is of type {@link IdentityConstants.EventType#EDGE_IDENTITY} and source {@link IdentityConstants.EventSource#REQUEST_IDENTITY} - * - * @param event the event to verify - * @return true if both type and source match - */ - static boolean isRequestIdentityEvent(final Event event) { - return ( - event != null && - IdentityConstants.EventType.EDGE_IDENTITY.equalsIgnoreCase(event.getType()) && - IdentityConstants.EventSource.REQUEST_IDENTITY.equalsIgnoreCase(event.getSource()) - ); - } - - /** - * Checks if the provided {@code event} is of type {@link IdentityConstants.EventType#GENERIC_IDENTITY} and source {@link IdentityConstants.EventSource#REQUEST_CONTENT} - * - * @param event the event to verify - * @return true if both type and source match - */ - static boolean isRequestContentEvent(final Event event) { - return ( - event != null && - IdentityConstants.EventType.GENERIC_IDENTITY.equalsIgnoreCase(event.getType()) && - IdentityConstants.EventSource.REQUEST_CONTENT.equalsIgnoreCase(event.getSource()) - ); - } - /** * Reads the url variables flag from the event data, returns false if not present * Note: This API needs to be used with isRequestIdentityEvent API to determine the correct event type and event source @@ -97,37 +39,9 @@ static boolean isRequestContentEvent(final Event event) { * @return true if urlVariables key is present in the event data and has a value of true */ static boolean isGetUrlVariablesRequestEvent(final Event event) { - if (event == null || event.getEventData() == null) { - return false; - } - boolean getUrlVariablesFlag = false; - - try { - Object urlVariablesFlagObject = event.getEventData().get(IdentityConstants.EventDataKeys.URL_VARIABLES); - getUrlVariablesFlag = urlVariablesFlagObject != null && (boolean) urlVariablesFlagObject; - } catch (ClassCastException e) { - MobileCore.log( - LoggingMode.WARNING, - LOG_TAG, - "EventUtils - Failed to read urlvariables value, expected boolean: " + e.getLocalizedMessage() - ); - return false; - } - - return getUrlVariablesFlag; - } - - /** - * Checks if the provided {@code event} is of type {@link IdentityConstants.EventType#GENERIC_IDENTITY} and source {@link IdentityConstants.EventSource#REQUEST_RESET} - * - * @param event the event to verify - * @return true if both type and source match - */ - static boolean isRequestResetEvent(final Event event) { return ( event != null && - IdentityConstants.EventType.GENERIC_IDENTITY.equalsIgnoreCase(event.getType()) && - IdentityConstants.EventSource.REQUEST_RESET.equalsIgnoreCase(event.getSource()) + DataReader.optBoolean(event.getEventData(), IdentityConstants.EventDataKeys.URL_VARIABLES, false) ); } @@ -139,18 +53,15 @@ static boolean isRequestResetEvent(final Event event) { * @return {@code boolean} indicating if it is the shared state update for the provided {@code stateOwnerName} */ static boolean isSharedStateUpdateFor(final String stateOwnerName, final Event event) { - if (Utils.isNullOrEmpty(stateOwnerName) || event == null) { - return false; - } - - String stateOwner; - - try { - stateOwner = (String) event.getEventData().get(IdentityConstants.EventDataKeys.STATE_OWNER); - } catch (ClassCastException e) { + if (StringUtils.isNullOrEmpty(stateOwnerName) || event == null) { return false; } + final String stateOwner = DataReader.optString( + event.getEventData(), + IdentityConstants.EventDataKeys.STATE_OWNER, + "" + ); return stateOwnerName.equals(stateOwner); } @@ -169,23 +80,9 @@ static boolean isSharedStateUpdateFor(final String stateOwnerName, final Event e */ static String getAdId(final Event event) { final Map data = event.getEventData(); - String adID; - - try { - adID = (String) data.get(IdentityConstants.EventDataKeys.ADVERTISING_IDENTIFIER); - } catch (ClassCastException e) { - MobileCore.log( - LoggingMode.DEBUG, - LOG_TAG, - "EventUtils - Failed to extract ad ID from event, expected String: " + e.getLocalizedMessage() - ); - return ""; - } + final String adID = DataReader.optString(data, IdentityConstants.EventDataKeys.ADVERTISING_IDENTIFIER, null); - if (adID == null || IdentityConstants.Default.ZERO_ADVERTISING_ID.equals(adID)) { - return ""; - } - return adID; + return (adID == null || IdentityConstants.Default.ZERO_ADVERTISING_ID.equals(adID) ? "" : adID); } /** @@ -195,23 +92,12 @@ static String getAdId(final Event event) { * @return the ECID or null if not found or unable to parse the payload */ static ECID getECID(final Map identityDirectSharedState) { - ECID legacyEcid = null; - - try { - final String legacyEcidString = (String) identityDirectSharedState.get( - IdentityConstants.SharedState.IdentityDirect.ECID - ); - legacyEcid = legacyEcidString == null ? null : new ECID(legacyEcidString); - } catch (ClassCastException e) { - MobileCore.log( - LoggingMode.DEBUG, - LOG_TAG, - "EventUtils - Failed to extract ECID from Identity direct shared state, expected String: " + - e.getLocalizedMessage() - ); - } - - return legacyEcid; + final String legacyEcidString = DataReader.optString( + identityDirectSharedState, + IdentityConstants.SharedState.IdentityDirect.ECID, + null + ); + return (legacyEcidString == null ? null : new ECID(legacyEcidString)); } /** @@ -221,26 +107,10 @@ static ECID getECID(final Map identityDirectSharedState) { * @return the Experience Cloud Org Id or null if not found or unable to parse the payload */ static String getOrgId(final Map configurationSharedState) { - String orgId = null; - - if (configurationSharedState == null) { - return orgId; - } - - try { - orgId = - (String) configurationSharedState.get( - IdentityConstants.SharedState.Configuration.EXPERIENCE_CLOUD_ORGID - ); - } catch (ClassCastException e) { - MobileCore.log( - LoggingMode.DEBUG, - LOG_TAG, - "EventUtils - Failed to extract Experience ORG ID from Configuration shared state, expected String: " + - e.getLocalizedMessage() - ); - } - - return orgId; + return DataReader.optString( + configurationSharedState, + IdentityConstants.SharedState.Configuration.EXPERIENCE_CLOUD_ORGID, + null + ); } } diff --git a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/Identity.java b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/Identity.java index 5c22bbdb..63967f02 100644 --- a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/Identity.java +++ b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/Identity.java @@ -17,10 +17,13 @@ import com.adobe.marketing.mobile.AdobeCallbackWithError; import com.adobe.marketing.mobile.AdobeError; import com.adobe.marketing.mobile.Event; +import com.adobe.marketing.mobile.Extension; import com.adobe.marketing.mobile.ExtensionError; import com.adobe.marketing.mobile.ExtensionErrorCallback; import com.adobe.marketing.mobile.LoggingMode; import com.adobe.marketing.mobile.MobileCore; +import com.adobe.marketing.mobile.util.DataReader; +import com.adobe.marketing.mobile.util.StringUtils; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -30,6 +33,9 @@ */ public class Identity { + public static final Class EXTENSION = IdentityExtension.class; + private static final long CALLBACK_TIMEOUT_MILLIS = 500L; + private Identity() {} /** @@ -43,7 +49,10 @@ public static String extensionVersion() { /** * Registers the extension with the Mobile SDK. This method should be called only once in your application class. + * + * @deprecated Use {@link MobileCore#registerExtensions(List, AdobeCallback)} with {@link Identity#EXTENSION} instead. */ + @Deprecated public static void registerExtension() { MobileCore.registerExtension( IdentityExtension.class, @@ -85,57 +94,53 @@ public static void getExperienceCloudId(final AdobeCallback callback) { ) .build(); - final ExtensionErrorCallback errorCallback = new ExtensionErrorCallback() { + final AdobeCallbackWithError callbackWithError = new AdobeCallbackWithError() { + @Override + public void call(Event responseEvent) { + if (responseEvent == null || responseEvent.getEventData() == null) { + returnError(callback, AdobeError.UNEXPECTED_ERROR); + return; + } + + final IdentityMap identityMap = IdentityMap.fromXDMMap(responseEvent.getEventData()); + + if (identityMap == null) { + MobileCore.log( + LoggingMode.DEBUG, + LOG_TAG, + "Identity - Failed to read IdentityMap from response event, invoking error callback with AdobeError.UNEXPECTED_ERROR" + ); + returnError(callback, AdobeError.UNEXPECTED_ERROR); + return; + } + + final List ecidItems = identityMap.getIdentityItemsForNamespace( + IdentityConstants.Namespaces.ECID + ); + + if (ecidItems == null || ecidItems.isEmpty() || ecidItems.get(0).getId() == null) { + callback.call(""); + } else { + callback.call(ecidItems.get(0).getId()); + } + } + @Override - public void error(final ExtensionError extensionError) { - returnError(callback, extensionError); + public void fail(AdobeError adobeError) { + returnError(callback, adobeError); MobileCore.log( LoggingMode.DEBUG, LOG_TAG, String.format( "Identity - Failed to dispatch %s event: Error : %s.", IdentityConstants.EventNames.IDENTITY_REQUEST_IDENTITY_ECID, - extensionError.getErrorName() + adobeError.getErrorName() ) ); } }; - MobileCore.dispatchEventWithResponseCallback( - event, - new AdobeCallback() { - @Override - public void call(Event responseEvent) { - if (responseEvent == null || responseEvent.getEventData() == null) { - returnError(callback, AdobeError.UNEXPECTED_ERROR); - return; - } - - final IdentityMap identityMap = IdentityMap.fromXDMMap(responseEvent.getEventData()); - - if (identityMap == null) { - MobileCore.log( - LoggingMode.DEBUG, - LOG_TAG, - "Identity - Failed to read IdentityMap from response event, invoking error callback with AdobeError.UNEXPECTED_ERROR" - ); - returnError(callback, AdobeError.UNEXPECTED_ERROR); - return; - } - - final List ecidItems = identityMap.getIdentityItemsForNamespace( - IdentityConstants.Namespaces.ECID - ); - - if (ecidItems == null || ecidItems.isEmpty() || ecidItems.get(0).getId() == null) { - callback.call(""); - } else { - callback.call(ecidItems.get(0).getId()); - } - } - }, - errorCallback - ); + MobileCore.dispatchEventWithResponseCallback(event, CALLBACK_TIMEOUT_MILLIS, callbackWithError); } /** @@ -179,48 +184,44 @@ public static void getUrlVariables(final AdobeCallback callback) { ) .build(); - final ExtensionErrorCallback errorCallback = new ExtensionErrorCallback() { + final AdobeCallbackWithError callbackWithError = new AdobeCallbackWithError() { @Override - public void error(final ExtensionError extensionError) { - returnError(callback, extensionError); + public void call(final Event responseEvent) { + if (responseEvent == null || responseEvent.getEventData() == null) { + returnError(callback, AdobeError.UNEXPECTED_ERROR); + return; + } + + final Map data = responseEvent.getEventData(); + final String urlVariableString = DataReader.optString( + data, + IdentityConstants.EventDataKeys.URL_VARIABLES, + null + ); + + if (urlVariableString == null) { + returnError(callback, AdobeError.UNEXPECTED_ERROR); + return; + } + callback.call(urlVariableString); + } + + @Override + public void fail(final AdobeError adobeError) { + returnError(callback, adobeError); MobileCore.log( LoggingMode.DEBUG, LOG_TAG, String.format( "Identity - Failed to dispatch %s event: Error : %s.", IdentityConstants.EventNames.IDENTITY_REQUEST_URL_VARIABLES, - extensionError.getErrorName() + adobeError.getErrorName() ) ); } }; - MobileCore.dispatchEventWithResponseCallback( - event, - new AdobeCallback() { - @Override - public void call(Event responseEvent) { - if (responseEvent == null || responseEvent.getEventData() == null) { - returnError(callback, AdobeError.UNEXPECTED_ERROR); - return; - } - - final Map data = responseEvent.getEventData(); - try { - String urlVariableString = (String) data.get(IdentityConstants.EventDataKeys.URL_VARIABLES); - if (urlVariableString == null) { - returnError(callback, AdobeError.UNEXPECTED_ERROR); - return; - } - callback.call(urlVariableString); - } catch (ClassCastException e) { - returnError(callback, AdobeError.UNEXPECTED_ERROR); - return; - } - } - }, - errorCallback - ); + MobileCore.dispatchEventWithResponseCallback(event, CALLBACK_TIMEOUT_MILLIS, callbackWithError); } /** @@ -241,21 +242,6 @@ public static void updateIdentities(final IdentityMap identityMap) { return; } - final ExtensionErrorCallback errorCallback = new ExtensionErrorCallback() { - @Override - public void error(final ExtensionError extensionError) { - MobileCore.log( - LoggingMode.DEBUG, - LOG_TAG, - String.format( - "Identity - Update Identities API. Failed to dispatch %s event: Error : %s.", - IdentityConstants.EventNames.UPDATE_IDENTITIES, - extensionError.getErrorName() - ) - ); - } - }; - final Event updateIdentitiesEvent = new Event.Builder( IdentityConstants.EventNames.UPDATE_IDENTITIES, IdentityConstants.EventType.EDGE_IDENTITY, @@ -263,7 +249,8 @@ public void error(final ExtensionError extensionError) { ) .setEventData(identityMap.asXDMMap(false)) .build(); - MobileCore.dispatchEvent(updateIdentitiesEvent, errorCallback); + + MobileCore.dispatchEvent(updateIdentitiesEvent); } /** @@ -274,7 +261,7 @@ public void error(final ExtensionError extensionError) { * @param namespace The namespace of the identity to remove. */ public static void removeIdentity(final IdentityItem item, final String namespace) { - if (Utils.isNullOrEmpty(namespace)) { + if (StringUtils.isNullOrEmpty(namespace)) { MobileCore.log( LoggingMode.DEBUG, LOG_TAG, @@ -291,21 +278,6 @@ public static void removeIdentity(final IdentityItem item, final String namespac IdentityMap identityMap = new IdentityMap(); identityMap.addItem(item, namespace); - final ExtensionErrorCallback errorCallback = new ExtensionErrorCallback() { - @Override - public void error(final ExtensionError extensionError) { - MobileCore.log( - LoggingMode.DEBUG, - LOG_TAG, - String.format( - "Identity - removeIdentity API. Failed to dispatch %s event: Error : %s.", - IdentityConstants.EventNames.REMOVE_IDENTITIES, - extensionError.getErrorName() - ) - ); - } - }; - final Event removeIdentitiesEvent = new Event.Builder( IdentityConstants.EventNames.REMOVE_IDENTITIES, IdentityConstants.EventType.EDGE_IDENTITY, @@ -313,7 +285,7 @@ public void error(final ExtensionError extensionError) { ) .setEventData(identityMap.asXDMMap(false)) .build(); - MobileCore.dispatchEvent(removeIdentitiesEvent, errorCallback); + MobileCore.dispatchEvent(removeIdentitiesEvent); } /** @@ -340,49 +312,45 @@ public static void getIdentities(final AdobeCallback callback) { ) .build(); - final ExtensionErrorCallback errorCallback = new ExtensionErrorCallback() { + final AdobeCallbackWithError callbackWithError = new AdobeCallbackWithError() { @Override - public void error(final ExtensionError extensionError) { - returnError(callback, extensionError); + public void call(final Event responseEvent) { + if (responseEvent == null || responseEvent.getEventData() == null) { + returnError(callback, AdobeError.UNEXPECTED_ERROR); + return; + } + + final IdentityMap identityMap = IdentityMap.fromXDMMap(responseEvent.getEventData()); + + if (identityMap == null) { + MobileCore.log( + LoggingMode.DEBUG, + LOG_TAG, + "Identity - Failed to read IdentityMap from response event, invoking error callback with AdobeError.UNEXPECTED_ERROR" + ); + returnError(callback, AdobeError.UNEXPECTED_ERROR); + return; + } + + callback.call(identityMap); + } + + @Override + public void fail(final AdobeError adobeError) { + returnError(callback, adobeError); MobileCore.log( LoggingMode.DEBUG, LOG_TAG, String.format( "Identity - Failed to dispatch %s event: Error : %s.", IdentityConstants.EventNames.REQUEST_IDENTITIES, - extensionError.getErrorName() + adobeError.getErrorName() ) ); } }; - MobileCore.dispatchEventWithResponseCallback( - event, - new AdobeCallback() { - @Override - public void call(Event responseEvent) { - if (responseEvent == null || responseEvent.getEventData() == null) { - returnError(callback, AdobeError.UNEXPECTED_ERROR); - return; - } - - final IdentityMap identityMap = IdentityMap.fromXDMMap(responseEvent.getEventData()); - - if (identityMap == null) { - MobileCore.log( - LoggingMode.DEBUG, - LOG_TAG, - "Identity - Failed to read IdentityMap from response event, invoking error callback with AdobeError.UNEXPECTED_ERROR" - ); - returnError(callback, AdobeError.UNEXPECTED_ERROR); - return; - } - - callback.call(identityMap); - } - }, - errorCallback - ); + MobileCore.dispatchEventWithResponseCallback(event, CALLBACK_TIMEOUT_MILLIS, callbackWithError); } /** diff --git a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityConstants.java b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityConstants.java index fbfcf14d..bb1edfb1 100644 --- a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityConstants.java +++ b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityConstants.java @@ -15,16 +15,16 @@ final class IdentityConstants { static final String LOG_TAG = "EdgeIdentity"; static final String EXTENSION_NAME = "com.adobe.edge.identity"; - static final String EXTENSION_VERSION = "1.1.0"; + static final String EXTENSION_VERSION = "2.0.0"; - final class Default { + static final class Default { static final String ZERO_ADVERTISING_ID = "00000000-0000-0000-0000-000000000000"; private Default() {} } - final class EventSource { + static final class EventSource { static final String BOOTED = "com.adobe.eventSource.booted"; static final String REMOVE_IDENTITY = "com.adobe.eventSource.removeIdentity"; @@ -40,7 +40,7 @@ final class EventSource { private EventSource() {} } - final class EventType { + static final class EventType { static final String EDGE_CONSENT = "com.adobe.eventType.edgeConsent"; static final String EDGE_IDENTITY = "com.adobe.eventType.edgeIdentity"; @@ -51,7 +51,7 @@ final class EventType { private EventType() {} } - final class EventNames { + static final class EventNames { static final String CONSENT_UPDATE_REQUEST_AD_ID = "Consent Update Request for Ad ID"; static final String IDENTITY_REQUEST_IDENTITY_ECID = "Edge Identity Request ECID"; @@ -66,7 +66,7 @@ final class EventNames { private EventNames() {} } - final class EventDataKeys { + static final class EventDataKeys { static final String ADVERTISING_IDENTIFIER = "advertisingidentifier"; static final String STATE_OWNER = "stateowner"; @@ -75,9 +75,9 @@ final class EventDataKeys { private EventDataKeys() {} } - final class SharedState { + static final class SharedState { - final class Hub { + static final class Hub { static final String NAME = "com.adobe.module.eventhub"; static final String EXTENSIONS = "extensions"; @@ -85,7 +85,7 @@ final class Hub { private Hub() {} } - final class Configuration { + static final class Configuration { static final String NAME = "com.adobe.module.configuration"; static final String EXPERIENCE_CLOUD_ORGID = "experienceCloud.org"; @@ -93,7 +93,7 @@ final class Configuration { private Configuration() {} } - final class IdentityDirect { + static final class IdentityDirect { static final String NAME = "com.adobe.module.identity"; static final String ECID = "mid"; @@ -104,7 +104,7 @@ private IdentityDirect() {} private SharedState() {} } - final class Namespaces { + static final class Namespaces { static final String ECID = "ECID"; static final String IDFA = "IDFA"; @@ -113,14 +113,14 @@ final class Namespaces { private Namespaces() {} } - final class XDMKeys { + static final class XDMKeys { static final String IDENTITY_MAP = "identityMap"; static final String ID = "id"; static final String AUTHENTICATED_STATE = "authenticatedState"; static final String PRIMARY = "primary"; - final class Consent { + static final class Consent { static final String AD_ID = "adID"; static final String CONSENTS = "consents"; @@ -135,7 +135,7 @@ private Consent() {} private XDMKeys() {} } - final class DataStoreKey { + static final class DataStoreKey { static final String DATASTORE_NAME = EXTENSION_NAME; static final String IDENTITY_PROPERTIES = "identity.properties"; @@ -145,7 +145,7 @@ final class DataStoreKey { private DataStoreKey() {} } - final class UrlKeys { + static final class UrlKeys { static final String TS = "TS"; static final String EXPERIENCE_CLOUD_ORG_ID = "MCORGID"; diff --git a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityExtension.java b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityExtension.java index 2a4b2ec0..385dc9c7 100644 --- a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityExtension.java +++ b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityExtension.java @@ -13,192 +13,160 @@ import static com.adobe.marketing.mobile.edge.identity.IdentityConstants.LOG_TAG; +import androidx.annotation.NonNull; +import androidx.annotation.VisibleForTesting; import com.adobe.marketing.mobile.Event; import com.adobe.marketing.mobile.Extension; import com.adobe.marketing.mobile.ExtensionApi; -import com.adobe.marketing.mobile.ExtensionError; -import com.adobe.marketing.mobile.ExtensionErrorCallback; import com.adobe.marketing.mobile.LoggingMode; import com.adobe.marketing.mobile.MobileCore; +import com.adobe.marketing.mobile.SharedStateResolution; +import com.adobe.marketing.mobile.SharedStateResult; +import com.adobe.marketing.mobile.SharedStateStatus; +import com.adobe.marketing.mobile.util.StringUtils; +import com.adobe.marketing.mobile.util.TimeUtils; import java.util.HashMap; import java.util.Map; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; class IdentityExtension extends Extension { - private ExecutorService executorService; - private final Object executorMutex = new Object(); - private final ConcurrentLinkedQueue cachedEvents; // cached events in memory until required shared states are resolved + /** + * A {@code SharedStateCallback} to retrieve the last set state of an extension and to + * create an XDM state at the event provided. + */ + private final SharedStateCallback sharedStateHandle = new SharedStateCallback() { + @Override + public SharedStateResult getSharedState(final String stateOwner, final Event event) { + return getApi().getSharedState(stateOwner, event, false, SharedStateResolution.LAST_SET); + } + + @Override + public void createXDMSharedState(final Map state, final Event event) { + getApi().createXDMSharedState(state, event); + } + }; - // package private for testing - IdentityState state = new IdentityState(new IdentityProperties()); + private final IdentityState state; /** * Constructor. - * - *

- * Called during the Identity extension's registration. - * The following listeners are registered during this extension's registration. - *

    - *
  • Listener {@link ListenerEventHubBoot} to listen for event with eventType {@link IdentityConstants.EventType#HUB} - * and EventSource {@link IdentityConstants.EventSource#BOOTED}
  • - *
  • Listener {@link ListenerIdentityRequestContent} to listen for event with eventType {@link IdentityConstants.EventType#GENERIC_IDENTITY} - * and EventSource {@link IdentityConstants.EventSource#REQUEST_CONTENT}
  • - *
  • Listener {@link ListenerEdgeIdentityRequestIdentity} to listen for event with eventType {@link IdentityConstants.EventType#EDGE_IDENTITY} - * and EventSource {@link IdentityConstants.EventSource#REQUEST_IDENTITY}
  • - *
  • Listener {@link ListenerEdgeIdentityUpdateIdentity} to listen for event with eventType {@link IdentityConstants.EventType#EDGE_IDENTITY} - * and EventSource {@link IdentityConstants.EventSource#UPDATE_IDENTITY}
  • - *
  • Listener {@link ListenerEdgeIdentityRemoveIdentity} to listen for event with eventType {@link IdentityConstants.EventType#EDGE_IDENTITY} - * and EventSource {@link IdentityConstants.EventSource#REMOVE_IDENTITY}
  • - *
  • Listener {@link ListenerIdentityRequestReset} to listen for event with eventType {@link IdentityConstants.EventType#EDGE_IDENTITY} - * and EventSource {@link IdentityConstants.EventSource#REQUEST_CONTENT}
  • - *
  • Listener {@link ListenerIdentityRequestReset} to listen for event with eventType {@link IdentityConstants.EventType#GENERIC_IDENTITY} - * and EventSource {@link IdentityConstants.EventSource#REQUEST_RESET}
  • - *
  • Listener {@link ListenerHubSharedState} to listen for event with eventType {@link IdentityConstants.EventType#HUB} - * and EventSource {@link IdentityConstants.EventSource#SHARED_STATE}
  • - *
- *

- * Thread : Background thread created by MobileCore + * Invoked on the background thread owned by an extension container that manages this extension. * * @param extensionApi {@link ExtensionApi} instance */ protected IdentityExtension(ExtensionApi extensionApi) { + this(extensionApi, new IdentityState()); + } + + @VisibleForTesting + IdentityExtension(final ExtensionApi extensionApi, final IdentityState state) { super(extensionApi); - cachedEvents = new ConcurrentLinkedQueue<>(); - - ExtensionErrorCallback listenerErrorCallback = new ExtensionErrorCallback() { - @Override - public void error(final ExtensionError extensionError) { - MobileCore.log( - LoggingMode.ERROR, - LOG_TAG, - String.format("Failed to register listener, error: %s", extensionError.getErrorName()) - ); - } - }; - - extensionApi.registerEventListener( - IdentityConstants.EventType.HUB, - IdentityConstants.EventSource.BOOTED, - ListenerEventHubBoot.class, - listenerErrorCallback - ); - extensionApi.registerEventListener( - IdentityConstants.EventType.GENERIC_IDENTITY, - IdentityConstants.EventSource.REQUEST_CONTENT, - ListenerIdentityRequestContent.class, - listenerErrorCallback - ); - extensionApi.registerEventListener( - IdentityConstants.EventType.EDGE_IDENTITY, - IdentityConstants.EventSource.REQUEST_IDENTITY, - ListenerEdgeIdentityRequestIdentity.class, - listenerErrorCallback - ); - extensionApi.registerEventListener( - IdentityConstants.EventType.EDGE_IDENTITY, - IdentityConstants.EventSource.UPDATE_IDENTITY, - ListenerEdgeIdentityUpdateIdentity.class, - listenerErrorCallback - ); - extensionApi.registerEventListener( - IdentityConstants.EventType.EDGE_IDENTITY, - IdentityConstants.EventSource.REMOVE_IDENTITY, - ListenerEdgeIdentityRemoveIdentity.class, - listenerErrorCallback - ); - extensionApi.registerEventListener( - IdentityConstants.EventType.HUB, - IdentityConstants.EventSource.SHARED_STATE, - ListenerHubSharedState.class, - listenerErrorCallback - ); - extensionApi.registerEventListener( - IdentityConstants.EventType.GENERIC_IDENTITY, - IdentityConstants.EventSource.REQUEST_RESET, - ListenerIdentityRequestReset.class, - listenerErrorCallback - ); + this.state = state; } - /** - * Required override. Each extension must have a unique name within the application. - * - * @return unique name of this extension - */ + @NonNull @Override protected String getName() { return IdentityConstants.EXTENSION_NAME; } - /** - * Optional override. - * - * @return the version of this extension - */ @Override protected String getVersion() { return IdentityConstants.EXTENSION_VERSION; } /** - * Adds an event to the event queue and starts processing the queue. + * {@inheritDoc} * - * @param event the received event to be added in the events queue; should not be null + *

+ * The following listeners are registered during this extension's registration. + *

    + *
  • EventType {@link IdentityConstants.EventType#GENERIC_IDENTITY} and EventSource {@link IdentityConstants.EventSource#REQUEST_CONTENT}
  • + *
  • EventType {@link IdentityConstants.EventType#EDGE_IDENTITY} and EventSource {@link IdentityConstants.EventSource#REQUEST_IDENTITY}
  • + *
  • EventType {@link IdentityConstants.EventType#EDGE_IDENTITY} and EventSource {@link IdentityConstants.EventSource#UPDATE_IDENTITY}
  • + *
  • EventType {@link IdentityConstants.EventType#EDGE_IDENTITY} and EventSource {@link IdentityConstants.EventSource#REMOVE_IDENTITY}
  • + *
  • EventType {@link IdentityConstants.EventType#EDGE_IDENTITY} and EventSource {@link IdentityConstants.EventSource#REQUEST_CONTENT}
  • + *
  • EventType {@link IdentityConstants.EventType#GENERIC_IDENTITY} and EventSource {@link IdentityConstants.EventSource#REQUEST_RESET}
  • + *
  • EventType {@link IdentityConstants.EventType#HUB} and EventSource {@link IdentityConstants.EventSource#SHARED_STATE}
  • + *
+ *

*/ - void processAddEvent(final Event event) { - if (event == null) { - return; - } + @Override + protected void onRegistered() { + // GENERIC_IDENTITY event listeners + getApi() + .registerEventListener( + IdentityConstants.EventType.GENERIC_IDENTITY, + IdentityConstants.EventSource.REQUEST_CONTENT, + this::handleRequestContent + ); - cachedEvents.add(event); - processCachedEvents(); - } + getApi() + .registerEventListener( + IdentityConstants.EventType.GENERIC_IDENTITY, + IdentityConstants.EventSource.REQUEST_RESET, + this::handleRequestReset + ); - /** - * Processes the cached events in the order they were received. - */ - void processCachedEvents() { - if (!state.hasBooted()) { - return; - } + // EDGE_IDENTITY event listeners + getApi() + .registerEventListener( + IdentityConstants.EventType.EDGE_IDENTITY, + IdentityConstants.EventSource.REQUEST_IDENTITY, + this::handleRequestIdentity + ); - while (!cachedEvents.isEmpty()) { - final Event event = cachedEvents.peek(); + getApi() + .registerEventListener( + IdentityConstants.EventType.EDGE_IDENTITY, + IdentityConstants.EventSource.UPDATE_IDENTITY, + this::handleUpdateIdentities + ); - if (EventUtils.isRequestIdentityEvent(event)) { - if (EventUtils.isGetUrlVariablesRequestEvent(event)) { - handleUrlVariablesRequest(event); - } else { - handleIdentityRequest(event); - } - } else if (EventUtils.isRequestContentEvent(event)) { - handleRequestContent(event); - } else if (EventUtils.isUpdateIdentityEvent(event)) { - handleUpdateIdentities(event); - } else if (EventUtils.isRemoveIdentityEvent(event)) { - handleRemoveIdentity(event); - } else if (EventUtils.isRequestResetEvent(event)) { - handleRequestReset(event); - } else if (EventUtils.isSharedStateUpdateFor(IdentityConstants.SharedState.IdentityDirect.NAME, event)) { - handleIdentityDirectECIDUpdate(event); - } - - cachedEvents.poll(); + getApi() + .registerEventListener( + IdentityConstants.EventType.EDGE_IDENTITY, + IdentityConstants.EventSource.REMOVE_IDENTITY, + this::handleRemoveIdentity + ); + + // HUB shared state event listener + getApi() + .registerEventListener( + IdentityConstants.EventType.HUB, + IdentityConstants.EventSource.SHARED_STATE, + this::handleIdentityDirectECIDUpdate + ); + } + + @Override + public boolean readyForEvent(@NonNull Event event) { + if (!state.bootupIfReady(sharedStateHandle)) return false; + + // Get url variables request depends on Configuration shared state + // Wait for configuration state to be set before processing such an event. + if (EventUtils.isGetUrlVariablesRequestEvent(event)) { + final SharedStateResult configurationStateResult = sharedStateHandle.getSharedState( + IdentityConstants.SharedState.Configuration.NAME, + event + ); + + return (configurationStateResult != null && configurationStateResult.getStatus() == SharedStateStatus.SET); } + + return true; } /** - * Calls {@link IdentityState#bootupIfReady(SharedStateCallback)} with a valid callback - * - * @return True if the bootup is complete + * Handles events requesting for identifiers. Dispatches a response event containing requested identifiers. + * @param event the identity request event */ - boolean bootupIfReady() { - final SharedStateCallback callback = createSharedStateCallback(); - - return state.bootupIfReady(callback); + void handleRequestIdentity(@NonNull final Event event) { + if (EventUtils.isGetUrlVariablesRequestEvent(event)) { + handleUrlVariablesRequest(event); + } else { + handleGetIdentifiersRequest(event); + } } /** @@ -206,39 +174,44 @@ boolean bootupIfReady() { * * @param event the identity request {@link Event} */ - void handleUrlVariablesRequest(final Event event) { - String urlVariablesString = null; - - final Map configurationState = getSharedState( + private void handleUrlVariablesRequest(@NonNull final Event event) { + final SharedStateResult configSharedStateResult = sharedStateHandle.getSharedState( IdentityConstants.SharedState.Configuration.NAME, event ); + final Map configurationState = configSharedStateResult != null + ? configSharedStateResult.getValue() + : null; + final String orgId = EventUtils.getOrgId(configurationState); - if (Utils.isNullOrEmpty(orgId)) { + if (StringUtils.isNullOrEmpty(orgId)) { handleUrlVariableResponse( event, - urlVariablesString, + null, "IdentityExtension - Cannot process getUrlVariables request Identity event, Experience Cloud Org ID not found in configuration." ); return; } - ECID ecid = state.getIdentityProperties().getECID(); + final ECID ecid = state.getIdentityProperties().getECID(); final String ecidString = ecid != null ? ecid.toString() : null; - if (Utils.isNullOrEmpty(ecidString)) { + if (StringUtils.isNullOrEmpty(ecidString)) { handleUrlVariableResponse( event, - urlVariablesString, + null, "IdentityExtension - Cannot process getUrlVariables request Identity event, ECID not found." ); return; } - urlVariablesString = - URLUtils.generateURLVariablesPayload(String.valueOf(Utils.getUnixTimeInSeconds()), ecidString, orgId); + final String urlVariablesString = URLUtils.generateURLVariablesPayload( + String.valueOf(TimeUtils.getUnixTimeInSeconds()), + ecidString, + orgId + ); handleUrlVariableResponse(event, urlVariablesString); } @@ -249,7 +222,7 @@ void handleUrlVariablesRequest(final Event event) { * @param event the identity request {@link Event} * @param urlVariables {@link String} representing the urlVariables encoded string */ - private void handleUrlVariableResponse(final Event event, final String urlVariables) { + void handleUrlVariableResponse(@NonNull final Event event, final String urlVariables) { handleUrlVariableResponse(event, urlVariables, null); } @@ -260,7 +233,7 @@ private void handleUrlVariableResponse(final Event event, final String urlVariab * @param urlVariables {@link String} representing the urlVariables encoded string * @param errorMsg {@link String} representing error encountered while generating the urlVariables string */ - private void handleUrlVariableResponse(final Event event, final String urlVariables, final String errorMsg) { + void handleUrlVariableResponse(@NonNull final Event event, final String urlVariables, final String errorMsg) { Event responseEvent = new Event.Builder( IdentityConstants.EventNames.IDENTITY_RESPONSE_URL_VARIABLES, IdentityConstants.EventType.EDGE_IDENTITY, @@ -273,27 +246,14 @@ private void handleUrlVariableResponse(final Event event, final String urlVariab } } ) + .inResponseToEvent(event) .build(); - ExtensionErrorCallback errorCallback = new ExtensionErrorCallback() { - @Override - public void error(ExtensionError extensionError) { - MobileCore.log( - LoggingMode.DEBUG, - LOG_TAG, - "IdentityExtension - Failed to dispatch Edge Identity response event for event " + - event.getUniqueIdentifier() + - " with error " + - extensionError.getErrorName() - ); - } - }; - - if (Utils.isNullOrEmpty(urlVariables) && !Utils.isNullOrEmpty(errorMsg)) { + if (StringUtils.isNullOrEmpty(urlVariables) && !StringUtils.isNullOrEmpty(errorMsg)) { MobileCore.log(LoggingMode.WARNING, LOG_TAG, errorMsg); } - MobileCore.dispatchResponseEvent(responseEvent, event, errorCallback); + getApi().dispatch(responseEvent); } /** @@ -301,8 +261,11 @@ public void error(ExtensionError extensionError) { * * @param event the edge update identity {@link Event} */ - void handleUpdateIdentities(final Event event) { - final Map eventData = event.getEventData(); // do not need to null check on eventData, as they are done on listeners + void handleUpdateIdentities(@NonNull final Event event) { + final Map eventData = event.getEventData(); + + if (eventData == null) return; // TODO: Add log message when logging changes are made + final IdentityMap map = IdentityMap.fromXDMMap(eventData); if (map == null) { @@ -323,8 +286,11 @@ void handleUpdateIdentities(final Event event) { * * @param event the edge remove identity request {@link Event} */ - void handleRemoveIdentity(final Event event) { - final Map eventData = event.getEventData(); // do not need to null check on eventData, as they are done on listeners + void handleRemoveIdentity(@NonNull final Event event) { + final Map eventData = event.getEventData(); + + if (eventData == null) return; // TODO: Add log message when logging changes are made + final IdentityMap map = IdentityMap.fromXDMMap(eventData); if (map == null) { @@ -340,64 +306,23 @@ void handleRemoveIdentity(final Event event) { shareIdentityXDMSharedState(event); } - /** - * Handles events of type {@code com.adobe.eventType.hub} and source {@code com.adobe.eventSource.sharedState}. - * If the state change event is for the direct Identity extension, get the direct Identity shared state and attempt - * to update the legacy ECID with the direct Identity extension ECID. - * - * @param event an event of type {@code com.adobe.eventType.hub} and source {@code com.adobe.eventSource.sharedState}; - * the event and its data should not be null, checked in listener - */ - void handleHubSharedState(final Event event) { - if ( - !EventUtils.isSharedStateUpdateFor(IdentityConstants.SharedState.Hub.NAME, event) && - !EventUtils.isSharedStateUpdateFor(IdentityConstants.SharedState.IdentityDirect.NAME, event) - ) { - return; - } - - if (state.hasBooted()) { - // regular Identity Direct shared state update, queue event for handleIdentityDirectECIDUpdate - processAddEvent(event); - } else { - if (bootupIfReady()) { - processCachedEvents(); - } - } - } - /** * Handles events requesting for identifiers. Dispatches response event containing the identifiers. Called by listener registered with event hub. * * @param event the identity request {@link Event} */ - void handleIdentityRequest(final Event event) { - Map xdmData = state.getIdentityProperties().toXDMData(false); - Event responseEvent = new Event.Builder( + private void handleGetIdentifiersRequest(@NonNull final Event event) { + final Map xdmData = state.getIdentityProperties().toXDMData(false); + final Event responseEvent = new Event.Builder( IdentityConstants.EventNames.IDENTITY_RESPONSE_CONTENT_ONE_TIME, IdentityConstants.EventType.EDGE_IDENTITY, IdentityConstants.EventSource.RESPONSE_IDENTITY ) .setEventData(xdmData) + .inResponseToEvent(event) .build(); - MobileCore.dispatchResponseEvent( - responseEvent, - event, - new ExtensionErrorCallback() { - @Override - public void error(ExtensionError extensionError) { - MobileCore.log( - LoggingMode.DEBUG, - LOG_TAG, - "IdentityExtension - Failed to dispatch Edge Identity response event for event " + - event.getUniqueIdentifier() + - " with error " + - extensionError.getErrorName() - ); - } - } - ); + getApi().dispatch(responseEvent); } /** @@ -405,7 +330,7 @@ public void error(ExtensionError extensionError) { * * @param event the identity request reset {@link Event} */ - void handleRequestReset(final Event event) { + void handleRequestReset(@NonNull final Event event) { state.resetIdentifiers(); shareIdentityXDMSharedState(event); @@ -415,24 +340,10 @@ void handleRequestReset(final Event event) { IdentityConstants.EventType.EDGE_IDENTITY, IdentityConstants.EventSource.RESET_COMPLETE ) + .inResponseToEvent(event) .build(); - MobileCore.dispatchEvent( - responseEvent, - new ExtensionErrorCallback() { - @Override - public void error(ExtensionError extensionError) { - MobileCore.log( - LoggingMode.DEBUG, - LOG_TAG, - "IdentityExtension - Failed to dispatch Edge Identity reset response event for event " + - event.getUniqueIdentifier() + - " with error " + - extensionError.getErrorName() - ); - } - } - ); + getApi().dispatch(responseEvent); } /** @@ -440,12 +351,20 @@ public void error(ExtensionError extensionError) { * * @param event the shared state update {@link Event} */ - void handleIdentityDirectECIDUpdate(final Event event) { - final Map identityState = getSharedState( + void handleIdentityDirectECIDUpdate(@NonNull final Event event) { + if (!EventUtils.isSharedStateUpdateFor(IdentityConstants.SharedState.IdentityDirect.NAME, event)) { + return; + } + + final SharedStateResult identitySharedStateResult = sharedStateHandle.getSharedState( IdentityConstants.SharedState.IdentityDirect.NAME, event ); + final Map identityState = (identitySharedStateResult != null) + ? identitySharedStateResult.getValue() + : null; + if (identityState == null) { return; } @@ -462,61 +381,12 @@ void handleIdentityDirectECIDUpdate(final Event event) { * * @param event the {@link Event} containing advertising identifier data */ - void handleRequestContent(final Event event) { + void handleRequestContent(@NonNull final Event event) { if (!EventUtils.isAdIdEvent(event)) { return; } // Doesn't need event dispatcher because MobileCore can be called directly - state.updateAdvertisingIdentifier(event, createSharedStateCallback()); - } - - /** - * Called by listeners to retrieve an {@code ExecutorService}. - * The {@code ExecutorService} is used to process events on a separate thread than the - * {@code EventHub} thread on which they were received. Processing events on a separate - * thread prevents blocking of the {@code EventHub}. - * - * @return this extension's instance of a single thread executor - */ - ExecutorService getExecutor() { - synchronized (executorMutex) { - if (executorService == null) { - executorService = Executors.newSingleThreadExecutor(); - } - - return executorService; - } - } - - /** - * Retrieves the shared state for the given state owner - * - * @param stateOwner the state owner for the requested shared state - * @param event the {@link Event} for which is shared state is to be retrieved - */ - private Map getSharedState(final String stateOwner, final Event event) { - final ExtensionApi extensionApi = getApi(); - - if (extensionApi == null) { - return null; - } - - final ExtensionErrorCallback getSharedStateCallback = new ExtensionErrorCallback() { - @Override - public void error(final ExtensionError extensionError) { - MobileCore.log( - LoggingMode.DEBUG, - LOG_TAG, - String.format( - "IdentityExtension - Failed getting %s shared state. Error : %s.", - stateOwner, - extensionError.getErrorName() - ) - ); - } - }; - - return extensionApi.getSharedEventState(stateOwner, event, getSharedStateCallback); + state.updateAdvertisingIdentifier(event, sharedStateHandle); } /** @@ -525,90 +395,6 @@ public void error(final ExtensionError extensionError) { * @param event the {@link Event} that triggered the XDM shared state change */ private void shareIdentityXDMSharedState(final Event event) { - final ExtensionApi extensionApi = super.getApi(); - - if (extensionApi == null) { - MobileCore.log( - LoggingMode.DEBUG, - LOG_TAG, - "IdentityExtension - ExtensionApi is null, unable to share XDM shared state for reset identities" - ); - return; - } - - // set the shared state - final ExtensionErrorCallback errorCallback = new ExtensionErrorCallback() { - @Override - public void error(final ExtensionError extensionError) { - MobileCore.log( - LoggingMode.DEBUG, - LOG_TAG, - String.format( - "IdentityExtension - Failed create XDM shared state. Error : %s.", - extensionError.getErrorName() - ) - ); - } - }; - - extensionApi.setXDMSharedEventState(state.getIdentityProperties().toXDMData(false), event, errorCallback); - } - - /** - * Creates standard shared state callback with functionality from {@link ExtensionApi} - * @return a new instance of {@link SharedStateCallback} - */ - private SharedStateCallback createSharedStateCallback() { - return new SharedStateCallback() { - @Override - public Map getSharedState(final String stateOwner, final Event event) { - ExtensionApi api = getApi(); - - if (api == null) { - return null; - } - - return api.getSharedEventState( - stateOwner, - event, - new ExtensionErrorCallback() { - @Override - public void error(ExtensionError extensionError) { - MobileCore.log( - LoggingMode.WARNING, - LOG_TAG, - "SharedStateCallback - Unable to fetch shared state, failed with error: " + - extensionError.getErrorName() - ); - } - } - ); - } - - @Override - public boolean setXDMSharedEventState(final Map state, final Event event) { - ExtensionApi api = getApi(); - - if (api == null) { - return false; - } - - return api.setXDMSharedEventState( - state, - event, - new ExtensionErrorCallback() { - @Override - public void error(ExtensionError extensionError) { - MobileCore.log( - LoggingMode.WARNING, - LOG_TAG, - "SharedStateCallback - Unable to set XDM shared state, failed with error: " + - extensionError.getErrorName() - ); - } - } - ); - } - }; + sharedStateHandle.createXDMSharedState(state.getIdentityProperties().toXDMData(false), event); } } diff --git a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityItem.java b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityItem.java index f40959d5..0a400b0b 100644 --- a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityItem.java +++ b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityItem.java @@ -15,6 +15,8 @@ import com.adobe.marketing.mobile.LoggingMode; import com.adobe.marketing.mobile.MobileCore; +import com.adobe.marketing.mobile.util.DataReader; +import com.adobe.marketing.mobile.util.DataReaderException; import java.util.HashMap; import java.util.Map; import java.util.Objects; @@ -166,23 +168,20 @@ static IdentityItem fromData(final Map data) { } try { - final String id = (String) data.get(IdentityConstants.XDMKeys.ID); - AuthenticatedState authenticatedState = AuthenticatedState.fromString( - (String) data.get(IdentityConstants.XDMKeys.AUTHENTICATED_STATE) + final String id = DataReader.getString(data, IdentityConstants.XDMKeys.ID); + + final AuthenticatedState authenticatedState = AuthenticatedState.fromString( + DataReader.optString( + data, + IdentityConstants.XDMKeys.AUTHENTICATED_STATE, + AuthenticatedState.AMBIGUOUS.getName() + ) ); - if (authenticatedState == null) { - authenticatedState = AuthenticatedState.AMBIGUOUS; - } - - boolean primary = false; - - if (data.get(IdentityConstants.XDMKeys.PRIMARY) != null) { - primary = (boolean) data.get(IdentityConstants.XDMKeys.PRIMARY); - } + final boolean primary = DataReader.optBoolean(data, IdentityConstants.XDMKeys.PRIMARY, false); return new IdentityItem(id, authenticatedState, primary); - } catch (ClassCastException e) { + } catch (final DataReaderException e) { MobileCore.log(LoggingMode.DEBUG, LOG_TAG, "IdentityItem - Failed to create IdentityItem from data."); return null; } diff --git a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityMap.java b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityMap.java index 41fa4c64..c82f3469 100644 --- a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityMap.java +++ b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityMap.java @@ -15,6 +15,8 @@ import com.adobe.marketing.mobile.LoggingMode; import com.adobe.marketing.mobile.MobileCore; +import com.adobe.marketing.mobile.util.DataReader; +import com.adobe.marketing.mobile.util.StringUtils; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -43,7 +45,7 @@ public class IdentityMap { public List getIdentityItemsForNamespace(final String namespace) { final List copyItems = new ArrayList<>(); - if (Utils.isNullOrEmpty(namespace)) { + if (StringUtils.isNullOrEmpty(namespace)) { return copyItems; } @@ -96,7 +98,7 @@ public void removeItem(final IdentityItem item, final String namespace) { return; } - if (Utils.isNullOrEmpty(namespace)) { + if (StringUtils.isNullOrEmpty(namespace)) { MobileCore.log( LoggingMode.DEBUG, LOG_TAG, @@ -167,7 +169,7 @@ void addItem(final IdentityItem item, final String namespace, final boolean isFi return; } - if (Utils.isNullOrEmpty(namespace)) { + if (StringUtils.isNullOrEmpty(namespace)) { MobileCore.log( LoggingMode.DEBUG, LOG_TAG, @@ -281,7 +283,7 @@ Map asXDMMap(final boolean allowEmpty) { } /** - * Creates an {@link IdentityMap} from the given xdm formatted {@link Map} + * Creates an {@link IdentityMap} from the given xdm formatted immutable {@link Map} * Returns null if the provided map is null/empty. * Return null if the provided map is not in Identity Map's XDM format. * @@ -292,16 +294,12 @@ static IdentityMap fromXDMMap(final Map map) { return null; } - Map identityMapDict = null; - try { - identityMapDict = (HashMap) map.get(IdentityConstants.XDMKeys.IDENTITY_MAP); - } catch (ClassCastException e) { - MobileCore.log( - LoggingMode.ERROR, - LOG_TAG, - String.format("Failed to create IdentityMap from data. Exception thrown: %s", e.getLocalizedMessage()) - ); - } + final Map identityMapDict = DataReader.optTypedMap( + Object.class, + map, + IdentityConstants.XDMKeys.IDENTITY_MAP, + null + ); if (identityMapDict == null) { return null; @@ -309,31 +307,21 @@ static IdentityMap fromXDMMap(final Map map) { final IdentityMap identityMap = new IdentityMap(); for (final String namespace : identityMapDict.keySet()) { - try { - final ArrayList> idArr = (ArrayList>) identityMapDict.get( - namespace - ); - if (idArr == null) { - continue; - } + final List> immutableIdList = DataReader.optTypedListOfMap( + Object.class, + identityMapDict, + namespace, + null + ); + + if (immutableIdList == null) continue; - for (Object idMap : idArr) { - final IdentityItem item = IdentityItem.fromData((Map) idMap); + for (final Map idMap : immutableIdList) { + final IdentityItem item = IdentityItem.fromData(idMap); - if (item != null) { - identityMap.addItemToMap(item, namespace, false); - } + if (item != null) { + identityMap.addItemToMap(item, namespace, false); } - } catch (ClassCastException e) { - MobileCore.log( - LoggingMode.ERROR, - LOG_TAG, - String.format( - "Failed to parse data for namespace (%s). Exception thrown: %s", - namespace, - e.getLocalizedMessage() - ) - ); } } diff --git a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityProperties.java b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityProperties.java index 3547f3c5..110b313c 100644 --- a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityProperties.java +++ b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityProperties.java @@ -15,6 +15,7 @@ import com.adobe.marketing.mobile.LoggingMode; import com.adobe.marketing.mobile.MobileCore; +import com.adobe.marketing.mobile.util.StringUtils; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -82,7 +83,7 @@ void setAdId(final String newAdId) { identityMap.removeItem(previousAdIdItem, IdentityConstants.Namespaces.GAID); } - if (Utils.isNullOrEmpty(newAdId)) { + if (StringUtils.isNullOrEmpty(newAdId)) { return; } @@ -130,7 +131,7 @@ ECID getECID() { ecidItems != null && !ecidItems.isEmpty() && ecidItems.get(0) != null && - !Utils.isNullOrEmpty(ecidItems.get(0).getId()) + !StringUtils.isNullOrEmpty(ecidItems.get(0).getId()) ) { return new ECID(ecidItems.get(0).getId()); } @@ -183,7 +184,7 @@ ECID getECIDSecondary() { ecidItems != null && ecidItems.size() > 1 && ecidItems.get(1) != null && - !Utils.isNullOrEmpty(ecidItems.get(1).getId()) + !StringUtils.isNullOrEmpty(ecidItems.get(1).getId()) ) { return new ECID(ecidItems.get(1).getId()); } diff --git a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityState.java b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityState.java index f250b046..40a6f291 100644 --- a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityState.java +++ b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityState.java @@ -13,11 +13,13 @@ import static com.adobe.marketing.mobile.edge.identity.IdentityConstants.LOG_TAG; +import androidx.annotation.VisibleForTesting; import com.adobe.marketing.mobile.Event; -import com.adobe.marketing.mobile.ExtensionError; -import com.adobe.marketing.mobile.ExtensionErrorCallback; import com.adobe.marketing.mobile.LoggingMode; import com.adobe.marketing.mobile.MobileCore; +import com.adobe.marketing.mobile.SharedStateResult; +import com.adobe.marketing.mobile.SharedStateStatus; +import com.adobe.marketing.mobile.util.DataReader; import java.util.HashMap; import java.util.Map; @@ -29,18 +31,27 @@ class IdentityState { private IdentityProperties identityProperties; private boolean hasBooted; + /** + * Loads the persisted identities (if any) into {@link #identityProperties} + */ + IdentityState() { + this(IdentityStorageService.loadPropertiesFromPersistence()); + } + /** * Creates a new {@link IdentityState} with the given {@link IdentityProperties} * * @param identityProperties identity properties */ + @VisibleForTesting IdentityState(final IdentityProperties identityProperties) { - this.identityProperties = identityProperties; + this.identityProperties = (identityProperties != null) ? identityProperties : new IdentityProperties(); } /** * @return the current bootup status */ + @VisibleForTesting boolean hasBooted() { return hasBooted; } @@ -54,7 +65,6 @@ IdentityProperties getIdentityProperties() { /** * Completes init for this Identity extension. - * Attempts to load the already persisted identities from persistence into {@link #identityProperties} * If no ECID is loaded from persistence (ideally meaning first launch), attempts to migrate existing ECID * from the direct Identity Extension, either from its persisted store or from its shared state if the * direct Identity extension is registered. If no ECID is found for migration, then a new ECID is generated. @@ -69,15 +79,19 @@ boolean bootupIfReady(final SharedStateCallback callback) { return true; } - // Load properties from local storage - identityProperties = IdentityStorageService.loadPropertiesFromPersistence(); - - if (identityProperties == null) { - identityProperties = new IdentityProperties(); - } - // Reuse the ECID from Identity Direct (if registered) or generate new ECID on first launch if (identityProperties.getECID() == null) { + // Wait for all extensions to be registered as forthcoming logic depends on Identity Direct state. + // This is inferred via EventHub's shared state and is based on the assumption that EventHub + // sets its state only when all the extensions are registered initially. + final SharedStateResult eventHubStateResult = callback.getSharedState( + IdentityConstants.SharedState.Hub.NAME, + null + ); + if (eventHubStateResult == null || eventHubStateResult.getStatus() != SharedStateStatus.SET) { + return false; + } + // Attempt to get ECID from direct Identity persistence to migrate an existing ECID final ECID directIdentityEcid = IdentityStorageService.loadEcidFromDirectIdentityPersistence(); @@ -92,25 +106,25 @@ boolean bootupIfReady(final SharedStateCallback callback) { ); } // If direct Identity has no persisted ECID, check if direct Identity is registered with the SDK - else if (isIdentityDirectRegistered(callback)) { - final Map identityDirectSharedState = callback.getSharedState( + else if (isIdentityDirectRegistered(eventHubStateResult.getValue())) { + // If the direct Identity extension is registered, attempt to get its shared state + final SharedStateResult sharedStateResult = callback.getSharedState( IdentityConstants.SharedState.IdentityDirect.NAME, null ); - // If the direct Identity extension is registered, attempt to get its shared state - if (identityDirectSharedState != null) { // identity direct shared state is set - handleECIDFromIdentityDirect(EventUtils.getECID(identityDirectSharedState)); - } // If there is no direct Identity shared state, abort boot-up and try again when direct Identity shares its state - else { + if (sharedStateResult == null || sharedStateResult.getStatus() != SharedStateStatus.SET) { MobileCore.log( LoggingMode.DEBUG, LOG_TAG, "IdentityState - On bootup direct Identity extension is registered, waiting for its state change." ); - return false; // If no ECID to migrate but Identity direct is registered, wait for Identity direct shared state + return false; } + + final Map identityDirectSharedState = sharedStateResult.getValue(); + handleECIDFromIdentityDirect(EventUtils.getECID(identityDirectSharedState)); } // Generate a new ECID as the direct Identity extension is not registered with the SDK and there was no direct Identity persisted ECID else { @@ -127,7 +141,7 @@ else if (isIdentityDirectRegistered(callback)) { hasBooted = true; MobileCore.log(LoggingMode.DEBUG, LOG_TAG, "IdentityState - Edge Identity has successfully booted up"); - callback.setXDMSharedEventState(identityProperties.toXDMData(false), null); + callback.createXDMSharedState(identityProperties.toXDMData(false), null); return hasBooted; } @@ -199,7 +213,7 @@ void updateAdvertisingIdentifier(final Event event, final SharedStateCallback ca // Save to persistence IdentityStorageService.savePropertiesToPersistence(identityProperties); - callback.setXDMSharedEventState(identityProperties.toXDMData(false), event); + callback.createXDMSharedState(identityProperties.toXDMData(false), event); } /** @@ -264,35 +278,27 @@ private void handleECIDFromIdentityDirect(final ECID legacyEcid) { /** * Check if the Identity direct extension is registered by checking the EventHub's shared state list of registered extensions. * - * @param callback the {@link SharedStateCallback} to be used for fetching the EventHub Shared state; should not be null - * @return true if the Identity direct extension is registered with the EventHub + * @param eventHubSharedState a {@code Map registeredExtensionsWithHub = callback.getSharedState( - IdentityConstants.SharedState.Hub.NAME, + private boolean isIdentityDirectRegistered(final Map eventHubSharedState) { + if (eventHubSharedState == null) { + return false; + } + + final Map extensions = DataReader.optTypedMap( + Object.class, + eventHubSharedState, + IdentityConstants.SharedState.Hub.EXTENSIONS, null ); - Map identityDirectInfo = null; - - if (registeredExtensionsWithHub != null) { - try { - final Map extensions = (HashMap) registeredExtensionsWithHub.get( - IdentityConstants.SharedState.Hub.EXTENSIONS - ); - - if (extensions != null) { - identityDirectInfo = - (HashMap) extensions.get(IdentityConstants.SharedState.IdentityDirect.NAME); - } - } catch (ClassCastException e) { - MobileCore.log( - LoggingMode.DEBUG, - LOG_TAG, - "IdentityState - Unable to fetch com.adobe.module.identity info from Hub State due to invalid format, expected Map" - ); - } - } + final Map identityDirectInfo = DataReader.optTypedMap( + Object.class, + extensions, + IdentityConstants.SharedState.Hub.EXTENSIONS, + null + ); return !Utils.isNullOrEmpty(identityDirectInfo); } @@ -334,21 +340,6 @@ private void dispatchAdIdConsentRequestEvent(final String consentVal) { .setEventData(consentData) .build(); - MobileCore.dispatchEvent( - consentEvent, - new ExtensionErrorCallback() { - @Override - public void error(ExtensionError extensionError) { - MobileCore.log( - LoggingMode.DEBUG, - LOG_TAG, - "Failed to dispatch consent event " + - consentEvent.toString() + - ": " + - extensionError.getErrorName() - ); - } - } - ); + MobileCore.dispatchEvent(consentEvent); } } diff --git a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityStorageService.java b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityStorageService.java index a3b6d80b..fb6d2f51 100644 --- a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityStorageService.java +++ b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/IdentityStorageService.java @@ -18,6 +18,7 @@ import android.content.SharedPreferences; import com.adobe.marketing.mobile.LoggingMode; import com.adobe.marketing.mobile.MobileCore; +import com.adobe.marketing.mobile.util.JSONUtils; import java.util.Map; import org.json.JSONException; import org.json.JSONObject; @@ -59,7 +60,7 @@ static IdentityProperties loadPropertiesFromPersistence() { try { final JSONObject jsonObject = new JSONObject(jsonString); - final Map propertyMap = Utils.toMap(jsonObject); + final Map propertyMap = JSONUtils.toMap(jsonObject); return new IdentityProperties(propertyMap); } catch (JSONException exception) { MobileCore.log( diff --git a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/ListenerEdgeIdentityRemoveIdentity.java b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/ListenerEdgeIdentityRemoveIdentity.java deleted file mode 100644 index 1d734b63..00000000 --- a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/ListenerEdgeIdentityRemoveIdentity.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - Copyright 2021 Adobe. All rights reserved. - This file is licensed to you under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. You may obtain a copy - of the License at http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, software distributed under - the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS - OF ANY KIND, either express or implied. See the License for the specific language - governing permissions and limitations under the License. -*/ - -package com.adobe.marketing.mobile.edge.identity; - -import com.adobe.marketing.mobile.Event; -import com.adobe.marketing.mobile.ExtensionApi; -import com.adobe.marketing.mobile.ExtensionListener; -import com.adobe.marketing.mobile.LoggingMode; -import com.adobe.marketing.mobile.MobileCore; - -class ListenerEdgeIdentityRemoveIdentity extends ExtensionListener { - - /** - * Constructor. - * - * @param extensionApi an instance of {@link ExtensionApi} - * @param type the {@link String} eventType this listener is registered to handle - * @param source the {@link String} eventSource this listener is registered to handle - */ - ListenerEdgeIdentityRemoveIdentity(final ExtensionApi extensionApi, final String type, final String source) { - super(extensionApi, type, source); - } - - /** - * Method that gets called when event with event type {@link IdentityConstants.EventType#EDGE_IDENTITY} - * and with event source {@link IdentityConstants.EventSource#REMOVE_IDENTITY} is dispatched through eventHub. - * - * @param event the remove identity {@link Event} to be processed - */ - @Override - public void hear(final Event event) { - if (event == null || event.getEventData() == null) { - MobileCore.log( - LoggingMode.DEBUG, - IdentityConstants.LOG_TAG, - "ListenerEdgeIdentityRemoveIdentity - Event or Event data is null. Ignoring the event." - ); - return; - } - - final IdentityExtension parentExtension = getIdentityExtension(); - - if (parentExtension == null) { - MobileCore.log( - LoggingMode.DEBUG, - IdentityConstants.LOG_TAG, - "ListenerEdgeIdentityRemoveIdentity - The parent extension, associated with this listener is null, Ignoring the event." - ); - return; - } - - parentExtension - .getExecutor() - .execute( - new Runnable() { - @Override - public void run() { - parentExtension.processAddEvent(event); - } - } - ); - } - - /** - * Returns the parent extension associated with the listener. - * - * @return a {@link IdentityExtension} object registered with the eventHub - */ - IdentityExtension getIdentityExtension() { - return (IdentityExtension) getParentExtension(); - } -} diff --git a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/ListenerEdgeIdentityRequestIdentity.java b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/ListenerEdgeIdentityRequestIdentity.java deleted file mode 100644 index cf71f5a6..00000000 --- a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/ListenerEdgeIdentityRequestIdentity.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - Copyright 2021 Adobe. All rights reserved. - This file is licensed to you under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. You may obtain a copy - of the License at http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, software distributed under - the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS - OF ANY KIND, either express or implied. See the License for the specific language - governing permissions and limitations under the License. -*/ - -package com.adobe.marketing.mobile.edge.identity; - -import com.adobe.marketing.mobile.Event; -import com.adobe.marketing.mobile.ExtensionApi; -import com.adobe.marketing.mobile.ExtensionListener; -import com.adobe.marketing.mobile.LoggingMode; -import com.adobe.marketing.mobile.MobileCore; - -class ListenerEdgeIdentityRequestIdentity extends ExtensionListener { - - /** - * Constructor. - * - * @param extensionApi an instance of {@link ExtensionApi} - * @param type the {@link String} eventType this listener is registered to handle - * @param source the {@link String} eventSource this listener is registered to handle - */ - ListenerEdgeIdentityRequestIdentity(final ExtensionApi extensionApi, final String type, final String source) { - super(extensionApi, type, source); - } - - /** - * Method that gets called when event with event type {@link IdentityConstants.EventType#GENERIC_IDENTITY} - * and with event source {@link IdentityConstants.EventSource#REQUEST_CONTENT} is dispatched through eventHub. - * - * @param event the request identity {@link Event} to be processed - */ - @Override - public void hear(final Event event) { - if (event == null || event.getEventData() == null) { - MobileCore.log( - LoggingMode.DEBUG, - IdentityConstants.LOG_TAG, - "ListenerEdgeIdentityRequestIdentity - Event or Event data is null. Ignoring the event." - ); - return; - } - - final IdentityExtension parentExtension = getIdentityExtension(); - - if (parentExtension == null) { - MobileCore.log( - LoggingMode.DEBUG, - IdentityConstants.LOG_TAG, - "ListenerEdgeIdentityRequestIdentity - The parent extension, associated with this listener is null. Ignoring the event." - ); - return; - } - - parentExtension - .getExecutor() - .execute( - new Runnable() { - @Override - public void run() { - parentExtension.processAddEvent(event); - } - } - ); - } - - /** - * Returns the parent extension associated with the listener. - * - * @return a {@link IdentityExtension} object registered with the eventHub - */ - IdentityExtension getIdentityExtension() { - return (IdentityExtension) getParentExtension(); - } -} diff --git a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/ListenerEdgeIdentityUpdateIdentity.java b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/ListenerEdgeIdentityUpdateIdentity.java deleted file mode 100644 index 09bad374..00000000 --- a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/ListenerEdgeIdentityUpdateIdentity.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - Copyright 2021 Adobe. All rights reserved. - This file is licensed to you under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. You may obtain a copy - of the License at http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, software distributed under - the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS - OF ANY KIND, either express or implied. See the License for the specific language - governing permissions and limitations under the License. -*/ - -package com.adobe.marketing.mobile.edge.identity; - -import com.adobe.marketing.mobile.Event; -import com.adobe.marketing.mobile.ExtensionApi; -import com.adobe.marketing.mobile.ExtensionListener; -import com.adobe.marketing.mobile.LoggingMode; -import com.adobe.marketing.mobile.MobileCore; - -class ListenerEdgeIdentityUpdateIdentity extends ExtensionListener { - - /** - * Constructor. - * - * @param extensionApi an instance of {@link ExtensionApi} - * @param type the {@link String} eventType this listener is registered to handle - * @param source the {@link String} eventSource this listener is registered to handle - */ - ListenerEdgeIdentityUpdateIdentity(final ExtensionApi extensionApi, final String type, final String source) { - super(extensionApi, type, source); - } - - /** - * Method that gets called when event with event type {@link IdentityConstants.EventType#EDGE_IDENTITY} - * and with event source {@link IdentityConstants.EventSource#UPDATE_IDENTITY} is dispatched through eventHub. - * - * @param event the udpate identity {@link Event} to be processed - */ - @Override - public void hear(final Event event) { - if (event == null || event.getEventData() == null) { - MobileCore.log( - LoggingMode.DEBUG, - IdentityConstants.LOG_TAG, - "ListenerEdgeIdentityUpdateIdentity - Event or Event data is null. Ignoring the event." - ); - return; - } - - final IdentityExtension parentExtension = getIdentityExtension(); - - if (parentExtension == null) { - MobileCore.log( - LoggingMode.DEBUG, - IdentityConstants.LOG_TAG, - "ListenerEdgeIdentityUpdateIdentity - The parent extension, associated with this listener is null, ignoring event." - ); - return; - } - - parentExtension - .getExecutor() - .execute( - new Runnable() { - @Override - public void run() { - parentExtension.processAddEvent(event); - } - } - ); - } - - /** - * Returns the parent extension associated with the listener. - * - * @return a {@link IdentityExtension} object registered with the eventHub - */ - IdentityExtension getIdentityExtension() { - return (IdentityExtension) getParentExtension(); - } -} diff --git a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/ListenerEventHubBoot.java b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/ListenerEventHubBoot.java deleted file mode 100644 index d9872173..00000000 --- a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/ListenerEventHubBoot.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - Copyright 2021 Adobe. All rights reserved. - This file is licensed to you under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. You may obtain a copy - of the License at http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, software distributed under - the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS - OF ANY KIND, either express or implied. See the License for the specific language - governing permissions and limitations under the License. -*/ - -package com.adobe.marketing.mobile.edge.identity; - -import com.adobe.marketing.mobile.Event; -import com.adobe.marketing.mobile.ExtensionApi; -import com.adobe.marketing.mobile.ExtensionListener; -import com.adobe.marketing.mobile.LoggingMode; -import com.adobe.marketing.mobile.MobileCore; - -class ListenerEventHubBoot extends ExtensionListener { - - /** - * Constructor. - * - * @param extensionApi an instance of {@link ExtensionApi} - * @param type the {@link String} eventType this listener is registered to handle - * @param source the {@link String} eventSource this listener is registered to handle - */ - ListenerEventHubBoot(final ExtensionApi extensionApi, final String type, final String source) { - super(extensionApi, type, source); - } - - /** - * Method that gets called when event with event type {@link IdentityConstants.EventType#HUB} - * and with event source {@link IdentityConstants.EventSource#BOOTED} is dispatched through eventHub. - * - * @param event the boot {@link Event} - */ - @Override - public void hear(final Event event) { - final IdentityExtension parentExtension = getIdentityExtension(); - - if (parentExtension == null) { - MobileCore.log( - LoggingMode.DEBUG, - IdentityConstants.LOG_TAG, - "ListenerEventHubBoot - The parent extension associated with this listener is null, ignoring this event." - ); - return; - } - - parentExtension - .getExecutor() - .execute( - new Runnable() { - @Override - public void run() { - parentExtension.bootupIfReady(); - } - } - ); - } - - /** - * Returns the parent extension associated with the listener. - * - * @return a {@link IdentityExtension} object registered with the eventHub - */ - IdentityExtension getIdentityExtension() { - return (IdentityExtension) getParentExtension(); - } -} diff --git a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/ListenerHubSharedState.java b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/ListenerHubSharedState.java deleted file mode 100644 index 1f5125fd..00000000 --- a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/ListenerHubSharedState.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - Copyright 2021 Adobe. All rights reserved. - This file is licensed to you under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. You may obtain a copy - of the License at http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, software distributed under - the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS - OF ANY KIND, either express or implied. See the License for the specific language - governing permissions and limitations under the License. -*/ - -package com.adobe.marketing.mobile.edge.identity; - -import com.adobe.marketing.mobile.Event; -import com.adobe.marketing.mobile.ExtensionApi; -import com.adobe.marketing.mobile.ExtensionListener; -import com.adobe.marketing.mobile.LoggingMode; -import com.adobe.marketing.mobile.MobileCore; - -class ListenerHubSharedState extends ExtensionListener { - - /** - * Constructor. - * - * @param extensionApi an instance of {@link ExtensionApi} - * @param type the {@link String} eventType this listener is registered to handle - * @param source the {@link String} eventSource this listener is registered to handle - */ - ListenerHubSharedState(final ExtensionApi extensionApi, final String type, final String source) { - super(extensionApi, type, source); - } - - /** - * Method that gets called when event with event type {@link IdentityConstants.EventType#HUB} - * and with event source {@link IdentityConstants.EventSource#SHARED_STATE} is dispatched through eventHub. - * - * @param event the hub shared state change {@link Event} to be processed - */ - @Override - public void hear(final Event event) { - if (event == null || event.getEventData() == null) { - MobileCore.log( - LoggingMode.DEBUG, - IdentityConstants.LOG_TAG, - "ListenerHubSharedState - Event / EventData is null. Ignoring the event." - ); - return; - } - - final IdentityExtension parentExtension = getIdentityExtension(); - - if (parentExtension == null) { - MobileCore.log( - LoggingMode.DEBUG, - IdentityConstants.LOG_TAG, - "ListenerHubSharedState - The parent extension, associated with this listener is null, ignoring the event." - ); - return; - } - - parentExtension - .getExecutor() - .execute( - new Runnable() { - @Override - public void run() { - parentExtension.handleHubSharedState(event); - } - } - ); - } - - /** - * Returns the parent extension associated with the listener. - * - * @return a {@link IdentityExtension} object registered with the eventHub - */ - IdentityExtension getIdentityExtension() { - return (IdentityExtension) getParentExtension(); - } -} diff --git a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/ListenerIdentityRequestContent.java b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/ListenerIdentityRequestContent.java deleted file mode 100644 index c2222c80..00000000 --- a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/ListenerIdentityRequestContent.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - Copyright 2022 Adobe. All rights reserved. - This file is licensed to you under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. You may obtain a copy - of the License at http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, software distributed under - the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS - OF ANY KIND, either express or implied. See the License for the specific language - governing permissions and limitations under the License. -*/ - -package com.adobe.marketing.mobile.edge.identity; - -import com.adobe.marketing.mobile.Event; -import com.adobe.marketing.mobile.ExtensionApi; -import com.adobe.marketing.mobile.ExtensionListener; -import com.adobe.marketing.mobile.LoggingMode; -import com.adobe.marketing.mobile.MobileCore; - -class ListenerIdentityRequestContent extends ExtensionListener { - - /** - * Constructor. - * - * @param extensionApi an instance of {@link ExtensionApi} - * @param type the {@link String} eventType this listener is registered to handle - * @param source the {@link String} eventSource this listener is registered to handle - */ - ListenerIdentityRequestContent(final ExtensionApi extensionApi, final String type, final String source) { - super(extensionApi, type, source); - } - - /** - * Method that gets called when event with event type {@link IdentityConstants.EventType#GENERIC_IDENTITY} - * and with event source {@link IdentityConstants.EventSource#REQUEST_CONTENT} is dispatched through eventHub. - * - * @param event the advertising identifier request content {@link Event} to be processed - */ - @Override - public void hear(final Event event) { - if (event == null || event.getEventData() == null) { - MobileCore.log( - LoggingMode.DEBUG, - IdentityConstants.LOG_TAG, - "ListenerIdentityRequestContent - Event or Event data is null. Ignoring the event." - ); - return; - } - - final IdentityExtension parentExtension = getIdentityExtension(); - - if (parentExtension == null) { - MobileCore.log( - LoggingMode.DEBUG, - IdentityConstants.LOG_TAG, - "ListenerIdentityRequestContent - The parent extension, associated with this listener is null, ignoring event." - ); - return; - } - - parentExtension - .getExecutor() - .execute( - new Runnable() { - @Override - public void run() { - parentExtension.processAddEvent(event); - } - } - ); - } - - /** - * Returns the parent extension associated with the listener. - * - * @return a {@link IdentityExtension} object registered with the eventHub - */ - IdentityExtension getIdentityExtension() { - return (IdentityExtension) getParentExtension(); - } -} diff --git a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/ListenerIdentityRequestReset.java b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/ListenerIdentityRequestReset.java deleted file mode 100644 index fd7fc25c..00000000 --- a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/ListenerIdentityRequestReset.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - Copyright 2021 Adobe. All rights reserved. - This file is licensed to you under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. You may obtain a copy - of the License at http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, software distributed under - the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS - OF ANY KIND, either express or implied. See the License for the specific language - governing permissions and limitations under the License. -*/ - -package com.adobe.marketing.mobile.edge.identity; - -import com.adobe.marketing.mobile.Event; -import com.adobe.marketing.mobile.ExtensionApi; -import com.adobe.marketing.mobile.ExtensionListener; -import com.adobe.marketing.mobile.LoggingMode; -import com.adobe.marketing.mobile.MobileCore; - -class ListenerIdentityRequestReset extends ExtensionListener { - - /** - * Constructor. - * - * @param extensionApi an instance of {@link ExtensionApi} - * @param type the {@link String} eventType this listener is registered to handle - * @param source the {@link String} eventSource this listener is registered to handle - */ - ListenerIdentityRequestReset(final ExtensionApi extensionApi, final String type, final String source) { - super(extensionApi, type, source); - } - - /** - * Method that gets called when event with event type {@link IdentityConstants.EventType#GENERIC_IDENTITY} - * and with event source {@link IdentityConstants.EventSource#REQUEST_RESET} is dispatched through eventHub. - * - * @param event the identity reset request {@link Event} to be processed - */ - @Override - public void hear(final Event event) { - if (event == null || event.getEventData() == null) { - MobileCore.log( - LoggingMode.DEBUG, - IdentityConstants.LOG_TAG, - "ListenerIdentityRequestReset - Event or Event data is null. Ignoring the event." - ); - return; - } - - final IdentityExtension parentExtension = getIdentityExtension(); - - if (parentExtension == null) { - MobileCore.log( - LoggingMode.DEBUG, - IdentityConstants.LOG_TAG, - "ListenerIdentityRequestReset - The parent extension, associated with this listener is null, ignoring event." - ); - return; - } - - parentExtension - .getExecutor() - .execute( - new Runnable() { - @Override - public void run() { - parentExtension.processAddEvent(event); - } - } - ); - } - - /** - * Returns the parent extension associated with the listener. - * - * @return a {@link IdentityExtension} object registered with the eventHub - */ - IdentityExtension getIdentityExtension() { - return (IdentityExtension) getParentExtension(); - } -} diff --git a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/SharedStateCallback.java b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/SharedStateCallback.java index 9cda5606..8580e407 100644 --- a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/SharedStateCallback.java +++ b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/SharedStateCallback.java @@ -12,10 +12,11 @@ package com.adobe.marketing.mobile.edge.identity; import com.adobe.marketing.mobile.Event; +import com.adobe.marketing.mobile.SharedStateResult; import java.util.Map; /** - * Callback for fetching Shared States from the outside of the extension class. + * Callback for streamlining Shared State operations (within and outside the extension class) */ interface SharedStateCallback { /** @@ -23,9 +24,9 @@ interface SharedStateCallback { * * @param stateOwner Shared state owner name * @param event current event for which to fetch the shared state; if null is passed, the latest shared state will be returned - * @return current shared state if found, null if shared state is pending or an error occurred + * @return a {@code SharedStateResult} at the event; null if an error occurred */ - Map getSharedState(final String stateOwner, final Event event); + SharedStateResult getSharedState(final String stateOwner, final Event event); /** * Creates an XDM Shared State for the provided {@code event} with the specified {@code state}. @@ -33,5 +34,5 @@ interface SharedStateCallback { * @param state data to be set as XDM Shared State * @param event current event for which to set the shared state; if null is passed, the next shared state version will be set */ - boolean setXDMSharedEventState(final Map state, final Event event); + void createXDMSharedState(final Map state, final Event event); } diff --git a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/URLUtils.java b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/URLUtils.java index 2a62a87b..8b5e81e9 100644 --- a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/URLUtils.java +++ b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/URLUtils.java @@ -13,6 +13,7 @@ import com.adobe.marketing.mobile.LoggingMode; import com.adobe.marketing.mobile.MobileCore; +import com.adobe.marketing.mobile.util.StringUtils; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; @@ -48,7 +49,7 @@ static String generateURLVariablesPayload(final String ts, final String ecid, fi urlFragment.append(IdentityConstants.UrlKeys.PAYLOAD); urlFragment.append("="); - if (Utils.isNullOrEmpty(theIdString)) { + if (StringUtils.isNullOrEmpty(theIdString)) { // No need to encode urlFragment.append("null"); } else { @@ -75,7 +76,7 @@ static String generateURLVariablesPayload(final String ts, final String ecid, fi */ static String appendKVPToVisitorIdString(final String originalString, final String key, final String value) { // quickly return original string if key or value are empty - if (Utils.isNullOrEmpty(key) || Utils.isNullOrEmpty(value)) { + if (StringUtils.isNullOrEmpty(key) || StringUtils.isNullOrEmpty(value)) { return originalString; } @@ -83,7 +84,7 @@ static String appendKVPToVisitorIdString(final String originalString, final Stri final String newUrlVariable = String.format("%s=%s", key, value); // if the original string is not empty, we need to append a pipe before we return - if (Utils.isNullOrEmpty(originalString)) { + if (StringUtils.isNullOrEmpty(originalString)) { return newUrlVariable; } else { return String.format("%s|%s", originalString, newUrlVariable); diff --git a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/Utils.java b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/Utils.java index 4e628f4e..2ad211ea 100644 --- a/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/Utils.java +++ b/code/edgeidentity/src/main/java/com/adobe/marketing/mobile/edge/identity/Utils.java @@ -15,25 +15,17 @@ import com.adobe.marketing.mobile.LoggingMode; import com.adobe.marketing.mobile.MobileCore; +import com.adobe.marketing.mobile.util.JSONUtils; import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; -import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; class Utils { - private static final long MILLISECONDS_PER_SECOND = 1000L; - private Utils() {} - static boolean isNullOrEmpty(final String str) { - return str == null || str.isEmpty(); - } - static boolean isNullOrEmpty(final Map map) { return map == null || map.isEmpty(); } @@ -59,107 +51,6 @@ static void putIfNotNull(final Map map, final String key, final } } - /* JSON - Map conversion helpers */ - // TODO: add tests / replace with third party library for json conversion; test more around jsonObject/jsonArray with null nodes - // TODO: check what should be the expected behavior with the konductor team (e.g. don't add the null nodes or add them with null values) - - /** - * Converts provided {@link JSONObject} into {@link Map} for any number of levels, which can be used as event data - * This method is recursive. - * The elements for which the conversion fails will be skipped. - * - * @param jsonObject to be converted - * @return {@link Map} containing the elements from the provided json, null if {@code jsonObject} is null - */ - static Map toMap(final JSONObject jsonObject) { - if (jsonObject == null) { - return null; - } - - Map jsonAsMap = new HashMap<>(); - Iterator keysIterator = jsonObject.keys(); - - while (keysIterator.hasNext()) { - String nextKey = keysIterator.next(); - Object value = null; - Object returnValue; - - try { - value = jsonObject.get(nextKey); - } catch (JSONException e) { - MobileCore.log( - LoggingMode.DEBUG, - LOG_TAG, - "Utils(toMap) - Unable to convert jsonObject to Map for key " + nextKey + ", skipping." - ); - } - - if (value == null) { - continue; - } - - if (value instanceof JSONObject) { - returnValue = toMap((JSONObject) value); - } else if (value instanceof JSONArray) { - returnValue = toList((JSONArray) value); - } else { - returnValue = value; - } - - jsonAsMap.put(nextKey, returnValue); - } - - return jsonAsMap; - } - - /** - * Converts provided {@link JSONArray} into {@link List} for any number of levels which can be used as event data - * This method is recursive. - * The elements for which the conversion fails will be skipped. - * - * @param jsonArray to be converted - * @return {@link List} containing the elements from the provided json, null if {@code jsonArray} is null - */ - static List toList(final JSONArray jsonArray) { - if (jsonArray == null) { - return null; - } - - List jsonArrayAsList = new ArrayList<>(); - int size = jsonArray.length(); - - for (int i = 0; i < size; i++) { - Object value = null; - Object returnValue = null; - - try { - value = jsonArray.get(i); - } catch (JSONException e) { - MobileCore.log( - LoggingMode.DEBUG, - LOG_TAG, - "Utils(toList) - Unable to convert jsonObject to List for index " + i + ", skipping." - ); - } - - if (value == null) { - continue; - } - - if (value instanceof JSONObject) { - returnValue = toMap((JSONObject) value); - } else if (value instanceof JSONArray) { - returnValue = toList((JSONArray) value); - } else { - returnValue = value; - } - - jsonArrayAsList.add(returnValue); - } - - return jsonArrayAsList; - } - /** * Creates a deep copy of the provided {@link Map}. * @@ -172,8 +63,12 @@ static Map deepCopy(final Map map) { } try { - return Utils.toMap(new JSONObject(map)); - } catch (NullPointerException e) { + // Core's JSONUtils retains null in resulting Map but, EdgeIdentity 1.0 implementaion + // filtered out the null value keys. One issue this may cause is sending empty objects to + // Edge Network. + // TODO: Add/verify tests to check side effects of retaining nulls in the resulting Map + return JSONUtils.toMap(new JSONObject(map)); + } catch (final JSONException | NullPointerException e) { MobileCore.log( LoggingMode.DEBUG, LOG_TAG, @@ -204,13 +99,4 @@ static List> deepCopy(final List> listOf return deepCopy; } - - /** - * Gets current unix timestamp in seconds. - * - * @return {code long} current timestamp - */ - static long getUnixTimeInSeconds() { - return System.currentTimeMillis() / MILLISECONDS_PER_SECOND; - } } diff --git a/code/gradle.properties b/code/gradle.properties index 8f211c79..363b6f82 100644 --- a/code/gradle.properties +++ b/code/gradle.properties @@ -9,12 +9,12 @@ android.disableAutomaticComponentCreation=true moduleProjectName=edgeidentity moduleName=edgeidentity moduleAARName=edgeidentity-phone-release.aar -moduleVersion=1.1.0 +moduleVersion=2.0.0 mavenRepoName=AdobeMobileEdgeIdentitySdk mavenRepoDescription=Adobe Experience Platform Edge Identity extension for the Adobe Experience Platform Mobile SDK mavenUploadDryRunFlag=false # production versions for production build -mavenCoreVersion=1.8.0 +mavenCoreVersion=2.0.0 diff --git a/code/settings.gradle b/code/settings.gradle index bb5f0304..9782bf67 100644 --- a/code/settings.gradle +++ b/code/settings.gradle @@ -12,6 +12,7 @@ dependencyResolutionManagement { google() mavenCentral() maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } + maven { url 'https://jitpack.io' } } }