Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Added new getUrlVariables API #68

Merged
merged 7 commits into from
Jun 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
374 changes: 357 additions & 17 deletions Documentation/api-reference.md

Large diffs are not rendered by default.

60 changes: 60 additions & 0 deletions Documentation/getting-started.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
## Getting started

The Adobe Experience Platform Identity for Edge Network extension has the following peer dependency, which must be installed prior to installing the identity extension:
- [Mobile Core](https://aep-sdks.gitbook.io/docs/foundation-extensions/mobile-core)

## Add the AEP Identity extension to your app

### Download and import the Identity extension

> :information_source: The following instructions are for configuring an application using Adobe Experience Platform Edge mobile extensions. If an application will include both Edge Network and Adobe Solution extensions, both the Identity for Edge Network and Identity for Experience Cloud ID Service extensions are required. Find more details in the [Frequently Asked Questions](https://aep-sdks.gitbook.io/docs/foundation-extensions/identity-for-edge-network/identity-faq) page.


### Java

1. Add the Mobile Core and Edge extensions to your project using the app's Gradle file.

```java
implementation 'com.adobe.marketing.mobile:core:1.+'
implementation 'com.adobe.marketing.mobile:edge:1.+'
implementation 'com.adobe.marketing.mobile:edgeidentity:1.+'
```

2. Import the Mobile Core and Edge extensions in your Application class.

```java
import com.adobe.marketing.mobile.MobileCore;
import com.adobe.marketing.mobile.Edge;
import com.adobe.marketing.mobile.edge.identity.Identity;
```

3. Register the Identity for Edge Extension with MobileCore:

### Java

```java
public class MobileApp extends Application {

@Override
public void onCreate() {
super.onCreate();
MobileCore.setApplication(this);
try {
Edge.registerExtension();
Identity.registerExtension();
// register other extensions
MobileCore.start(new AdobeCallback () {
@Override
public void call(Object o) {
MobileCore.configureWithAppID("yourAppId");
}
});

} catch (Exception e) {
...
}


}
}
```
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ class SharedViewModel : ViewModel() {
private val _ecidLegacyText = MutableLiveData<String>("")
val ecidLegacyText: LiveData<String> = _ecidLegacyText

private val _urlVariablesText = MutableLiveData<String>("")
val urlVariablesText: LiveData<String> = _urlVariablesText

private val _identitiesText = MutableLiveData<String>("")
val identitiesText: LiveData<String> = _identitiesText

Expand All @@ -51,6 +54,10 @@ class SharedViewModel : ViewModel() {
_ecidLegacyText.value = value
}

fun setUrlVariablesValue(value: String) {
_urlVariablesText.value = value
}

fun setIdentitiesValue(value: String) {
_identitiesText.value = value
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@ class GetIdentityFragment : Fragment() {
}
)

val urlVariablesTextView = root.findViewById<TextView>(R.id.text_url_variables)
sharedViewModel.urlVariablesText.observe(
viewLifecycleOwner,
Observer {
urlVariablesTextView.text = it
}
)

val identitiesTextView = root.findViewById<TextView>(R.id.text_identities)
sharedViewModel.identitiesText.observe(
viewLifecycleOwner,
Expand Down Expand Up @@ -85,6 +93,21 @@ class GetIdentityFragment : Fragment() {
sharedViewModel.setEcidLegacyValue(if (resultSecondary != null) "legacy: $resultSecondary" else "")
}

root.findViewById<Button>(R.id.btn_get_url_variables).setOnClickListener {
val latch = CountDownLatch(2)
var resultUrlVariables: String? = null

com.adobe.marketing.mobile.edge.identity.Identity.getUrlVariables { urlVariables ->
Log.d("Home", "Got UrlVariables String: $urlVariables")
resultUrlVariables = urlVariables
latch.countDown()
}

latch.await(1, TimeUnit.SECONDS)

sharedViewModel.setUrlVariablesValue(if (resultUrlVariables != null) "urlVariablesString: $resultUrlVariables" else "urlVariablesString: not found")
}

root.findViewById<Button>(R.id.btn_get_identities).setOnClickListener {
val latch = CountDownLatch(1)
var result: String? = null
Expand Down
25 changes: 25 additions & 0 deletions code/app/src/main/res/layout/fragment_get_identity.xml
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,38 @@

</LinearLayout>

<Button
android:id="@+id/btn_get_url_variables"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/btn_get_url_variables"
android:layout_gravity="center"
android:layout_marginTop="18dp"
/>

<TextView
android:id="@+id/text_url_variables"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:textAlignment="center"
android:textSize="12sp"
android:layout_gravity="center"
android:scrollbars="vertical"
android:background="@drawable/border"
/>

<Button
android:id="@+id/btn_reset_identities"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/btn_reset_identities"
android:layout_gravity="center"
android:layout_marginTop="18dp"
android:backgroundTint="@android:color/holo_red_light"
android:textColor="@android:color/white"
/>

<Button
Expand Down
1 change: 1 addition & 0 deletions code/app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<string name="menu_custom_identity">Set Custom Identity</string>
<string name="menu_multiple_identity">Test Multiple Identities</string>
<string name="btn_get_ecid">Get ECID</string>
<string name="btn_get_url_variables">Get URL Variables</string>
<string name="btn_get_identities">Get Identities</string>
<string name="btn_reset_identities">Reset Identities</string>
<string name="label_identifier">Identifier: </string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,19 @@ public void call(Object o) {
resetTestExpectations();
}

/**
* Updates configuration shared state with an orgId
*/
static void setupConfiguration() throws Exception {
HashMap<String, Object> config = new HashMap<String, Object>() {
{
put("experienceCloud.org", "testOrg@AdobeOrg");
}
};
MobileCore.updateConfiguration(config);
TestHelper.waitForThreads(2000);
}

/**
* Set the ECID in persistence for Identity Direct extension.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

import static com.adobe.marketing.mobile.TestHelper.*;
import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.registerEdgeIdentityExtension;
import static com.adobe.marketing.mobile.edge.identity.IdentityFunctionalTestUtil.setupConfiguration;
import static com.adobe.marketing.mobile.edge.identity.IdentityTestUtil.*;
import static org.junit.Assert.*;

Expand Down Expand Up @@ -282,6 +283,29 @@ public void testGetExperienceCloudId_nullCallback() {
}
}

// --------------------------------------------------------------------------------------------
// Tests for getUrlVariables API
// --------------------------------------------------------------------------------------------

@Test
public void testGetUrlVariables() throws Exception {
// test
setupConfiguration();
String urlVariables = getUrlVariablesSync();

assertNotNull(urlVariables);
}

@Test
public void testGetUrlVariables_nullCallback() {
// test
try {
Identity.getUrlVariables(null); // should not crash
} catch (Exception e) {
fail();
}
}

// --------------------------------------------------------------------------------------------
// Tests for getIdentities API
// --------------------------------------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,33 @@ static boolean isRequestContentEvent(final Event event) {
);
}

/**
* 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
* @param event the event to verify
* @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}
*
Expand Down Expand Up @@ -186,4 +213,34 @@ static ECID getECID(final Map<String, Object> identityDirectSharedState) {

return legacyEcid;
}

/**
* Extracts the Experience Cloud Org Id from the Configuration shared state
*
* @param configurationSharedState the configuration shared state data
* @return the Experience Cloud Org Id or null if not found or unable to parse the payload
*/
static String getOrgId(final Map<String, Object> 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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
import com.adobe.marketing.mobile.ExtensionErrorCallback;
import com.adobe.marketing.mobile.LoggingMode;
import com.adobe.marketing.mobile.MobileCore;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* Defines the public APIs for the AEP Edge Identity extension.
Expand Down Expand Up @@ -136,6 +138,91 @@ public void call(Event responseEvent) {
);
}

/**
* Returns the identifiers in URL query parameter format for consumption in hybrid mobile applications.
* There is no leading &amp; or ? punctuation as the caller is responsible for placing the variables in their resulting URL in the correct locations.
* If an error occurs while retrieving the URL variables, the AdobeCallbackWithError is called with a null value and AdobeError instance.
* If AdobeCallback is provided then callback is not called in case of error.
* Otherwise, the encoded string is returned, for ex: "adobe_mc=TS%3DTIMESTAMP_VALUE%7CMCMID%3DYOUR_ECID%7CMCORGID%3D9YOUR_EXPERIENCE_CLOUD_ID"
* The {@code adobe_mc} attribute is an URL encoded list that contains:
* <ul>
* <li>TS: a timestamp taken when the request was made</li>
* <li>MCID: Experience Cloud ID (ECID)</li>
* <li>MCORGID: Experience Cloud Org ID</li>
* </ul>
*
* @param callback {@link AdobeCallback} of {@code String} invoked with a value containing the identifiers in query parameter format.
* If an {@link AdobeCallbackWithError} is provided, an {@link AdobeError} can be returned in the
* eventuality of any error that occurred while getting the identifiers query string
*/
public static void getUrlVariables(final AdobeCallback<String> callback) {
if (callback == null) {
MobileCore.log(
LoggingMode.DEBUG,
LOG_TAG,
"Identity - Unexpected null callback, provide a callback to retrieve current visitor identifiers (URLVariables) query string."
);
return;
}

final Event event = new Event.Builder(
IdentityConstants.EventNames.IDENTITY_REQUEST_URL_VARIABLES,
IdentityConstants.EventType.EDGE_IDENTITY,
IdentityConstants.EventSource.REQUEST_IDENTITY
)
.setEventData(
new HashMap<String, Object>() {
{
put(IdentityConstants.EventDataKeys.URL_VARIABLES, true);
}
}
)
.build();

final ExtensionErrorCallback<ExtensionError> errorCallback = new ExtensionErrorCallback<ExtensionError>() {
@Override
public void error(final ExtensionError extensionError) {
returnError(callback, extensionError);
MobileCore.log(
LoggingMode.DEBUG,
LOG_TAG,
String.format(
"Identity - Failed to dispatch %s event: Error : %s.",
IdentityConstants.EventNames.IDENTITY_REQUEST_URL_VARIABLES,
extensionError.getErrorName()
)
);
}
};

MobileCore.dispatchEventWithResponseCallback(
event,
new AdobeCallback<Event>() {
@Override
public void call(Event responseEvent) {
if (responseEvent == null || responseEvent.getEventData() == null) {
returnError(callback, AdobeError.UNEXPECTED_ERROR);
return;
}

final Map<String, Object> 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
);
}

/**
* Updates the currently known {@link IdentityMap} within the SDK.
* The Identity extension will merge the received identifiers with the previously saved one in an additive manner,
Expand Down
Loading