The Embrace Developer Hub

Welcome to the Embrace documentation. You'll find comprehensive guides and documentation to help you start working with Embrace as quickly as possible, as well as support if you get stuck. Let's jump right in!

Get Started

Integration Guide

Android Get Started Guide

📘

Docs Have a New Home!

See the updated Android integration guide.

To get started with Embrace for Android, the basic integration is four simple steps and should take less than 15 minutes. If you are in front of your Mac or PC and ready to code, please use the self-service flow. To ask us questions directly, join the Embrace Slack community.

Once you complete the initial integration steps, you can verify its success by reviewing events as they happen real-time. While you are still attached to the debugger, go to the Recent Sessions page on the left-hand menu of the Embrace dashboard. Select the Debugger tab in the upper menu. Locate and click into your session under Live Sessions. You should see your events flow in real-time.

To fully realize Embrace's value in (i) development and (ii) post app release, a few more features are recommended. This includes integrating logs and moments, and defining your customer segments. Please see the Recommended Configuration guide below.


Step 1: Add the Embrace SDK

FAQ: Common Questions and Solutions

The Embrace Android SDK is publicly available on JCenter. Make the following changes in your project’s build.gradle file to add the SDK to you app:

buildscript {
  repositories {
    jcenter()
    google()
  }
  dependencies {
    classpath 'embrace-io:embrace-swazzler:4.4.0'
  }
}

Configure Embrace in your app build.gradle file:

apply plugin: 'com.android.application'
apply plugin: 'embrace-swazzler'
repositories {
  jcenter()
  google()
}

android {
    ....

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    ...
}

embrace {
  appId = '<EMBRACE_APP_ID>'
  apiToken = '<API_TOKEN>'
}

The app ID and API token are available during the self-serve flow and in the dashboard under settings. Click the gear icon on the top right hand corner. If you can't find them or still have not received them, please contact us at [email protected].

Your AndroidManifest.xml should have the following permissions set so Embrace can send events and monitor connectivity.

  • android.permission.INTERNET
  • android.permission.ACCESS_NETWORK_STATE

Requirements

Embrace requires

  • Android 4.1 (API 16) or later
  • Gradle 4.4 or later
  • Android Build Tools Plugin 3.+
  • Java 8

If you use a version older than any of those listed, please contact us via email at [email protected] or reach out to us on Slack.

Step 2: Initialize Embrace

FAQ | API

From your app’s custom Application class, which must extend android.app.Application, call Embrace.getInstance().start(this) at the start of the onCreate method.

import io.embrace.android.embracesdk.Embrace;

