Quickstart

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. Default UI
  12. (Optional) Agent Viewer Session
  13. (Optional) Specify a Custom Agent Viewer
  14. (Optional) One-Click Connect

Get an Agent Account and Group ID from Glance

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

To include the AAR in the app, put it in the app/libs folder. Then modify the application’s build.gradle file to include the following just below apply plugin: '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:

compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
}

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

implementation(name: 'glanceSDK', ext: 'aar')
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
annotationProcessor "androidx.lifecycle:lifecycle-compiler:2.2.0"
implementation "org.java-websocket:Java-WebSocket:1.4.0"

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.

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. Pass a reference to your main activity and your Group ID as the second parameter.

You may also pass optional name, email, and phone number strings 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.

The third argument to Visitor.init is reserved for future use, you should pass an empty string.

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

Set an Event Handler

Add the following to your Activity:

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

To start a session with a random key call:

Visitor.startSession()
Visitor.startSession();

If you have a known value you wish to use for a 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.

Visitor.startSession("12345")
Visitor.startSession("12345");

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.

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

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

By View Object

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

Default UI

Glance provides a default user interface for screenshare, agent video, and voice sessions.

You can customize the default interface colors, text, and graphics to match your company’s branding, see Default User Interface for more information.

To build your own custom user interface, the default UI needs to be disabled:

Visitor.defaultUI(false)
Visitor.defaultUI(false);

Agent Viewer Session

When an agent joins with video, a small default view will be shown in the corner with the agent video.

To control the agent viewer view, specify a custom agent view described in the next section.

Custom Agent Viewer

A custom agent viewer can show the agent video in a custom view that your application controls.

Define a view that is present in all of the activity layouts you would like to show and utilize a consistent view id across all instances.

Pass that consistent view id into the api.

Visitor.setCustomSessionViewId(R.id.my_viewer_overlay)

To stop the custom session viewer behavior:

Visitor.clearCustomSessionViewId()
Visitor.setCustomSessionViewId(R.id.glance_agent_viewer);

PS.: remember to call Visitor.defaultUI(false); otherwise these changes won't take effect.

To remove the custom agent viewer behavior:

Visitor.clearCustomSessionViewId();

One-Click Connect

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

Support

Email mobilesupport@glance.net with any questions.

FAQ

  1. If you are getting the following error while trying to run the app and installing NDK fails:
No version of NDK matched the requested version 21.0.6113669. Versions available locally: 21.4.7075529, 23.1.7779620

Install NDK '21.0.6113669' and sync project

Go to File > Project Structure > Modules > NDK Version > choose the latest version you have installed > Apply > Run again

  1. I already have everything set up to use the Media Projection, but when I start the session and then I grant the permission and the Agent joins the session, only a blank screen is shown on their side.
    A.: maybe you forgot to implement the onActivityResult listener. Please check our sample to see how to do it.

  2. I've already had called Visitor.defaultUI(false) and Visitor.setCustomSessionViewId(R.id.glance_agent_viewer) but I'm still not able to see my custom Agent Viewer layout.
    A.: check if you haven't forgotten to add the line in your MainActivity layout.

  3. I've set all configurations needed to customize the AgentViewer view, but the view is not draggable.
    A.: you need to implement the View.OnTouchListener for this to work. Check our sample of how to do it.

  4. I've implemented a different shape for my custom AgentViewer view, but it is being shown in a square shape.
    A.: check your view class implementation. Using Canvas, Path and Paint in Android is always challenging.

  5. I've overridden the default UI and video UI dialog button colors values, but they are not changing.
    A.: check your defined themes are extending any Material Themes or other similar, because they may prevent the buttons to use our defined color keys.

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