Let's Chat?

Quickstart

NOTE: The following information is for the 6.1 version of the SDK.

The Glance Android SDK will display the mobile application or device screen to a remote agent. Once the session starts showing, the SDK will track view changes, activity changes, and device rotation.

This document describes the more common use case of Visitor sessions. A Visitor session is started by a user of your app that is not an authenticated Glance user, though they may be an authenticated user of your app. The session is joined by a customer support or sales Agent that is an authenticated Glance user.

To integrate with the SDK, an application needs to take the following steps, each outlined in their own section:

  1. Get an agent account and Group ID from Glance
  2. Include the AAR
  3. Optimized Builds
  4. Initialize the Visitor Class
  5. Set an Event handler
  6. Start a Visitor session
  7. Confirm it's working
  8. End the session
  9. (Optional) Media Projection
  10. (Optional) Masking Views
  11. (Optional) One-Click Connect

Get an Agent Account and Group ID from Glance

Before you get started you'll need a Glance account. Contact Glance to set up a Group (organization account) and an individual Agent account. You will receive:

  1. A numeric Group ID
  2. An agent username, for example agnes.acme.glance.net (Glance usernames are in the form of DNS names)
  3. An agent password

In production usage, agents will typically authenticate with a single-sign-on, often via their CRM implementation (e.g. Salesforce).

Include the AAR

You can find the AAR in [our public GitLab repo here] (https://gitlab.com/glance-networks/glancesdkdemos-android/-/tree/master/libs).

To include the AAR in the app, put it in the app/libs folder. Then modify the app/build.gradle file to include the following:

plugins {
    id: 'com.android.application'
}
repositories {
    flatDir {
        dirs 'libs'
    }
}

Ensure multiDexEnabled is set to true within the android > defaultConfig section.

android {
    defaultConfig {
        minSdkVersion 19

        ...

        // Enabling multidex support.
        multiDexEnabled true
    }
    ...
}

Add the following block within the android section (this may already exist):

compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
}

Add the following within the dependencies block of the build.gradle file:

implementation fileTree(dir: 'libs', include: ['glanceSDK.aar'])
implementation 'androidx.multidex:multidex:2.0.1'
implementation "org.java-websocket:Java-WebSocket:1.5.1"

Finally, change this line in settings.gradle:

repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)

to:

repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS)

Then, sync gradle by going to Tools -> Android -> Sync Project with Gradle Files or clicking the icon. Until you do this, Android Studio won’t be able to autocomplete or import the appropriate classes.

NOTE: If you have **android:allowBackup="true"** set on your project's manifest, you'll need to add the following rule on your manifest's application level: **tools:replace="android:allowBackup"**, otherwise you'll get a build error.

Optimized Builds

The Glance AAR includes a binary build for each supported native architecture. The Glance library uses the Android NDK and requires native support for each platform.

The Glance AAR file includes the binaries for each architecture and is larger as a result. To create an optimized and much smaller APK that only includes the library binary for a single architecture you need to take advantage of APK splits.

Follow the APK splits documentation to create optimized APKs.

Initialize the Visitor Class

You must call Visitor.init once to initialize the visitor class for your group, within an initialization function in your code (init, onCreate, etc.). Initialize the framework with your Glance Group ID, which is required. The token, name, email, and phone fields are optional and are used to identify your user. This information will be stored in Glance session records and available on reports and via our APIs.

You can pass empty strings or any other values useful to you. The limits are, name: 62 characters, email: 26 characters, phone: 30 characters.

Visitor.init(activity, 1234, "", "Vera Visitor", "vera@example.com", "444-555-1234", "<VISITOR_ID or empty>")
Visitor.init(activity, 1234, "", "Vera Visitor", "vera@example.com", "444-555-1234", "<VISITOR_ID or empty>");

Events

Before starting a session you should register a VisitorListener listener to monitor session events:

