diff --git a/.circleci/config.yml b/.circleci/config.yml index 6c71bdd5..ad3cbc41 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -48,9 +48,9 @@ jobs: name: Build command: make ci-build - - run: - name: Build App - command: make ci-build-app + # - run: + # name: Build App + # command: make ci-build-app - run: name: UnitTests diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 524718e3..d9a6f74a 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,16 +1,8 @@ - - - -### Expected Behaviour - -### Actual Behaviour - -### Reproduce Scenario (including but not limited to) - -#### Steps to Reproduce - -#### Platform and Version - -#### Sample Code that illustrates the problem - -#### Logs taken while reproducing problem +--- +name: Blank issue +labels: task +--- +## Prerequisites + +- [ ] I have searched in this repository's issues to see if it has already been reported. +- [ ] This is not a Security Disclosure, otherwise please follow the guidelines in [Security Policy](https://github.com/adobe/aepsdk-edgeidentity-android/security/policy). diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 00000000..7ef16c91 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,70 @@ +name: Bug report +description: Create a bug report to help us improve. Use this template if you encountered an issue while integrating with or implementing the APIs of this SDK. +labels: [bug, triage-required] + +body: +- type: checkboxes + attributes: + label: Prerequisites + description: Please check the following items before logging a new bug report. + options: + - label: This is not a Security Disclosure, otherwise please follow the guidelines in [Security Policy](https://github.com/adobe/aepsdk-edgeidentity-android/security/policy). + required: true + - label: I have searched in this repository's issues to see if it has already been reported. + required: true + - label: I have updated to the latest released version of the SDK and the issue still persists. + required: true + +- type: textarea + attributes: + label: Bug summary + description: Please provide a summary of the bug you are reporting. + validations: + required: true + +- type: textarea + attributes: + label: Environment + description: | + Please provide the OS version, SDK version(s) used, IDE version, and any other specific settings that could help us narrow down the problem. + Example: + - **OS**: Android 13 + - **SDK(s)**: edgeidentity 2.0.0, edge 2.0.0, core 2.0.0 + - **IDE**: Android Studio 2021.3.1 Patch 1 + validations: + required: true + +- type: textarea + attributes: + label: Steps to reproduce + description: Steps to reproduce the behavior consistently. + placeholder: | + 1. ... + 2. ... + 3. ... + validations: + required: false + +- type: textarea + attributes: + label: Current behavior + description: A concise description of what you are experiencing. + validations: + required: false + +- type: textarea + attributes: + label: Expected behavior + description: A concise description of what you expected to happen. + validations: + required: false + +- type: textarea + attributes: + label: Anything else? + description: | + Here you can include sample code that illustrates the problem, logs taken while reproducing the problem, or anything that can give us more context about the issue you are encountering. + + Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in. + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 00000000..b220d582 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,43 @@ +name: Feature request +description: Suggest an idea for this project. +labels: [feature-request, triage-required] + +body: +- type: checkboxes + attributes: + label: Prerequisites + description: Please check the following items before logging a new feature request. + options: + - label: This is not a Security Disclosure, otherwise please follow the guidelines in [Security Policy](https://github.com/adobe/aepsdk-edgeidentity-android/security/policy). + required: true + - label: I have searched in this repository's issues to see if it has already been reported. + required: true + +- type: textarea + id: description + attributes: + label: Feature request summary + description: Please provide a summary of the feature. + validations: + required: true + +- type: textarea + attributes: + label: Current behavior + description: A concise description of what you are experiencing. + validations: + required: false + +- type: textarea + attributes: + label: Expected behavior + description: A concise description of what you expected to happen. + validations: + required: false + +- type: textarea + attributes: + label: Additional implementation details or code snippets + description: Provide additional information about this request, implementation details or code snippets. + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/project_epic.yml b/.github/ISSUE_TEMPLATE/project_epic.yml new file mode 100644 index 00000000..eec745ae --- /dev/null +++ b/.github/ISSUE_TEMPLATE/project_epic.yml @@ -0,0 +1,24 @@ +name: Project epic +description: Create an internal epic that represents the top level parent of multiple tasks. +labels: [epic] + +body: +- type: textarea + id: description + attributes: + label: Epic description + description: Please provide a detailed description for this epic. + validations: + required: true + +- type: textarea + id: tasks + attributes: + label: Tasks + description: | + Provide a high-level definition of done for this epic as a list of tasks that need to be completed. + Tip: List out the task links if they already exist or list them out as text with a descriptive title so they can be easily converted to task items. + placeholder: | + - [ ] your task link here + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/project_task.yml b/.github/ISSUE_TEMPLATE/project_task.yml new file mode 100644 index 00000000..f4334a3b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/project_task.yml @@ -0,0 +1,17 @@ +name: Project task +description: Create an internal task that can be completed as a standalone code change or is part of an epic. +labels: [task] +body: +- type: textarea + attributes: + label: Task description + description: Please provide a summary or the "what" of the task logged. + validations: + required: true + +- type: textarea + attributes: + label: Additional implementation details or code snippet(s) + description: Provide additional information about this task, implementation details or code snippets. + validations: + required: false diff --git a/.github/workflows/maven-release.yml b/.github/workflows/maven-release.yml index fbff1c77..627da1b4 100644 --- a/.github/workflows/maven-release.yml +++ b/.github/workflows/maven-release.yml @@ -11,7 +11,7 @@ jobs: - name: Set up Java uses: actions/setup-java@v1 with: - java-version: 1.8 + java-version: 11 - name: Cache Gradle packages uses: actions/cache@v2 with: diff --git a/.github/workflows/maven-snapshot.yml b/.github/workflows/maven-snapshot.yml index 748479fb..aa38ba6c 100644 --- a/.github/workflows/maven-snapshot.yml +++ b/.github/workflows/maven-snapshot.yml @@ -11,7 +11,7 @@ jobs: - name: Set up Java uses: actions/setup-java@v1 with: - java-version: 1.8 + java-version: 11 - name: Cache Gradle packages uses: actions/cache@v2 with: diff --git a/.gitignore b/.gitignore index f86dd9f4..bbccea0c 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,20 @@ ci/ **/.idea/ # Secrets -**/*/values/secrets.xml \ No newline at end of file +**/*/values/secrets.xml + +# Local configuration file (sdk path, etc) +local.properties + +# Android Studio Navigation editor temp files +.navigation/ + +# Coverage tools +jacoco.exec + +# Application files +*.apk +*.aab + +# Dex files for ART/Dalvik VM +*.dex diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 7ba0d6a4..7f3d977d 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -2,73 +2,78 @@ ## Our Pledge -In the interest of fostering an open and welcoming environment, we as -contributors and maintainers pledge to making participation in our project and -our community a harassment-free experience for everyone, regardless of age, body -size, disability, ethnicity, gender identity and expression, level of experience, -nationality, personal appearance, race, religion, or sexual identity and -orientation. +We as members, contributors, and leaders pledge to make participation in our project and community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. ## Our Standards -Examples of behavior that contributes to creating a positive environment -include: +Examples of behavior that contribute to a positive environment for our project and community include: -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience +* Focusing on what is best, not just for us as individuals but for the overall community -Examples of unacceptable behavior by participants include: +Examples of unacceptable behavior include: -* The use of sexualized language or imagery and unwelcome sexual attention or -advances -* Trolling, insulting/derogatory comments, and personal or political attacks +* The use of sexualized language or imagery, and sexual attention or advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks * Public or private harassment -* Publishing others' private information, such as a physical or electronic - address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting +* Publishing others’ private information, such as a physical or email address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities -Project maintainers are responsible for clarifying the standards of acceptable -behavior and are expected to take appropriate and fair corrective action in -response to any instances of unacceptable behavior. +Project maintainers are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any instances of unacceptable behavior. -Project maintainers have the right and responsibility to remove, edit, or -reject comments, commits, code, wiki edits, issues, and other contributions -that are not aligned to this Code of Conduct, or to ban temporarily or -permanently any contributor for other behaviors that they deem inappropriate, -threatening, offensive, or harmful. +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope -This Code of Conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. Examples of -representing a project or community include using an official project e-mail -address, posting via an official social media account, or acting as an appointed -representative at an online or offline event. Representation of a project may be -further defined and clarified by project maintainers. +This Code of Conduct applies when an individual is representing the project or its community both within project spaces and in public spaces. Examples of representing a project or community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. ## Enforcement -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting the project team at Grp-opensourceoffice@adobe.com. All -complaints will be reviewed and investigated and will result in a response that -is deemed necessary and appropriate to the circumstances. The project team is -obligated to maintain confidentiality with regard to the reporter of an incident. -Further details of specific enforcement policies may be posted separately. +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by first contacting the project team. Oversight of Adobe projects is handled by the Adobe Open Source Office, which has final say in any violations and enforcement of this Code of Conduct and can be reached at Grp-opensourceoffice@adobe.com. All complaints will be reviewed and investigated promptly and fairly. + +The project team must respect the privacy and security of the reporter of any incident. + +Project maintainers who do not follow or enforce the Code of Conduct may face temporary or permanent repercussions as determined by other members of the project's leadership or the Adobe Open Source Office. + +## Enforcement Guidelines + +Project maintainers will follow these Community Impact Guidelines in determining the consequences for any action they deem to be in violation of this Code of Conduct: + +**1. Correction** + +Community Impact: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community. + +Consequence: A private, written warning from project maintainers describing the violation and why the behavior was unacceptable. A public apology may be requested from the violator before any further involvement in the project by violator. + +**2. Warning** + +Community Impact: A relatively minor violation through a single incident or series of actions. + +Consequence: A written warning from project maintainers that includes stated consequences for continued unacceptable behavior. Violator must refrain from interacting with the people involved for a specified period of time as determined by the project maintainers, including, but not limited to, unsolicited interaction with those enforcing the Code of Conduct through channels such as community spaces and social media. Continued violations may lead to a temporary or permanent ban. + +**3. Temporary Ban** + +Community Impact: A more serious violation of community standards, including sustained unacceptable behavior. + +Consequence: A temporary ban from any interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Failure to comply with the temporary ban may lead to a permanent ban. + +**4. Permanent Ban** + +Community Impact: Demonstrating a consistent pattern of violation of community standards or an egregious violation of community standards, including, but not limited to, sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. -Project maintainers who do not follow or enforce the Code of Conduct in good -faith may face temporary or permanent repercussions as determined by other -members of the project's leadership. +Consequence: A permanent ban from any interaction with the community. ## Attribution -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, -available at [https://contributor-covenant.org/version/1/4][version] +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.1, +available at [https://contributor-covenant.org/version/2/1][version] [homepage]: https://contributor-covenant.org -[version]: https://contributor-covenant.org/version/1/4/ +[version]: https://contributor-covenant.org/version/2/1 \ No newline at end of file diff --git a/COPYRIGHT b/COPYRIGHT index 8aa33c0c..b67d6c5e 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -1,4 +1,4 @@ -© Copyright 2015-2021 Adobe. All rights reserved. +© Copyright 2015-2023 Adobe. All rights reserved. Adobe holds the copyright for all the files found in this repository. diff --git a/Documentation/README.md b/Documentation/README.md index 5967d96f..e46f8815 100644 --- a/Documentation/README.md +++ b/Documentation/README.md @@ -1,53 +1,8 @@ -# Advertising identifier - -## Configuration -To enable advertising identifier features in the sample app, follow these steps: -1. Update the value for key `gms_ads_app_id` located in the `secrets.xml` at [aepsdk-edgeidentity-android/code/app/src/main/res/values](../code/app/src/main/res/values/secrets.xml) with a valid Google AdMob app ID. - - See Google's [quick start reference](https://developers.google.com/admob/android/quick-start) on how to get your AdMob app ID. See step 3 of the [Configure your app](https://developers.google.com/admob/android/quick-start#import_the_mobile_ads_sdk) section for a free public test app ID from Google. - - Any real key values in the `secrets.xml` file should **not** be committed to the repository. -2. By default, the ad ID features are commented out in the sample app. To enable these features, uncomment the implemention code using [find and replace all](https://www.jetbrains.com/help/idea/finding-and-replacing-text-in-project.html#replace_search_string_in_project) to replace all instances of: -```java -/* Ad ID implementation -``` -with: -```java -//* Ad ID implementation -``` -Each code block has a pair of block comments wrapped around it to enable this behavior: -```java -/* Ad ID implementation (pt. 1/4) - -/* Ad ID implementation (pt. 1/4) */ -``` - -After replacement it will become: -```java -//* Ad ID implementation (pt. 1/4) - -//* Ad ID implementation (pt. 1/4) */ -``` - -For convenience, these are the default find and replace shortcuts in Android Studio: -[Default shortcuts for find and replace](./assets/find-and-replace-shortcuts.png) - -The shortcut should open a window that looks like the following: -[Example of find and replace](./assets/find-and-replace-all-example.png) -There should be 5 pairs of special comment blocks (10 total matches) across two files: -`app/build.gradle`, `CustomIdentityFragment.kt`, and `SharedViewModel.kt` - -3. With the implementation code and gradle files uncommented with new dependencies, sync the project with the Gradle file changes using: File -> Sync Project with Gradle Files - -[Example of find and replace](./assets/sync-project-gradle-example.png) - -The app should now be properly configured to use advertising identifier features. - -To **disable** these features, follow these steps: -1. [Find and replace](https://www.jetbrains.com/help/idea/finding-and-replacing-text-in-project.html#replace_search_string_in_project) all instances of: -```java -//* Ad ID implementation -``` -with: -```java -/* Ad ID implementation -``` -2. Sync Project with Gradle files using: File -> Sync Project with Gradle Files \ No newline at end of file +# Edge Identity extension documentation + +## Contents +- [Getting started](getting-started.md) +- [API reference](api-reference.md) +- [Getting started with the test app](getting-started-test-app.md) +- [Troubleshooting guide](troubleshooting-guide.md) +- [Frequently asked questions](frequently-asked-questions.md) \ No newline at end of file diff --git a/Documentation/api-reference.md b/Documentation/api-reference.md index 218a5dc7..48310377 100644 --- a/Documentation/api-reference.md +++ b/Documentation/api-reference.md @@ -1,4 +1,4 @@ -# Adobe Experience Platform Identity for Edge Network Extension - Android +# Adobe Experience Platform Identity for Edge Network Extension Android API Reference ## Prerequisites @@ -35,13 +35,25 @@ public static String extensionVersion() ```java String extensionVersion = Identity.extensionVersion(); ``` + +#### Kotlin + +##### Syntax +```kotlin +fun extensionVersion(): String +``` + +##### Example +```kotlin +val extensionVersion = Identity.extensionVersion() +``` ------ ### getExperienceCloudId This API retrieves the Experience Cloud ID (ECID) that was generated when the app was initially launched. This ID is preserved between app upgrades, is saved and restored during the standard application backup process, and is removed at uninstall. -> **Note** +> **Note** > The ECID value is returned via the `AdobeCallback`. When `AdobeCallbackWithError` is provided to this API, the timeout value is 500ms. If the operation times out or an unexpected error occurs, the `fail` method is called with the appropriate `AdobeError`. #### Java @@ -63,6 +75,20 @@ Identity.getExperienceCloudId(new AdobeCallback() { }); ``` +#### Kotlin + +##### Syntax +```kotlin +fun getExperienceCloudId(callback: AdobeCallback) +``` + +##### Example +```kotlin +Identity.getExperienceCloudId { id -> + //Handle the ID returned here +} +``` + ------ ### getIdentities @@ -90,6 +116,20 @@ Identity.getIdentities(new AdobeCallback() { }); ``` +#### Kotlin + +##### Syntax +```kotlin +fun getIdentities(callback: AdobeCallback) +``` + +##### Example +```kotlin +Identity.getIdentities { identityMap -> + //Handle the IdentityMap returned here +} +``` + ------ ### getUrlVariables @@ -128,14 +168,34 @@ Identity.getUrlVariables(new AdobeCallback() { }); ``` +#### Kotlin + +##### Syntax +```kotlin +fun getUrlVariables(callback: AdobeCallback) +``` + +##### Example +```kotlin +Identity.getUrlVariables { urlVariablesString -> + //handle the URL query parameter string here + //For example, open the URL in a webView + val webView = findViewById(R.id.your_webview) // initialize with your webView + webView.loadUrl("http://www.example.com?" + urlVariablesString) +} +``` + ------ ### registerExtension Registers the Identity for Edge Network extension with the Mobile Core extension. +> **Warning** +> Deprecated as of 2.0.0. Use the [MobileCore.registerExtensions API](https://github.com/adobe/aepsdk-core-android/blob/main/Documentation/MobileCore/api-reference.md) instead. + > **Note** -> If your use-case covers both Edge Network and Adobe Experience Cloud Solutions extensions, you need to register Identity for Edge Network and Identity for Experience Cloud Identity Service from Mobile Core extensions. For more details, see the [frequently asked questions](https://aep-sdks.gitbook.io/docs/foundation-extensions/identity-for-edge-network/identity-faq#q-i-am-using-aep-edge-and-adobe-solutions-extensions-which-identity-extension-should-i-install-and-register). +> If your use-case covers both Edge Network and Adobe Experience Cloud Solutions extensions, you need to register Identity for Edge Network and Identity for Experience Cloud Identity Service from Mobile Core extensions. For more details, see the [frequently asked questions](frequently-asked-questions.md). #### Java @@ -152,6 +212,18 @@ import com.adobe.marketing.mobile.edge.identity.Identity Identity.registerExtension(); ``` +#### Kotlin + +##### Syntax +```kotlin +fun registerExtension() +``` + +##### Example +```kotlin +Identity.registerExtension() +``` + ------ ### removeIdentity @@ -179,6 +251,19 @@ IdentityItem item = new IdentityItem("user@example.com"); Identity.removeIdentity(item, "Email"); ``` +#### Kotlin + +##### Syntax +```kotlin +fun removeIdentity(item: IdentityItem, namespace: String) +``` + +##### Example +```kotlin +val item = IdentityItem("user@example.com") +Identity.removeIdentity(item, "Email") +``` + ------ ### resetIdentities @@ -192,12 +277,12 @@ Some example use cases for this API are: * A last-resort reset for when an ECID should no longer be used. This API is not recommended for: -* Resetting a user's consent and privacy settings; see [Privacy and GDPR](https://aep-sdks.gitbook.io/docs/resources/privacy-and-gdpr). +* Resetting a user's consent and privacy settings; see [Privacy and GDPR](https://developer.adobe.com/client-sdks/documentation/privacy-and-gdpr). * Removing existing custom identifiers; use the [`removeIdentity`](#removeidentity) API instead. -* Removing a previously synced advertising identifier after the advertising tracking settings were changed by the user; use the [`setAdvertisingIdentifier`](https://aep-sdks.gitbook.io/docs/foundation-extensions/mobile-core/identity/identity-api-reference#setadvertisingidentifier) API instead. +* Removing a previously synced advertising identifier after the advertising tracking settings were changed by the user; use the [`setAdvertisingIdentifier`](#setadvertisingidentifier) API instead. > **Warning** ->The Identity for Edge Network extension does not read the Mobile SDK's privacy status, and therefore setting the SDK's privacy status to opt-out will not automatically clear the identities from the Identity for Edge Network extension. See [`MobileCore.resetIdentities`](https://aep-sdks.gitbook.io/docs/foundation-extensions/mobile-core/mobile-core-api-reference#resetidentities) for more details. +>The Identity for Edge Network extension does not read the Mobile SDK's privacy status, and therefore setting the SDK's privacy status to opt-out will not automatically clear the identities from the Identity for Edge Network extension. See [`MobileCore.resetIdentities`](https://github.com/adobe/aepsdk-core-android/blob/main/Documentation/MobileCore/api-reference.md) for more details. ------ @@ -208,7 +293,7 @@ When this API is called with a valid advertising identifier, the Identity for Ed The GAID is preserved between app upgrades, is saved and restored during the standard application backup process, and is removed at uninstall. > **Warning** -> In order to enable collection of the user's current advertising tracking authorization selection for the provided advertising identifier, you need to install and register the [AEPEdgeConsent](https://aep-sdks.gitbook.io/docs/foundation-extensions/consent-for-edge-network) extension and update the [AEPEdge](https://aep-sdks.gitbook.io/docs/foundation-extensions/experience-platform-extension) dependency to minimum 1.3.2. +> In order to enable collection of the user's current advertising tracking authorization selection for the provided advertising identifier, you need to install and register the [Consent](https://github.com/adobe/aepsdk-edgeconsent-android) extension and update the [Edge](https://github.com/adobe/aepsdk-edge-android) dependency to minimum 1.3.2. > **Note** > These examples require Google Play Services to be configured in your mobile application, and use the Google Mobile Ads Lite SDK. For instructions on how to import the SDK and configure your `ApplicationManifest.xml` file, see [Google Mobile Ads Lite SDK setup](https://developers.google.com/admob/android/lite-sdk). @@ -367,6 +452,22 @@ identityMap.addItem(item, "Email") Identity.updateIdentities(identityMap); ``` + +#### Kotlin + +##### Syntax +```kotlin +fun updateIdentities(identityMap: IdentityMap) +``` + +##### Example +```kotlin +val item = IdentityItem("user@example.com") +val identityMap = IdentityMap() +identityMap.addItem(item, "Email") +Identity.updateIdentities(identityMap) +``` + ------ ## Public Classes @@ -377,7 +478,7 @@ Defines a map containing a set of end user identities, keyed on either namespace The format of the IdentityMap class is defined by the [XDM Identity Map Schema](https://github.com/adobe/xdm/blob/master/docs/reference/mixins/shared/identitymap.schema.md). -For more information, please read an overview of the [AEP Identity Service](https://experienceleague.adobe.com/docs/experience-platform/identity/home.html). +For more information, please read an overview of the [Adobe Experience Platform Identity Service](https://experienceleague.adobe.com/docs/experience-platform/identity/home.html). ```text "identityMap" : { @@ -412,6 +513,8 @@ For more information, please read an overview of the [AEP Identity Service](http **Example** +#### Java + ```java // Construct IdentityMap identityMap = new IdentityMap(); @@ -434,6 +537,30 @@ List namespaces = identityMap.getNamespaces(); boolean hasNotIdentities = identityMap.isEmpty(); ``` +#### Kotlin + +```kotlin +// Construct +val identityMap = IdentityMap() + +// Add an item +val item = IdentityItem("user@example.com") +identityMap.addItem(item, "Email") + +// Remove an item +val item = IdentityItem("user@example.com") +identityMap.removeItem(item, "Email") + +// Get a list of items for a given namespace +val items = identityMap.getIdentityItemsForNamespace("Email") + +// Get a list of all namespaces used in current IdentityMap +val namespaces = identityMap.getNamespaces() + +// Check if IdentityMap has no identities +val hasNotIdentities = identityMap.isEmpty() +``` + ------ ### IdentityItem @@ -444,6 +571,8 @@ The format of the IdentityItem class is defined by the [XDM Identity Item Schema **Example** +#### Java + ```java // Construct IdentityItem item = new IdentityItem("identifier"); @@ -459,11 +588,27 @@ AuthenticatedState state = item.getAuthenticatedState(); boolean primary = item.isPrimary(); ``` +#### Kotlin + +```kotlin +// Construct +val item = IdentityItem("identifier") + +val item = IdentityItem("identifier", AuthenticatedState.AUTHENTICATED, false) + +// Getters +val id = item.id + +val state = item.authenticatedState + +val primary = item.isPrimary +``` + ------ ### AuthenticatedState -Defines the state an [Identity Item](api-reference.md#identityitem) is authenticated for. +Defines the state an [Identity Item](#identityitem) is authenticated for. The possible authenticated states are: @@ -473,6 +618,8 @@ The possible authenticated states are: **Syntax** +#### Java + ```java public enum AuthenticatedState { AMBIGUOUS("ambiguous"), @@ -480,3 +627,12 @@ public enum AuthenticatedState { LOGGED_OUT("loggedOut"); } ``` +#### Kotlin + +```kotlin +enum class AuthenticatedState(val name: String) { + AMBIGUOUS("ambiguous"), + AUTHENTICATED("authenticated"), + LOGGED_OUT("loggedOut") +} +``` \ No newline at end of file diff --git a/Documentation/frequently-asked-questions.md b/Documentation/frequently-asked-questions.md new file mode 100644 index 00000000..c39706bb --- /dev/null +++ b/Documentation/frequently-asked-questions.md @@ -0,0 +1,121 @@ +## Frequently asked questions + +### Q: I am using AEP Edge and Adobe Solutions extensions, which Identity Extension should I install and register? + +A: Both + +When using both Adobe Experience Platform Edge and Adobe Solutions extensions, both Identity for Edge Network and Identity for Experience Cloud ID Service extensions can be registered with the Mobile SDK at the same time. + +**Note** +The following instructions are for configuring an application using both Edge Network and Adobe Solutions mobile extensions. If an application will include only Adobe Experience Platform Edge extensions, follow the instructions here. + +Download and import the Identity and Identity for Edge Network extensions +#### 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:2.+' + implementation 'com.adobe.marketing.mobile:identity:2.+' + implementation 'com.adobe.marketing.mobile:edge:2.+' + implementation 'com.adobe.marketing.mobile:edgeidentity:2.+' + ``` +> **Warning** +> Using dynamic dependency versions is not recommended for production apps. Refer to this [page](https://github.com/adobe/aepsdk-core-android/blob/main/Documentation/MobileCore/gradle-dependencies.md) for managing gradle dependencies. + +2. Import the Mobile Core and Edge extensions in your application class. + + ```java + import com.adobe.marketing.mobile.*; + ``` + +Register the Identity and Identity for Edge Network extensions with Mobile Core + +### Q: Will an existing Experience Cloud ID (ECID) migrate to the Identity for Edge Network extension? + +A: Yes. + +If the application previously installed the Identity for Experience Cloud ID Service extension and upgrades to the Identity for Edge Network extension, the existing ECID value is migrated to the Identity for Edge Network extension on first launch of the application. + +Note, however, if the Mobile SDK's privacy status was set to `optedOut` at the time the application is upgraded, the Identity for Experience Cloud ID Service extension will not have an ECID, as it was cleared. In this case, the Identity for Edge Network extension will generate a new ECID. + +### Q: What is the Experience Cloud ID (ECID) used by the SDK when using both AEP Edge extensions and Adobe Solutions extensions? + +A: The Identity for Edge Network extension and the Identity for Experience Cloud ID Service extension each manage their own ECID. However, the two ECIDs are synced as part of the XDM IdentityMap. + +At first launch of the application after upgrading to the Identity for Edge Network extension, the existing ECID from the Identity for Experience Cloud ID Service extension is migrated to the Identity for Edge Network extension. In this case both extensions will have the same ECID value. + +The [resetIdentities](https://github.com/adobe/aepsdk-core-android/blob/main/Documentation/MobileCore/api-reference.md) API regenerates a new ECID used by the Identity for Edge Network extension. This API call does not change the ECID used by the Identity for Experience Cloud ID Service extension. After calling this API, the ECID used by each identity extension will be different. + +Changing the privacy status to optedOut will clear the ECID value used by the Identity for Experience Cloud ID Service extension. Changing the privacy status back to optedIn will generate a new ECID used by the Identity for Experience Cloud ID Service extension. Privacy status changes do not change the ECID used by the Identity for Edge Network extension. Changing the privacy status will cause the ECID used by each identity extension to be different. + +When each identity extension has a different ECID, the Identity for Edge Network extension will include the Identity for Experience Cloud ID Service ECID in its [IdentityMap](api-reference.md), and so the Adobe Experience Platform Identity Service will link the the two ECIDs in the customer's Identity Graph. + +The following example shows an IdentityMap containing the ECIDs from both Identity for Edge Network extension and Identity for Experience Cloud ID Service extension. The ECID from the Identity for Edge Network extension is always listed first in the list of ECIDs. + +```json + "identityMap" : { + "ECID" : [ + { + "id" : "73586628797489658169123381027155647197", + "authenticatedState" : "ambiguous", + "primary" : false + }, + { + "id" : "81117527655405132265917409409236407340", + "authenticatedState" : "ambiguous", + "primary" : false + } + ] + } +``` +### Q: I set privacy status to opted out, why do I see an ECID value when calling Identity.getExperienceCloudId()? + +A: The Identity for Edge Network extension does not change its ECID based on privacy status changes. + +**Note** +The Identity for Edge Network extension and the Identity for Experience Cloud ID Service extension each manage their own ECID value and are generated independently of each other. + +The Identity for Edge Network extension does not clear its stored identities or regenerate the ECID due to privacy status changes. Instead, use the [MobileCore.resetIdentities](https://github.com/adobe/aepsdk-core-android/blob/main/Documentation/MobileCore/api-reference.md) API. Note this API does not clear the ECID but instead generates a new ECID. + +Each identity extension has its own API to retrieve their respective ECIDs as well. Use [Identity.getExperienceCloudId](api-reference.md) to get the Identity for Edge Network extension's ECID, and [Identity.getExperienceCloudId](https://github.com/adobe/aepsdk-core-android/blob/main/Documentation/Identity/api-reference.md) to get the Identity for Experience Cloud ID Service extension's ECID. + +### Q: How can I get all the identifiers used by the SDK when using both AEP Edge extensions and Adobe Solutions extensions? + +A: Use both `getSdkIdentities` and `getIdentities`. +To get the identifiers used by the Adobe Solutions extensions, call [getSdkIdentities](https://github.com/adobe/aepsdk-core-android/blob/main/Documentation/MobileCore/api-reference.md). +To get the identifiers used by the AEP Edge extensions, call [getIdentities](api-reference.md). + +### Q: How can I clear all the identifiers from the SDK when using both AEP Edge extensions and Adobe Solutions extensions? + +A: Set privacy status to `optedOut` and call `resetIdentities`. + +To clear the identifiers used by the Adobe Solutions extensions, call [setPrivacyStatus](https://github.com/adobe/aepsdk-core-android/blob/main/Documentation/MobileCore/api-reference.md) and set the privacy status to optedOut. + +To clear the identifiers used by the AEP Edge extensions, call [resetIdentities](https://github.com/adobe/aepsdk-core-android/blob/main/Documentation/MobileCore/api-reference.md) + +### Q: What steps are needed to generate a new Experience Cloud ID (ECID) for a user when using both AEP Edge extensions and Adobe Solutions extensions? + +A: Both identity extensions' ECID must be regenerated in sequence to avoid linking the old and new ECIDs in Adobe Experience Platform. + +When using Real-time Customer Profile and Identity Service, the ECIDs from both identity extensions are linked together in the customer's Identity Graph. Care must be taken when regenerating new ECIDs such that the old and new ECIDs are not linked within the same Identity Graph. + +Perform the following API calls to regenerate the ECIDs in sequence: +1. Set [privacy status](https://github.com/adobe/aepsdk-core-android/blob/main/Documentation/MobileCore/api-reference.md) to `optedOut` to clear the ECID from the AEP Identity direct service extension. +2. Call [resetIdentities](https://github.com/adobe/aepsdk-core-android/blob/main/Documentation/MobileCore/api-reference.md) to regenerate a new ECID in the Identity for Edge Network extension. +3. Call [getExperienceCloudId](api-reference.md) on the Identity for Edge Network extension. This ensures the new ECID is generated before continuing. +4. Set privacy status `to optedIn` to generate a new ECID in the AEP Identity direct service extension. + +After completing the above steps, each identity extension will have its own, different, ECID. The new ECIDs will get linked under a new Identity Graph for the customer. + +```java +MobileCore.setPrivacyStatus(MobilePrivacyStatus.OPT_OUT); +MobileCore.resetIdentities(); +com.adobe.marketing.mobile.edge.identity.Identity.getExperienceCloudId(new AdobeCallback() { + @Override + public void call(String s) { + // ignore + } +}); +MobileCore.setPrivacyStatus(MobilePrivacyStatus.OPT_IN); +``` \ No newline at end of file diff --git a/Documentation/getting-started-test-app.md b/Documentation/getting-started-test-app.md index 3dde45fb..befe36de 100644 --- a/Documentation/getting-started-test-app.md +++ b/Documentation/getting-started-test-app.md @@ -1,6 +1,82 @@ # Getting started with the test app -## Testing tips for Android advertising identifier +## Data Collection mobile property prerequisites + +The test app needs to be configured with the following edge extensions before it can be used: +- [Mobile Core](https://github.com/adobe/aepsdk-core-android) (installed by default) +- [Edge Network](https://github.com/adobe/aepsdk-edge-android) +- [Edge Identity](https://github.com/adobe/aepsdk-edgeidentity-android) +- [Edge Consent](https://github.com/adobe/aepsdk-edgeconsent-android) (recommended when using the setAdvertisingIdentifier API) + +1. In the test app, set your `ENVIRONMENT_FILE_ID` in `EdgeIdentityApplication.kt`. Refer to [getting started](getting-started.md) for how to get the ENVIRONMENT_FILE_ID. +2. Select the `app` runnable with the desired emulator and run the program. + +## Validation with Assurance + +Configure a new Assurance session by setting the Base URL to `testapp://main` and launch Assurance in the demo app by running the following command in your terminal: + +```bash +$ adb shell am start -W -a android.intent.action.VIEW -d "testapp://main?adb_validation_sessionid=ADD_YOUR_SESSION_ID_HERE" com.adobe.marketing.edge.identity.app +``` + +Note: replace `ADD_YOUR_SESSION_ID_HERE` with your Assurance session identifier. + +Once the connection is established and the events list starts getting populated, you can filter the events for this extension by typing `Edge Identity` in the `Search Events` search box. + +## Testing with advertising identifier + +To enable advertising identifier features in the test app, follow these steps: +1. Update the value for key `gms_ads_app_id` located in the `secrets.xml` at [aepsdk-edgeidentity-android/code/app/src/main/res/values](../code/app/src/main/res/values/secrets.xml) with a valid Google AdMob app ID. + - See Google's [quick start reference](https://developers.google.com/admob/android/quick-start) on how to get your AdMob app ID. See step 3 of the [Configure your app](https://developers.google.com/admob/android/quick-start#import_the_mobile_ads_sdk) section for a free public test app ID from Google. + - Any real key values in the `secrets.xml` file should **not** be committed to the repository. +2. By default, the ad ID features are commented out in the sample app. To enable these features, uncomment the implemention code using [find and replace all](https://www.jetbrains.com/help/idea/finding-and-replacing-text-in-project.html#replace_search_string_in_project) to replace all instances of: +```java +/* Ad ID implementation +``` +with: +```java +//* Ad ID implementation +``` +Each code block has a pair of block comments wrapped around it to enable this behavior: +```java +/* Ad ID implementation (pt. 1/4) + +/* Ad ID implementation (pt. 1/4) */ +``` + +After replacement it will become: +```java +//* Ad ID implementation (pt. 1/4) + +//* Ad ID implementation (pt. 1/4) */ +``` + +For convenience, these are the default find and replace shortcuts in Android Studio: +[Default shortcuts for find and replace](./assets/find-and-replace-shortcuts.png) + +The shortcut should open a window that looks like the following: +[Example of find and replace](./assets/find-and-replace-all-example.png) +There should be 5 pairs of special comment blocks (10 total matches) across two files: +`app/build.gradle`, `CustomIdentityFragment.kt`, and `SharedViewModel.kt` + +3. With the implementation code and gradle files uncommented with new dependencies, sync the project with the Gradle file changes using: File -> Sync Project with Gradle Files + +[Example of find and replace](./assets/sync-project-gradle-example.png) + +The app should now be properly configured to use advertising identifier features. + +To **disable** these features, follow these steps: +1. [Find and replace](https://www.jetbrains.com/help/idea/finding-and-replacing-text-in-project.html#replace_search_string_in_project) all instances of: +```java +//* Ad ID implementation +``` +with: +```java +/* Ad ID implementation +``` +2. Sync Project with Gradle files using: File -> Sync Project with Gradle Files + +### Testing tips for Android advertising identifier See Google's [Advertising ID help article](https://support.google.com/googleplay/android-developer/answer/6048248?hl=en) for the latest requirements to access ad ID through `AdvertisingIdClient` APIs. Developers using ad ID should get the value from the API each time it is used, as permissions for ad tracking and/or the value of the ID itself may be changed at any time. @@ -31,14 +107,15 @@ In other Android environments, the ad ID tracking authorization is controlled us [New ad ID settings page - opt-in state](./assets/new_adid_setting_optin.png) [New ad ID settings page - opt-out state](./assets/new_adid_setting_optout.png) -## Android Ads SDKs -## Google Mobile Ads Lite SDK +#### Android Ads SDKs + +##### Google Mobile Ads Lite SDK The [Google Mobile Ads Lite SDK](https://developers.google.com/admob/android/lite-sdk) is a way to use ads APIs without including the full size [Google Mobile Ads SDK](https://developers.google.com/admob/android/quick-start). See API reference for [`AdvertisingIdClient`](https://developers.google.com/android/reference/com/google/android/gms/ads/identifier/AdvertisingIdClient) and [`AdvertisingIdClient.Info`](https://developers.google.com/android/reference/com/google/android/gms/ads/identifier/AdvertisingIdClient.Info); the latter provides the APIs for getting the ad ID value and tracking authorization status. The Google AdMob SDK requires an application ID specified in the `AndroidManifest.xml` when the SDK is included in the build, otherwise the app will crash. However, for just ad ID testing purposes, the SDK doesn't have to be initialized. See Google's [quick start guide](https://developers.google.com/admob/android/quick-start#import_the_mobile_ads_sdk) for a detailed implementation guide (and a free sample app ID provided by Google for testing purposes in step 3). -#### Implementation example +##### Implementation example Using a getter to return the ad ID value. Key points to note: - Use of a background coroutine scope from the call site. - Checking the ad tracking authorization status to return the appropriate ad ID value. @@ -95,7 +172,7 @@ Required normal permissions to use ad ID (Android 13 and above): ``` For more specifics on the use of this permission in the context of Android version requirements and permission merging through SDKs, see the [AdvertisingIdClient.Info documentation](https://developers.google.com/android/reference/com/google/android/gms/ads/identifier/AdvertisingIdClient.Info). -## AndroidX Ads SDK +##### AndroidX Ads SDK Overview: https://developer.android.com/jetpack/androidx/releases/ads See the overview for official releases; the latest version is still in alpha and may not be fully supported. `AdvertisingIdClient` API reference: https://developer.android.com/reference/androidx/ads/identifier/AdvertisingIdClient diff --git a/Documentation/getting-started.md b/Documentation/getting-started.md index c3aace0f..95c1d4ae 100644 --- a/Documentation/getting-started.md +++ b/Documentation/getting-started.md @@ -1,60 +1,90 @@ -## Getting started +## Adobe Experience Platform Edge Identity Mobile Extension -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) +The Adobe Experience Platform Identity for Edge Network mobile extension enables identity management from your mobile app when using the Adobe Experience Platform Mobile SDK and the Edge Network extension. -## Add the AEP Identity extension to your app +## Configure the Identity extension in Data Collection UI +1. Log into [Adobe Experience Platform Data Collection](https://experience.adobe.com/data-collection). +2. From **Tags**, locate or search for your Tag mobile property. +3. In your mobile property, select **Extensions** tab. +4. On the **Catalog** tab, locate or search for the **Identity** extension, and select **Install**. +5. There are no configuration settings for **Identity**. +6. Follow the publishing process to update SDK configuration. -### Download and import the Identity extension +## Add the Identity extension to your app -> :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. +The Adobe Experience Platform Identity for Edge Network extension depends on the following extensions: +- [Mobile Core](https://github.com/adobe/aepsdk-core-android) +- [Edge Network](https://github.com/adobe/aepsdk-edge-android) (required for handling requests to Adobe Edge Network) -### Java +### Download and import the Identity extension -1. Add the Mobile Core and Edge extensions to your project using the app's Gradle file. +> **Note** 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](frequently-asked-questions.md) page. - ```java - implementation 'com.adobe.marketing.mobile:core:1.+' - implementation 'com.adobe.marketing.mobile:edge:1.+' - implementation 'com.adobe.marketing.mobile:edgeidentity:1.+' +1. Add the Mobile Core, Edge, and Edge Identity extensions to your project using the app's Gradle file: + +```gradle +implementation 'com.adobe.marketing.mobile:core:2.+' +implementation 'com.adobe.marketing.mobile:edge:2.+' +implementation 'com.adobe.marketing.mobile:edgeidentity:2.+' ``` +> **Warning** +> Using dynamic dependency versions is not recommended for production apps. Refer to this [page](https://github.com/adobe/aepsdk-core-android/blob/main/Documentation/MobileCore/gradle-dependencies.md) for managing gradle dependencies. -2. Import the Mobile Core and Edge extensions in your Application class. +2. Import the libraries: +#### Java +```java +import com.adobe.marketing.mobile.MobileCore; +import com.adobe.marketing.mobile.Edge; +import com.adobe.marketing.mobile.edge.identity.Identity; +``` +#### Kotlin +```kotlin +import com.adobe.marketing.mobile.MobileCore +import com.adobe.marketing.mobile.Edge +import com.adobe.marketing.mobile.edge.identity.Identity +``` - ```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: +### Register the Identity for Edge Extension with MobileCore -### Java +#### Java ```java public class MobileApp extends Application { + // Set up the preferred Environment File ID from your mobile property configured in Data Collection UI + private final String ENVIRONMENT_FILE_ID = ""; @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) { - ... - } - + MobileCore.configureWithAppID(ENVIRONMENT_FILE_ID); + // Register Adobe Experience Platform SDK extensions + MobileCore.registerExtensions( + Arrays.asList(Edge.EXTENSION, Identity.EXTENSION), + o -> Log.debug("MobileApp", "MobileApp", "Adobe Experience Platform Mobile SDK initialized.") + ); } } ``` +#### Kotlin + +```kotlin +class MobileApp : Application() { + // Set up the preferred Environment File ID from your mobile property configured in Data Collection UI + private var ENVIRONMENT_FILE_ID: String = "" + override fun onCreate() { + super.onCreate() + MobileCore.setApplication(this) + MobileCore.configureWithAppID(ENVIRONMENT_FILE_ID) + // Register Adobe Experience Platform SDK extensions + MobileCore.registerExtensions( + listOf(Edge.EXTENSION, Identity.EXTENSION) + ) { + Log.debug("MobileApp", "MobileApp", "Adobe Experience Platform Mobile SDK initialized.") + } + } +} +``` \ No newline at end of file diff --git a/Documentation/troubleshooting-guide.md b/Documentation/troubleshooting-guide.md new file mode 100644 index 00000000..d928adf9 --- /dev/null +++ b/Documentation/troubleshooting-guide.md @@ -0,0 +1,29 @@ +## Troubleshooting Guide + +### Development on M1 Macs + +M1 Macs may run into errors during the build process, specifically finding the npm installation directory. + +``` +Execution failed for task ':spotlessInternalRegisterDependencies'. + +Can't automatically determine npm executable and none was specifically supplied! + +Spotless tries to find your npm executable automatically. It looks for npm in the following places: +- An executable referenced by the java system property 'npm.exec' - if such a system property exists. +- The environment variable 'NVM_BIN' - if such an environment variable exists. +- The environment variable 'NVM_SYMLINK' - if such an environment variable exists. +- The environment variable 'NODE_PATH' - if such an environment variable exists. +- In your 'PATH' environment variable + +If autodiscovery fails for your system, try to set one of the environment variables correctly or +try setting the system property 'npm.exec' in the build process to override autodiscovery. +``` + +To address this: +- Update Android Studio to the latest version (minimum version Bumblebee Patch 1 should address this issue) +- Update the Android Gradle Plugin to the latest version (7.x.x as of this writing) + +If that does not address the issue, try installing node using the installer and not through homebrew: https://nodejs.org/en/download/ + +Please make sure that these build configuration changes are kept local; any build process dependencies (ex: Gradle version, packages) that are updated in this process should **not** be included in any PRs that are not specifically for updating the project's build configuration. \ No newline at end of file diff --git a/LICENSE b/LICENSE index 161d7ff9..c911c8d8 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,7 @@ file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. -Copyright 2021 Adobe +Copyright 2023 Adobe Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/README.md b/README.md index 2f5f7753..2d00cd29 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,14 @@ # Adobe Experience Platform Edge Identity Mobile Extension - +[![Maven Central](https://img.shields.io/maven-central/v/com.adobe.marketing.mobile/edgeidentity.svg?logo=android&logoColor=white&label=edgeidentity)](https://mvnrepository.com/artifact/com.adobe.marketing.mobile/edgeidentity) ## About this project -The Adobe Experience Platform Edge Identity is a mobile extension for the [Adobe Experience Platform SDK](https://github.com/Adobe-Marketing-Cloud/acp-sdks) and requires the `MobileCore` extension. This extension enables handling of user identity data from a mobile app when using the AEP Mobile SDK and the Edge Network extension. +The Adobe Experience Platform Identity for Edge Network mobile extension enables identity management from your mobile app when using the [Adobe Experience Platform Mobile SDK](https://developer.adobe.com/client-sdks/documentation) and the Edge Network extension. ### Installation -Integrate the Edge Identity extension into your app by including the following in your gradle file's `dependencies`: - -```gradle -implementation 'com.adobe.marketing.mobile:edgeidentity:1.+' -implementation 'com.adobe.marketing.mobile:edge:1.+' -implementation 'com.adobe.marketing.mobile:core:1.+' -implementation 'com.adobe.marketing.mobile:edgeconsent:1.+' // Recommended when using the setAdvertisingIdentifier API -``` +Integrate the Identity for Edge Network mobile extension into your app by following the [getting started guide](Documentation/getting-started.md). ### Development @@ -23,62 +16,15 @@ implementation 'com.adobe.marketing.mobile:edgeconsent:1.+' // Recommended when To open and run the project, open the `code/settings.gradle` file in Android Studio. -**Data Collection mobile property prerequisites** - -The test app needs to be configured with the following edge extensions before it can be used: -- Mobile Core (installed by default) -- [Edge](https://aep-sdks.gitbook.io/docs/foundation-extensions/experience-platform-extension) -- [Edge Identity](https://aep-sdks.gitbook.io/docs/foundation-extensions/identity-for-edge-network) -- [Edge Consent](https://aep-sdks.gitbook.io/docs/foundation-extensions/consent-for-edge-network) (recommended when using the setAdvertisingIdentifier API) - -**Run demo application** - -1. In the test app, set your `ENVIRONMENT_FILE_ID` in `EdgeIdentityApplication.kt`. -2. Select the `app` runnable with the desired emulator and run the program. - -> **Note** -> To enable GAID related advertising identifier features, follow the [documentation](Documentation/README.md#advertising-identifier) for the required setup steps. - -**View the platform events with Assurance** - -Configure a new Assurance session by setting the Base URL to `testapp://main` and launch Assurance in the demo app by running the following command in your terminal: - -```bash -$ adb shell am start -W -a android.intent.action.VIEW -d "testapp://main?adb_validation_sessionid=ADD_YOUR_SESSION_ID_HERE" com.adobe.marketing.mobile.testapp -``` - -Note: replace ADD_YOUR_SESSION_ID_HERE with your Assurance session identifier. - -Once the connection is established and the events list starts getting populated, you can filter the events for this extension by typing `Edge Identity` in the `Search Events` search box. - -**Development on M1 Macs** -M1 Macs may run into errors during the build process, specifically finding the npm installation directory. - -``` -Execution failed for task ':spotlessInternalRegisterDependencies'. - -Can't automatically determine npm executable and none was specifically supplied! - -Spotless tries to find your npm executable automatically. It looks for npm in the following places: -- An executable referenced by the java system property 'npm.exec' - if such a system property exists. -- The environment variable 'NVM_BIN' - if such an environment variable exists. -- The environment variable 'NVM_SYMLINK' - if such an environment variable exists. -- The environment variable 'NODE_PATH' - if such an environment variable exists. -- In your 'PATH' environment variable - -If autodiscovery fails for your system, try to set one of the environment variables correctly or -try setting the system property 'npm.exec' in the build process to override autodiscovery. -``` +**Run the test app** -To address this: -- Update Android Studio to the latest version (minimum version Bumblebee Patch 1 should address this issue) -- Update the Android Gradle Plugin to the latest version (7.x.x as of this writing) +To configure and run the test app for this project, follow the [getting started guide for the test app](Documentation/getting-started-test-app.md). -If that does not address the issue, try installing node using the installer and not through homebrew: https://nodejs.org/en/download/ +**Development on M1 Macs** -Please make sure that these build configuration changes are kept local; any build process dependencies (ex: Gradle version, packages) that are updated in this process should **not** be included in any PRs that are not specifically for updating the project's build configuration. +If you are seeing any build failures when running the project for the first time on your M1 machine, check out the [troubleshooting guides](Documentation/troubleshooting-guide.md). -### Code Format +#### Code Format This project uses the code formatting tools [Spotless](https://github.com/diffplug/spotless/tree/main/plugin-gradle) with [Prettier](https://prettier.io/) and [ktlint](https://github.com/pinterest/ktlint). Formatting is applied when the project is built from Gradle and is checked when changes are submitted to the CI build system. @@ -93,7 +39,11 @@ make init | Project | Description | | ------------------------------------------------------------ | ------------------------------------------------------------ | -| [AEP SDK Sample App for Android](https://github.com/adobe/aepsdk-sample-app-android) | Contains Android sample app for the AEP SDK. | +| [Core extensions](https://github.com/adobe/aepsdk-core-android) | The Mobile Core represents the foundation of the Adobe Experience Platform mobile SDK. | +| [Edge Network extension](https://github.com/adobe/aepsdk-edge-android) | The Edge Network extension allows you to send data to the Adobe Edge Network from a mobile application. | +| [Consent for Edge Network extension](https://github.com/adobe/aepsdk-edgeconsent-android) | The Consent extension enables consent preferences collection from your mobile app when using the AEP SDK and the Edge Network extension. | +| [Assurance extension](https://github.com/adobe/aepsdk-assurance-android) | The Assurance extension enables validation workflows for your SDK implementation. | +| [Adobe Experience Platform sample app for Android](https://github.com/adobe/aepsdk-sample-app-android) | Contains a fully implemented Android sample app using the Experience Platform SDKs. | ## Documentation diff --git a/code/app/build.gradle b/code/app/build.gradle index c3abf6ab..bc005aa9 100644 --- a/code/app/build.gradle +++ b/code/app/build.gradle @@ -1,7 +1,8 @@ -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' -apply plugin: 'kotlin-android-extensions' -apply plugin: "com.diffplug.spotless" +plugins { + id 'com.android.application' + id 'com.diffplug.spotless' + id 'org.jetbrains.kotlin.android' +} spotless { kotlin { @@ -12,14 +13,16 @@ spotless { } android { - compileSdkVersion 31 + namespace 'com.adobe.marketing.edge.identity.app' + + compileSdk rootProject.ext.compileSdkVersion defaultConfig { applicationId "com.adobe.marketing.edge.identity.app" - minSdkVersion 19 - targetSdkVersion 31 - versionCode 1 - versionName "1.0" + minSdk rootProject.ext.minSdkVersion + targetSdk rootProject.ext.targetSdkVersion + versionCode rootProject.ext.versionCode + versionName project.property('moduleVersion') as String ?: "1.0.0 (Default)" multiDexEnabled = true testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" @@ -35,14 +38,18 @@ android { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } + kotlinOptions { - jvmTarget = '1.8' + jvmTarget = rootProject.ext.kotlinJvmTarget } } +configurations.all { + resolutionStrategy.cacheChangingModulesFor 0, 'seconds' +} + dependencies { - implementation fileTree(dir: "libs", include: ["*.jar"]) - implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + implementation "org.jetbrains.kotlin:kotlin-stdlib:${rootProject.ext.kotlinVersion}" implementation 'androidx.core:core-ktx:1.3.2' implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'androidx.legacy:legacy-support-v4:1.0.0' @@ -55,13 +62,14 @@ 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' + + implementation "com.adobe.marketing.mobile:core:2.+" + implementation 'com.adobe.marketing.mobile:identity:2.+' + implementation 'com.adobe.marketing.mobile:edgeconsent:2.+' + implementation 'com.adobe.marketing.mobile:assurance:2.+' + implementation ('com.adobe.marketing.mobile:edge:2.+') { + 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/app/src/main/AndroidManifest.xml b/code/app/src/main/AndroidManifest.xml index 18386222..3a7d481a 100644 --- a/code/app/src/main/AndroidManifest.xml +++ b/code/app/src/main/AndroidManifest.xml @@ -1,7 +1,6 @@ - + - + + + + + + ` + + + + + (R.id.btn_remove_identities).setOnClickListener { @@ -106,8 +108,10 @@ class CustomIdentityFragment : Fragment() { val authenticatedState: AuthenticatedState? = sharedViewModel.authenticatedState.value val isPrimary: Boolean = sharedViewModel.isPrimary.value ?: false - val item = IdentityItem(identifier, authenticatedState, isPrimary) - Identity.removeIdentity(item, namespace) + if (identifier != null && namespace != null) { + val item = IdentityItem(identifier, authenticatedState, isPrimary) + Identity.removeIdentity(item, namespace) + } } // Advertising identifier features @@ -121,7 +125,7 @@ class CustomIdentityFragment : Fragment() { // Default hint for how to enable ad ID features; overwritten by actual implementation when ad ID features are enabled. root.findViewById