Skip to content

Commit

Permalink
Merge pull request #57 from adobe/staging
Browse files Browse the repository at this point in the history
Merge staging to main for 2.1.0 release
  • Loading branch information
prudrabhat committed Apr 24, 2023
2 parents b6127ea + b8102ce commit c5a3e05
Show file tree
Hide file tree
Showing 46 changed files with 3,421 additions and 267 deletions.
4 changes: 2 additions & 2 deletions code/assurance-testapp/src/main/AndroidManifest.xml
Expand Up @@ -25,12 +25,12 @@
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
android:theme="@style/AppThemeLight">
<activity
android:name=".AssuranceTestAppActivity"
android:exported="true"
android:label="@string/title_activity_assurance_test_app"
android:theme="@style/AppTheme">
android:theme="@style/AppThemeLight">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
Expand Down
Expand Up @@ -119,6 +119,13 @@ private fun AssuranceConnectionInput() {
) {
Text(text = stringResource(id = R.string.assurance_connection_button_name))
}

Button(
onClick = { Assurance.startSession() },
modifier = Modifier.fillMaxWidth()
) {
Text(text = stringResource(id = R.string.assurance_quick_connect_button_name))
}
}
}

Expand Down
1 change: 1 addition & 0 deletions code/assurance-testapp/src/main/res/values/strings.xml
Expand Up @@ -18,6 +18,7 @@
<string name="assurance_version">Assurance v%1$s</string>
<string name="assurance_connection_input_hint">Enter Assurance Connection URL</string>
<string name="assurance_connection_button_name">Start Session</string>
<string name="assurance_quick_connect_button_name">Quick Connect</string>

<string name="event_chunking_section_title">Event Chunking</string>
<string name="send_small_payload_button_name">Send Small Payload</string>
Expand Down
28 changes: 0 additions & 28 deletions code/assurance-testapp/src/main/res/values/styles.xml

This file was deleted.

18 changes: 16 additions & 2 deletions code/assurance/build.gradle
Expand Up @@ -15,6 +15,7 @@ plugins {
id 'maven-publish'
id 'signing'
id 'com.diffplug.spotless'
id 'kotlin-android'
}

// Apply local gradle tasks
Expand Down Expand Up @@ -45,6 +46,10 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion

// provides a major advantage by preventing the generation
// of individual png icons for each screen size in favor of a single vector
vectorDrawables.useSupportLibrary = true

buildConfigField("String","EXTENSION_VERSION","\"${rootProject.moduleVersion}\"")
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'

Expand Down Expand Up @@ -79,6 +84,11 @@ android {
targetCompatibility rootProject.ext.targetCompatibility
}

kotlinOptions {
jvmTarget = rootProject.ext.kotlinJvmTarget
languageVersion = rootProject.ext.kotlinLanguageVersion
apiVersion = rootProject.ext.kotlinApiVersion
}
}