public final class MyApplication extends Application {

@Override
public void onCreate() {
    super.onCreate();
    Embrace.getInstance().start(this);
}

Please make sure any networking libraries such as OkHttp or Retrofit are initialized before Embrace.

Step 3: Set Your User Identifiers

FAQ: Identifying Users | API

User lookup is a useful tool to understand and resolve problems quickly. It can help developers and QA teams debug issues during development. You can also utilize user lookup to triage customer complaints post-release.

Set the identifiers for your users by adding one or more of the lines below. The best practice is to set the user identifiers early in the startup and whenever a user logs in or registers.

Embrace.getInstance().setUserIdentifier("123");
Embrace.getInstance().setUsername("abc");
Embrace.getInstance().setUserEmail("[email protected]");

Step 4: Test the Integration

To verify your integration is working, add an error log to your application:

Embrace.getInstance().logError("error log with screenshot sent to Embrace (Woo-hoo!)");

If you are integrating your app with Embrace for the first time in the onboarding page, you will be able to proceed to the next step once a complete session is captured. Complete the session by backgrounding your app and relaunching it. Once you gain access to the rest of the dash and are still attached to the debugger, go to the Recent Sessions page on the left-hand menu. Select Debugger on the upper menu and locate and click into your session under Live Sessions. You should see your events flow in real-time.

In general, data for the entire session is sent to Embrace when the application is sent to the background and reopened.


Recommended Configuration

Crash & Log Symbolication

FAQ
By default, a stack trace will only show memory addresses, so it must be symbolicated to display useful information. Symbolication will replace the memory addresses with function names, file paths, and line numbers.

Proguard files will be uploaded automatically. (Please note that we do not officially support Dexguard.) If you don't see symbolicated crashes while using Proguard, contact us at [email protected] and we will work with you directly.


Startup Performance

FAQ | API
The Embrace SDK automatically records the Startup event once it's initialized, and automatically determines the end of the startup when the Activity.onResume() method returns. However not all apps fit the onResume() paradigm (i.e. having a splash screen). You can manage the end of your app's startup by adding the @StartupActivity annotation to any Activity class that you wish to skip. This will tell the Embrace SDK that it should not automatically end the Startup for that Activity.

@StartupActivity
public class MainActivity extends Activity {
  // Your code goes here...
}

For any skipped activity, to end the Startup manually, add the following method call before wherever a user can first interact with your app. Keep in mind that your startup can have multiple ending locations (i.e. cold start vs start via push notifcation to a deeplink). Feel free to call this method as many times as you like.

Embrace.getInstance().endAppStartup();

By default, a screenshot will be captured if the startup moment does not complete within 5 seconds and the app is still in the foreground. To disable this behavior, set the following configuration in the SDK config file. See this section for more information on how to use the SDK config.

{
  "startup_moment": {
    "take_screenshot": false
  }
}

Logging

FAQ | API

Log messages are a great tool to gain proactive visibility into a user's session and to debug issues. Add Error, Warning and Info log messages to provide additional context to your user timelines and to aggregate on counts of expected issues. Embrace does not limit the number of logs and does not require that you turn them off on app release.† Each log message may include a stack trace and screenshot (defaulted takeScreenshot: false for info logs).

// Properties are not required but are shown here as examples.
// A screenshot is captured for Error and Warning logs by default.
// A stack trace is only captured for Error logs by default.

// Set log properties (optional step) 
Map<String, Object> props = new HashMap<>();

props.put("item", item_name /*user defined*/); 
props.put("quantity", item_qty /*user defined*/);

// Log an error message (Screenshot default:on, Stacktrace default: on)
// Second parameter sets the log properties. To not use log properties, set the 2nd parameter to null
// Third parameter controls the screenshots. Not providing this parameter will use default configs for screenshots
Embrace.getInstance().logError("User purchase request failed", props, false);

// Log a warning message (Screenshot default:on, Stacktrace default:off)
Embrace.getInstance().logWarning("User attempted expired credit card", props);

// Log an info message (Screenshot default:off, Stacktrace default:off)
Embrace.getInstance().logInfo("User has entered checkout flow", props);

Additionally, Embrace supports adding custom properties to add even more context around log messages. These are simple key-value attribute pairs that are sent with the log message to provide additional visibility. Both property keys and values function as filters on the App Performance and Logging pages, and are displayed in session timelines. You are limited to 10 properties for any given log message.

In the example above, an item property key is set and item_name is assigned as the value of the property. Log properties can be utilized in multiple ways. For example, you can set props.put("share", platform] where platform could be "instagram", "facebook", or "twitter" to track which media platform a user might have shared content to.

† Important: note that all log messages are sent with a network request immediately as they occur, and not at the end of the session. We highly recommend that you do not define your console logs (i.e. debug and verbose messages) as info logs. Instead, use Breadcrumbs.

Breadcrumbs

FAQ | API

Other tools limit breadcrumbs via their pricing models, however, we fundamentally believe this is a mistake. Set your low-level debug and verbose messages as Breadcrumbs to provide rich context within each session on the user timeline. Unlike Error, Warning or Info logs, breadcrumbs are neither aggregated nor are they sent with properties or a stack trace.

Additionally, breadcrumbs are sent with the session payload and not as they occur. This allows developers to pipe their console logs to provide additional session context without inflating the overall cost of the SDK.

// Add a breadcrumb to the Session Timeline (stacktraces and screenshots not applicable)
Embrace.getInstance().logBreadcrumb("Your 64-char-or-less message here...")

Performance Monitoring ("Moments")

FAQ | API

App Moments identify and measure the time to completion of key locations in your app. Conceptually, this is like a stopwatch. SLAs, KPIs, and key experiences are often best measured with Moments. Examples include the time it takes for startups to complete or the time it takes to complete a purchase after a "confirm purchase" button is pressed.

Embrace measures time distributions (durations) and incomplete rates. Incomplete rates fall into three categories:

  1. Abandonment Rates - when a user leaves before the predefined 5s threshold
  2. Stall Rates - when a user leaves after 5s
  3. Crash Rates - when a user crashes or OOMs during the moment.

When defining the start and end(s) of the moment, keep in mind that a moment can have multiple endings (feel free to end it as many times as you like). Similar to log data, moment data is sent immediately when it occurs. We also support adding custom properties to moments with the same 10 property limit as log properties. Pass custom properties to the start and/or end of a moment.

// Moments often end in multiple different places in the app and code.  
// An end event can be called multiple times to ensure a moment is ended.

// Set screenshot boolean (optional step)
boolean shouldTakeScreenshot = true;

// Set moment properties (optional step)
Map<String, Object> props = new HashMap<>();

props.put("item", item_name /*user defined*/);
props.put("quantity", item_qty /*user defined*/);

// Identify and start app moment 
Embrace.getInstance().startEvent("purchase-cart"
    null /*this is a moment identifier*/, 
    shouldTakeScreenshot,
    props);
    
// End Moment
Embrace.getInstance().endEvent("purchase-cart"
    null /*this is a moment identifier*/,
    shouldTakeScreenshot,
    props);

Moment identifiers are useful when an app has separate parallel instances of the same Moment. A common use case for parallel moments is image or photo uploading.


User Segments ("Personas")

API

Many mobile teams track users in pre-defined segments or cohorts. Often these segments, like payers or heavy bidders, have specific usage patterns with errors that are not detectable or otherwise hidden when aggregated with all other users. Set and clear Personas as soon as you know when a user belongs to or leaves a specific segment.

// Setting the "Payer" Persona on a User
Embrace.getInstance().setUserAsPayer();

// Clearing the "Payer" Persona from User
Embrace.getInstance().clearUserAsPayer();

// Clearing all user personas 
Embrace.getInstance().clearAllUserPersonas();

// Default personas are also available to all apps 
// new_user, power_user, logged_in, vip, content_creator, tester
Embrace.getInstance().setUserPersona("new_user")

SDK Config File

🚧

The configuration file format and required configuration file location changed with the release of the 4.x series of SDKs. The following section describes the format and location used for versions 4.0.0 and later. We encourage everybody to upgrade to a 4.x SDK, but if you are not able to upgrade and you need help with the 3.x configuration file format, please contact [email protected]

Certain SDK configs are only settable in a custom embrace-config.json file. This file should be located in app/src/main,

File format

🚧

If you use a configuration file, you must specify the app_id and api_token in it. The specification of these credentials in your app/build.gradle file is deprecated.

A sample configuration file is shown below. with a number of sample settings. See the table below for a complete set of configuration options.

{
  "app_id": "NNNNN",
  "api_token": "0123456789abcdef0123456789abcdef",
  "sdk_config": {
    "networking": {
      "capture_request_content_length": false
    },
    "startup_moment": {
      "automatically_end": true
    },
    "taps": {
      "capture_coordinates": true
    }    
  }
}

Custom Settings for Build Types, Flavors, and Variants

🚧

SDK version needed

Since SDK release 4.2.7 it is possible to specify flavor configurations. Prior to that it was only possible to specify variant and build-type configurations for flavorless projects.

It is possible to specify build type-, flavor-, and variant specific configurations that take precedence of the default configuration located at app/src/main/embrace-config.json. No merging of configuration is done between, say, a build-type configuration and the default configuration. The entire configuration must be specified in each configuration file.

The order of evaluation is as follows. The first option that is found will be used