class MyActivity : VisitorListener {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Visitor.init(this, 1234, "", "Vera Visitor", "vera@example.com", "444-555-1234")
        Visitor.addListener(this)
    }

    override fun onDestroy() {
        super.onDestroy()

        Visitor.removeListener(this)
    }

    // this is called on the Glance Event thread
    override fun onGlanceVisitorEvent(event: Event) {
        if (event.code == EventCode.EventConnectedToSession) {
            // Show any UI to indicate the session has started
            // If not using a known session key, you can get the random key here
            // to display to the user to read to the agent
            final String sessionKey = event.GetValue("sessionkey");
        }
        else if (event.code == EventCode.EventSessionEnded) {
            // Show any UI to indicate the session has ended
        }
        else if (event.type == EventType.EventWarning ||
                event.type == EventType.EventError ||
                event.type == EventType.EventAssertFail) {
            // Best practice is to log code and message of all events of these types
        }
    }
}
public class MyActivity implements VisitorListener {

    @Override
    protected void onCreate(@Nullable final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Visitor.init(this, 1234, "", "Vera Visitor", "vera@example.com", "444-555-1234", "");
        Visitor.addListener(this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        Visitor.removeListener(this);
    }

    // this is called on the Glance Event thread
    public void onGlanceVisitorEvent(Event event) {
        if (event.getCode() == EventCode.EventConnectedToSession){
            // Show any UI to indicate the session has started
            // If not using a known session key, you can get the random key here
            // to display to the user to read to the agent
            final String sessionKey = event.GetValue("sessionkey");
        }
        else if (event.getCode() == EventCode.EventSessionEnded ){
            // Show any UI to indicate the session has ended
        }
        else if (event.getType() == EventType.EventWarning ||
                 event.getType() == EventType.EventError ||
                 event.getType() == EventType.EventAssertFail) {
            // Best practice is to log code and message of all events of these types
        }
    }
}

NOTE: You must wait for EventVisitorInitialized before calling startSession.

Start a Visitor Session

There are two main options to consider when starting a session: session key and video mode.

A session can start with or without a specific session key. If you don't want to provide a session key, you'll need to use the "GLANCE_KEYTYPE_RANDOM" string instead, in order to generate a random one and have it returned in the properties of the GlanceEvent with code EventConnectedToSession. If you have a known value you wish to use for a session key, such as a customer id, you can pass it to startSession. The key may only contain characters from the Base64URL set, up to 63 characters maximum.

A session can start with multiple different video modes. The options are as follows:

  • VideoOff: Video for both the agent and user will start OFF
  • VideoSmallVisitor: Small widget, Video for user will start ON, agent video will start OFF
  • VideoSmallMultiway: Small widget, Video for user and agent will start ON
  • VideoLargeVisitor: Large widget, Video for user will start ON, agent video will start OFF
  • VideoLargeMultiway: Large widget, Video for user and agent will start ON

To start a session with parameters, use the StartParams class to set them, and pass that into startSession. You can also change the terms URL by using the setTermsUrl method:

val startParams = StartParams()
startParams.setKey(SESSION_KEY) // required
startParams.setVideo(VIDEO_MODE) // optional - defaults to VideoOff
startParams.setTermsUrl("https://google.com") // optional
Visitor.startSession(startParams)
StartParams startParams = new StartParams();
startParams.setKey(SESSION_KEY); // required
startParams.setVideo(VIDEO_MODE); // optional - defaults to VideoOff
startParams.setTermsUrl("https://google.com"); // optional
Visitor.startSession(startParams);

To start a session with a random key call, you must use the "GLANCE_KEYTYPE_RANDOM" string as a key:

startParams.setKey("GLANCE_KEYTYPE_RANDOM")
startParams.setKey("GLANCE_KEYTYPE_RANDOM");

Confirm it's Working

To confirm the integration is working, start the session and note the session key.

The agent should then go to: https://www.glance.net/agentjoin/AgentJoin.aspx.

If not logged in already, the agent will be asked to login:

When logged-in a form will be shown to enter the session key.

At that point the web viewer will display the screen being shared with the ability to gesture:

When the key is known a view can be opened directly with https://www.glance.net/agentjoin/AgentView.aspx?username={username}&sesionkey={key}&wait=1

End the Session

The session can be ended from either the agent side or the app side. To end from the app, call:

Visitor.endSession()
Visitor.endSession();

In either case the event EventSessionEnded will be sent.

Make sure to also remove the listener before the activity is destroyed (typically done in onDestroy):

Visitor.removeListener(this)
Visitor.removeListener(this);

Media Projection

Media Projection allows the recording of the entire screen, including the home screen and other applications. Full details can be found in the Media Projection Demo (Kotlin).

Permissions to Capture Entire Screen

If Media Projection is enabled, the SDK will request full screen capture permission at runtime on devices running Android Lollipop or later. If the user accepts, the session will utilize the permission to record the full screen. If the user rejects the SDK falls back to the solution that is used by pre-Lollipop Android devices to record the screen.

Masking and Gesturing Outside of the Application

Capturing the full screen on Android allows the SDK to record the home screen and other apps. When the user is outside the context of the app the SDK cannot mask views or display gestures to the user. This means that keyboards and input fields outside of the app integrating the SDK will be fully visible to the agent which may present security issues. Consider your app use case carefully before enabling the full screen feature.

Masking the Keyboard

Keyboard masking allows the SDK to cover the keyboard when its in use. This prevents potentially sensitive user information from being communicated to the agent. This feature only applies when permission to capture the entire screen is enabled and approved by the user. Otherwise keyboard masking is not necessary because the keyboard is not captured as part of the screenshare.

As a result of keyboard masking being specific to full screen mode it should be noted that keyboards displayed outside of the app integrating the SDK (other apps on the device and home screen) will not be masked.

To enable keyboard masking:

Visitor.maskKeyboard(true)
Visitor.maskKeyboard(true);

Masking Views

Specific views can be hidden from the agent by passing it them to the SDK. There are two ways to mask views: by view id or by passing in the view object. Masking by ID is the preferred approach that can work reliably within the Android activity lifecycle where activity instances are rapidly created and destroyed for a variety of reasons.

By View ID

Adding:

Visitor.addMaskedViewId(R.id.password_view)
Visitor.addMaskedViewId(R.id.password_view);

Removing:

Visitor.removeMaskedViewId(R.id.password_view)
Visitor.removeMaskedViewId(R.id.password_view);

By View Object

Adding:

var passwordView = findViewById<View>(R.id.password_view)
Visitor.addMaskedView(passwordView)
View passwordView = findViewById(R.id.password_view);
Visitor.addMaskedView(passwordView);

Removing:

var passwordView = findViewById<View>(R.id.password_view)
Visitor.removeMaskedView(passwordView)
View passwordView = findViewById(R.id.password_view);
Visitor.removeMaskedView(passwordView);

Masking a Composable view

To add ids to composable views, follow the instructions described in the official docs. In short, you'll need to:

  1. Create an ids.xml file in res/values/ and define your views ids there:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <item name="compose_view_1" type="id" />
</resources>
  1. Change your compose view to a native view form:

before

Text(
    text = stringResource(id = R.string.quick_demos_title),
    color = HomePrimaryTextColor,
    fontSize = 20.sp,
    fontWeight = FontWeight.Bold
)

after

// COMPOSE VIEW WITH ID REFERENCE SO WE CAN USE IT TO PASS TO THE SDK
AndroidView(factory = {
    TextView(it).apply {
        id = R.id.compose_view_1 // the id you defined in ids.xml   
        text = it.getText(R.string.quick_demos_title)
        setTextColor(android.graphics.Color.WHITE)
        typeface = Typeface.DEFAULT_BOLD
        textSize = 20.sp.value
    }
})
  1. Proceed with the steps described in the By View ID section, using the same defined id.

One-Click Connect

Agent One-Click Connect can be implemented with the Presence and Signalling API.

Support

Email mobilesupport@glance.net with any questions.

By continuing to use the site, you agree to the use of cookies. Learn More