Expand Down Expand Up @@ -142,7 +152,9 @@ publishing {
url = 'https://developer.adobe.com/client-sdks'
licenses {
license {
name = 'Apache License, Version 2.0'
name = 'The Apache License, Version 2.0'
url = 'https://www.apache.org/licenses/LICENSE-2.0.txt'
distribution = 'repo'
}
}
developers {
Expand Down Expand Up @@ -235,11 +247,13 @@ task platformFunctionalTestJacocoReport(type: JacocoReport, dependsOn: "createPh
dependencies {
implementation 'androidx.appcompat:appcompat:1.0.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinApiVersion"
implementation "com.adobe.marketing.mobile:core:${rootProject.mavenCoreVersion}"

testImplementation 'junit:junit:4.13'
testImplementation 'com.google.code.gson:gson:2.8.5'
testImplementation "org.mockito:mockito-core:4.5.1"
testImplementation 'org.mockito:mockito-core:4.5.1'
testImplementation 'org.mockito.kotlin:mockito-kotlin:3.2.0'
testImplementation 'org.mockito:mockito-inline:4.5.1'
testImplementation 'net.sf.kxml:kxml2:2.3.0@jar'
testImplementation 'org.json:json:20171018'
Expand Down
1 change: 1 addition & 0 deletions code/assurance/src/main/AndroidManifest.xml
Expand Up @@ -14,5 +14,6 @@
<application>
<activity android:name=".AssuranceFullScreenTakeoverActivity" android:exported="false"/>
<activity android:name=".AssuranceErrorDisplayActivity" android:exported="false"/>
<activity android:name=".AssuranceQuickConnectActivity" android:exported="false"/>
</application>
</manifest>
Expand Up @@ -15,6 +15,7 @@
import androidx.annotation.NonNull;
import com.adobe.marketing.mobile.assurance.AssuranceExtension;
import com.adobe.marketing.mobile.services.Log;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
Expand All @@ -23,12 +24,13 @@ public class Assurance {

public static final Class<? extends Extension> EXTENSION = AssuranceExtension.class;
public static final String LOG_TAG = "Assurance";
public static final String EXTENSION_VERSION = "2.0.1";
public static final String EXTENSION_VERSION = "2.1.0";
public static final String EXTENSION_NAME = "com.adobe.assurance";
public static final String EXTENSION_FRIENDLY_NAME = "Assurance";

private static final String DEEPLINK_SESSION_ID_KEY = "adb_validation_sessionid";
private static final String START_SESSION_URL = "startSessionURL";
private static final String IS_QUICK_CONNECT = "quickConnect";

// ========================================================================================
// Public APIs
Expand Down Expand Up @@ -102,4 +104,23 @@ public static void startSession(@NonNull final String url) {
.build();
MobileCore.dispatchEvent(startSessionEvent);
}

/**
* Starts an Assurance session via quick flow. Invoking this method on a non-debuggable build,
* or when a session already exists will result in a no-op.
*/
public static void startSession() {
Log.debug(LOG_TAG, LOG_TAG, "QuickConnect api triggered.");

// Send a quick connect start session event irrespective of the build here.
// Validation will be done when the extension handles this event.
final Event startSessionEvent =
new Event.Builder(
"Assurance Start Session (Quick Connect)",
EventType.ASSURANCE,
EventSource.REQUEST_CONTENT)
.setEventData(Collections.singletonMap(IS_QUICK_CONNECT, true))
.build();
MobileCore.dispatchEvent(startSessionEvent);
}
}
@@ -0,0 +1,46 @@
/*
* Copyright 2023 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.assurance

import com.adobe.marketing.mobile.Assurance
import com.adobe.marketing.mobile.assurance.AssuranceSessionOrchestrator.SessionUIOperationHandler
import com.adobe.marketing.mobile.services.Log

/**
* Provides components necessary for native presentations to interact with the session.
* This should be initialized when the AssuranceExtension is created to ensure that the
* components are available.
*/
internal object AssuranceComponentRegistry {
private const val LOG_SOURCE = "AssuranceComponentRegistry"

internal var assuranceStateManager: AssuranceStateManager? = null
private set

internal var sessionUIOperationHandler: SessionUIOperationHandler? = null
private set

@JvmName("initialize")
@Synchronized
internal fun initialize(
assuranceStateManager: AssuranceStateManager,
uiOperationHandler: SessionUIOperationHandler
) {
if (this.assuranceStateManager != null || this.sessionUIOperationHandler != null) {
Log.warning(Assurance.LOG_TAG, LOG_SOURCE, "Components already initialized.")
return
}

this.assuranceStateManager = assuranceStateManager
this.sessionUIOperationHandler = uiOperationHandler
}
}
Expand Up @@ -12,8 +12,10 @@
package com.adobe.marketing.mobile.assurance;


import androidx.annotation.Nullable;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

final class AssuranceConstants {
static final String VENDOR_ASSURANCE_MOBILE = "com.adobe.griffon.mobile";
Expand All @@ -39,6 +41,7 @@ private GenericEventPayloadKey() {}

static final class SDKEventDataKey {
static final String START_SESSION_URL = "startSessionURL";
static final String IS_QUICK_CONNECT = "quickConnect";
static final String EXTENSIONS = "extensions";
static final String STATE_OWNER = "stateowner";
static final String FRIENDLY_NAME = "friendlyName";
Expand Down Expand Up @@ -222,6 +225,35 @@ static final class SocketCloseCode {
static final int SESSION_DELETED = 4903;

private SocketCloseCode() {}

/**
* Converts a socket close code to an {@code AssuranceConnectionError} if such a mapping
* exists. Not all socket close codes are error codes and not all AssuranceConnectionErrors
* are socket errors. So this utility is needed to bridge socket codes and
* AssuranceConnectionError.
*
* @param closeCode a socket close code for which an AssuranceConnectionError is needed
* @return an {@code AssuranceConnectionError}
*/
@Nullable
static AssuranceConnectionError toAssuranceConnectionError(final int closeCode) {
switch (closeCode) {
case ORG_MISMATCH:
return AssuranceConnectionError.ORG_ID_MISMATCH;
case CLIENT_ERROR:
return AssuranceConnectionError.CLIENT_ERROR;
case CONNECTION_LIMIT:
return AssuranceConnectionError.CONNECTION_LIMIT;
case EVENT_LIMIT:
return AssuranceConnectionError.EVENT_LIMIT;
case SESSION_DELETED:
return AssuranceConnectionError.SESSION_DELETED;
case ABNORMAL:
return AssuranceConnectionError.GENERIC_ERROR;
default:
return null;
}
}
}

static final class IntentExtraKey {
Expand All @@ -231,57 +263,95 @@ static final class IntentExtraKey {
private IntentExtraKey() {}
}

static final class QuickConnect {
static final String BASE_DEVICE_API_URL = "https://device.griffon.adobe.com/device";
static final String DEVICE_API_PATH_CREATE = "create";
static final String DEVICE_API_PATH_STATUS = "status";
static final String KEY_SESSION_ID = "sessionUuid";
static final String KEY_SESSION_TOKEN = "token";
static final String KEY_ORG_ID = "orgId";
static final String KEY_DEVICE_NAME = "deviceName";
static final String KEY_CLIENT_ID = "clientId";
static final int CONNECTION_TIMEOUT_MS = (int) TimeUnit.SECONDS.toMillis(5);
static final int READ_TIMEOUT_MS = (int) TimeUnit.SECONDS.toMillis(5);
static final long STATUS_CHECK_DELAY_MS = TimeUnit.SECONDS.toMillis(2);
static final int MAX_RETRY_COUNT = 300;
}

// ========================================================================================
// Enums
// ========================================================================================

enum AssuranceSocketError {
enum AssuranceConnectionError {
GENERIC_ERROR(
"Connection Error",
"The connection may be failing due to a network issue or an incorrect PIN. "
+ "Please verify internet connectivity or the PIN and try again."),
NO_ORGID(
+ "Please verify internet connectivity or the PIN and try again.",
true),
NO_ORG_ID(
"Invalid Configuration",
"The Experience Cloud organization identifier is unavailable from the SDK. Ensure"
+ " SDK configuration is setup correctly. See documentation for more detail."),
ORGID_MISMATCH(
+ " SDK configuration is setup correctly. See documentation for more detail.",
false),
ORG_ID_MISMATCH(
"Unauthorized Access",
"The Experience Cloud organization identifier does not match with that of the"
+ " Assurance session. Ensure the right Experience Cloud organization is being"
+ " used. See documentation for more detail."),
+ " used. See documentation for more detail.",
false),
CONNECTION_LIMIT(
"Connection Limit Reached",
"You have reached the maximum number of connected devices allowed for a session. "
+ "Please disconnect another device and try again."),
+ "Please disconnect another device and try again.",
false),
EVENT_LIMIT(
"Event Limit Reached",
"You have reached the maximum number of events that can be sent per minute."),
"You have reached the maximum number of events that can be sent per minute.",
false),
CLIENT_ERROR(
"Client Disconnected",
"This client has been disconnected due to an unexpected error. Error Code 4400."),
"This client has been disconnected due to an unexpected error. Error Code 4400.",
false),
SESSION_DELETED(
"Session Deleted",
"The session client connected to has been deleted. Error Code 4903.");
"The session client connected to has been deleted. Error Code 4903.",
false),

CREATE_DEVICE_REQUEST_MALFORMED(
"Malformed Request",
"The network request for device creation was malformed.",
false),
STATUS_CHECK_REQUEST_MALFORMED(
"Malformed Request", "The network request for status check was malformed.", false),
RETRY_LIMIT_REACHED(
"Retry Limit Reached",
"The maximum allowed retries for fetching the session details were reached.",
true),
CREATE_DEVICE_REQUEST_FAILED("Request Failed", "Failed to register device.", true),
DEVICE_STATUS_REQUEST_FAILED("Request Failed", "Failed to get device status", true),
UNEXPECTED_ERROR("Unexpected Error", "An unexpected error occurred", true);

private final String error;
private final String errorDescription;
private final String description;
private final boolean isRetryable;

private AssuranceSocketError(final String error, final String description) {
private AssuranceConnectionError(
final String error, final String description, final boolean isRetryable) {
this.error = error;
this.errorDescription = description;
this.description = description;
this.isRetryable = isRetryable;
}

String getErrorDescription() {
return errorDescription;
String getDescription() {
return description;
}

String getError() {
return error;
}

@Override
public String toString() {
return error + ": " + errorDescription;
boolean isRetryable() {
return isRetryable;
}
}

Expand Down

0 comments on commit c5a3e05

Please sign in to comment.