  • Variant -- app/src/<variant>/embrace-config.json
  • Flavor -- app/src/<flavor>/embrace-config.json
  • Build type -- app/src/<build type>/embrace-config.json
  • Default -- app/src/main/embrace-config.json

Note that if you have a project without any flavors configured, then your variant and build type names will be the same.

Let's consider a project with the following structure:

  • Two flavors -- paid and free
  • Two build types -- debug and release

and the following configuration files

  • Variant file located at app/src/paidRelease/embrace-config.json
  • Flavor file location at app/src/paid/embrace-config.json
  • Build type file at app/src/release/embrace-config.json
  • Default at app/src/main/embrace-config.json
VariantConfig usedReason
paidReleaseapp/src/paidRelease/embrace-config.jsonVariant config exists
paidDebugapp/src/paid/embrace-config.jsonNo variant config exists, but there is a matching flavor config
freeReleaseapp/src/release/embrace-config.jsonNo matching variant or flavor config exists, but there is a matching build type config
freeDebugapp/src/main/embrace-config.jsonNo matching variant, flavor, or build type config exists, so we fall back on the default config

Note that this is an artificially-complicated example to illustrate what is possible. Most likely your configuration will be much simpler.

Supported Settings

KeyTypeDefaultDescription
app[report_disk_usage]booleantrueThe SDK collects the disk usage for the app. You can disable this if your app has a large number of local files to prevent excessive resource usage, especially on lower-end devices
crash_handler[enabled]booleantrueSet to false to prevent the SDK from connecting to the uncaught exception handler.
networking[capture_request_content_length]booleantrueDisable capture of network length which can interfere with certain streaming network requests
networking[disabled_url_patterns]string array[]Specify one or more regular expressions to exclude network request with URLs matching one of the regular expressions from being captured.
networking[trace_id_header]stringx-emb-trace-idThe name of the header that trace IDs are captured from
session[async_end]booleanfalseSend the session end message asynchronously.
session[max_session_seconds]intnullEnable automatic ending of sessions every N seconds. This is only recommended for applications, such as kiosks, where the app is never expected to go to the background. This value must be 60 seconds or greater if set.
startup_moment[automatically_end]booleantrueControl whether the startup moment is automatically ended.
startup_moment[take_screenshot]booleantrueControl whether screenshots are taken during the startup moment.
taps[capture_coordinates]booleantrueControl whether coordinates are captured for taps.

SDK version 4.2.2 and later will indicate which settings are being overridden by your custom configuration with a log emitted for each non-default setting during SDK startup, e.g.

Embrace: Custom config value networking.capture_request_content_length: false
Embrace: Embrace SDK started. API key: NNNNN Version: 4.2.4

SDK Gradle Plugin Config File

📘

Most applications do not require any custom configuration of the Embrace SDK Gradle Plugin, but some modular applications require one or more of these settings to be present. Please contact [email protected] if you have any questions about these settings and if they are needed for your app.

The SDK Gradle Plugin config file must be located in your project at the following location src/main/embrace-swazzler-config.json. The configuration is shared by all variants.

KeyTypeDefaultDescription
force_incremental_overwritebooleanfalseEnable this to force copying of unchanged JAR files during the swazzling phase. Enabling this is discouraged unless Embrace's support team has instructed you to enable it.
force_okhttp_wrapper_injectionbooleanfalseEnable this if okHttp exists as a dependency in any of your dependencies or submodules. The plugin will emit a warning at build time indicating if you need to add this setting.
force_volley_wrapper_injectionbooleanfalseEnable this if Volley exists as a dependency in any of your dependencies or submodules. The plugin will emit a warning at build time indicating if you need to add this setting.
{
  "force_okhttp_wrapper_injection": true
}

Updated about a month ago

Integration Guide


Android Get Started Guide

Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.