mPulse Android SDK (Version 2) Reference

Introduction

The mPulse Android SDK (version 2) is a library that you can use to send beacons from any Android application to mPulse.

What types of data can I send?

The mPulse Android SDK lets you send Custom Metric and Custom Timer beacons to mPulse.

For each beacon, you can set the View Group, A/B test, and Custom Dimensions.

The mPulse Android SDK also monitors all network activity performed by the application and its libraries. Each network request can be monitored individually and its performance data will be sent on a beacon.

The mPulse Android SDK also allows you to monitor Actions, which are distinct user interactions. Actions can be started at any time via the SDK, and stopped either programmatically or automatically by the SDK once all network activity has quieted down. All network requests during the Action will be included on the Action beacon’s Waterfall.

Getting Started

Before using the mPulse Android SDK, you will need to have a mPulse app and an associated API Key. For information on how to setup the mPulse app and the API Key, go to mPulse setup.

Once your app has been configured in mPulse, you can use the mPulse Android SDK.

Custom Metrics

Custom Metrics are user-defined counts that refer to a business goal, or to a Key Performance Indicator (KPI) such as revenue, conversion, orders per minute, widgets sold, etc. The value or meaning of a Custom Metric is defined by the App Administrator.

You can programmatically increment a Custom Metric using the SDK.

Custom Metrics must be defined in the App dialog before use.

Custom Timers

A Custom Timer can be based on any measurable user-defined duration.

You can programmatically send the value of a Custom Timer using the SDK.

Custom Timers must be defined in the App dialog before use.

View Groups

A View Group (also known as a Page Group in a web app) allows for measurement across views that belong together. Grouping views in this way helps you capture and summarize the performance characteristics across the entire group.

For mobile apps, Launch may make up one View Group, while the Login view may make up a second, and Product views a third group. Search Results and Checkout views may also have their own groups.

You can programmatically set the View Group using the SDK.

Custom Dimensions

In addition to the out-of-the-box dimensions already provided within mPulse, App Admins can define additional Custom Dimensions for the given app. For example, a Custom Dimension to track Premium Users versus Free Users.

You can programmatically set a Custom Dimension using the SDK.

Custom Dimensions must be defined in the App dialog before use.

mPulse Android SDK

Getting the Library (Gradle)

Instrumenting an Android app with Gradle can be done by including two dependencies to your project’s build.gradle files: one at the project level and one at the application level.

In the project’s build.gradle file, add the following classpath:

buildscript {
    repositories {
        // ...
    }
    dependencies {
        classpath 'com.soasta.mpulse:mpulse-android-gradle-plugin:<replace with most recent version>'
        // ...
    }
}

At the Android application level, two changes are necessary to make mPulse available in your Android application.

At the top of your application’s build.gradle file, add this apply plugin line:

apply plugin: "com.android.application"
apply plugin: "com.soasta.mpulse.android"

Then add the mPulse library to your compile dependencies:

dependencies {
    compile 'com.soasta.mpulse:mpulse-android:<replace with most recent version>'
    // ...
}

You can find the most recent version on JCenter or Maven, and can read the Release Notes.

Configuration

Initialization

To use the mPulse Android SDK, you must first initialize your Android project with your API Key:

import com.soasta.mpulse.android.MPulse;

public static final String MPULSE_API_KEY = "YOUR_API_KEY";

// First, initialize with your API Key in the onCreate Method of your Activity
MPulse.sharedInstance().initializeWithAPIKey(MPULSE_API_KEY, getApplicationContext());

// Later, you can interact with MPulse by getting the shared instance
MPulse mpulse = MPulse.sharedInstance();

After you’ve called initializeWithAPIKey(), you can access the instance by calling MPulse.sharedInstance().

In most cases, it makes sense to do this in your main Activity’s onCreate() method.

You can also specify global settings during initialization:

MPulseSettings settings = new MPulseSettings();
settings.setViewGroup("Default");
settings.setABTest("A");

MPulse.sharedInstance().initializeWithAPIKey(MPULSE_API_KEY, getApplicationContext(), settings);

ProGuard

If you are using ProGuard with minifyEnabled, you will need to add the following to your proguard-rules.pro file:

-keep class com.soasta.** { *; }
-keepattributes Signature

Permissions

In order to send beacons the following Android permissions are required:

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

Capturing location data is optional and can be activated by adding one of the following permissions:

  • android.permission.ACCESS_COARSE_LOCATION

Or

  • android.permission.ACCESS_FINE_LOCATION

Example AndroidManifest.xml lines:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Enabling or Disabling the SDK at Runtime

Once initializeWithAPIKey() is called, the mPulse Android SDK is enabled.

You can disable the mPulse Android SDK at runtime by calling disable():

MPulse.sharedInstance().initializeWithAPIKey(MPULSE_API_KEY);

// later:
MPulse.sharedInstance().disable();

Once disabled, mPulse will no longer send beacons.

mPulse can be re-enabled by calling enable():

MPulse.sharedInstance().enable();

Automatic Network Request Instrumentation

Once included in the project, mPulse will automatically instrument all network requests.

Network requests will be instrumented as long as they are sent from one of the following classes (or a library that uses one of these classes):

  • java.net.URLConnection
  • com.squareup.okhttp.OkHttpClient version 1.x
  • okhttp3.OkHttpClient version 3.x (after version 2.2.0)

Network Request Filtering

Network Request Filtering allows developers to selectively monitor the performance of specific network requests in the application. This means you can gather performance data for requests that are important to the user experience, while ignoring requests that are not relevant, such as other library’s analytics beacons.

You can modify the state of network request monitoring through either the mPulse UI or via the SDK at runtime. Network request monitoring can be in one of three modes:

  • ALL (Blacklist mode) (default): All network requests are instrumented. You can exclude specific URLs.
  • MATCH (Whitelist mode): Only those requests matching your criteria will be instrumented. Your Whitelist will control which URLs are included.
  • NONE: No network requests are instrumented.

The mPulse Android SDK allows you to control the state of network request monitoring during runtime using the following SDK APIs:

Disable network request beacons (ie. set the mode to NONE):

MPulse.sharedInstance().disableNetworkMonitoring();

Enable network request beacons (ie. set the mode to ALL, Blacklist mode):

MPulse.sharedInstance().enableNetworkMonitoring();

Enable Whitelist-based network request filtering (ie. set the mode to MATCH, Whitelist mode):

MPulse.sharedInstance().enableFilteredNetworkMonitoring();

When these APIs are used, they will take precedence over the mPulse UI configuration, for the duration of the runtime of the application.

Programmatically Extending the Filters

The mPulse Android SDK maintains a Blacklist and Whitelist (for ALL and MATCH modes respectively), and it will use these lists to filter URLs.

The mPulse UI allows you to control the Blacklist and Whitelist URLs within the app’s configuration dialog.

In addition, you can programmatically add URL filters at runtime. These filters will be amended to the app configuration from the mPulse UI.

Examples of adding URL filters to the Whitelist and Blacklist:

// Adds a RegEx pattern to the list of Whitelist filters
MPulse.sharedInstance().addUrlWhiteListFilter("NameOfFilter", ".*pattern.*");

// Adds a RegEx pattern to the list of Whitelist filters (without a filter name)
MPulse.sharedInstance().addUrlWhiteListFilter(".*pattern.*");

// Adds a RegEx pattern to the list of Blacklist filters
MPulse.sharedInstance().addUrlBlackListFilter("NameOfFilter", ".*pattern.*");

// Adds a RegEx pattern to the list of Blacklist filters (without a filter name)
MPulse.sharedInstance().addUrlBlackListFilter(".*pattern.*");

// If you wish to only tag a network request with a specific View Group using a pattern
MPulse.sharedInstance().addViewGroupFilter("NameOfFilter", ".*pattern.*", "My View Group");

Here’s an example of using an advanced filter within your application. The MPFilter class is given direct access to the MPBeacon, and should set result.setMatched(true) when matched.

// Imports
import com.soasta.mpulse.core.filter.MPFilter;
import com.soasta.mpulse.core.filter.MPFilterResult;
import com.soasta.mpulse.core.beacons.MPBeacon;
import com.soasta.mpulse.andriod.beacons.MPApiNetworkRequestBeacon;

// In your code:
MPFilter filter = new MPFilter()
{
  @Override
  public MPFilterResult match(MPBeacon beacon)
  {
    MPFilterResult result = new MPFilterResult();

    // Do something here to either drop or include this beacon
    if (beacon != null && beacon instanceof MPApiNetworkRequestBeacon)
    {
      MPApiNetworkRequestBeacon networkBeacon = (MPApiNetworkRequestBeacon) beacon;
      if (networkBeacon.getUrl().matches(".*pattern.*"))
      {
        result.setViewGroup("Example View Group");
        result.setMatched(true);
      }
    }

    return result;
  }
};

For easier interaction with URLs you also have the option to use MPUrlFilter which will pass a String to the match() method:

// Imports:
import com.soasta.mpulse.android.filter.MPUrlFilter;
import com.soasta.mpulse.core.filter.MPFilterResult;

// In your code:
MPUrlFilter filter = new MPUrlFilter()
{
  @Override
  public MPFilterResult match(String url)
  {
    MPFilterResult result = new MPFilterResult();

    if (url != null && !url.equals(""))
    {
      if (url.contains("example.com"))
      {
        result.setViewGroup("example");
        result.setMatched(true);
      }
    }

    return result;
  }
};

Now that the filter has been created, you can add it to the Whitelist or Blacklist.

If you wish to include the filter in the Whitelist, setting matched true (MPFilterResult.setMatched(true)) on the MPFilterResult for match(MPBeacon beacon) will tell mPulse to monitor the request, while setting matched to false (MPFilterResult.setMatched(false)) will tell mPulse to ignore the request.

MPulse.sharedInstance().getFilterManager().addWhiteListFilter("NameOfFilter", filter);

Conversely if you wish to include the filter in the Blacklist, a setting matched to false (MPFilterResult.setMatched(false)) on the MPFilterResult for match(MPBeacon beacon) will tell mPulse to monitor the request, while setting the matched to true (MPFilterResult.setMatched(true)) will tell mPulse to ignore the request.

MPulse.sharedInstance().getFilterManager().addBlackListFilter("NameOfFilter", filter);

Should a viewGroup already be configured via the SDK (using MPulse.sharedInstance().setViewGroup(String viewGroup)) the viewGroup set by MPFilterResult via MPFilterResult.setViewGroup("myviewgroup") will override it. A value of null or "" (empty string) will not change the viewGroup on the beacon.

Excluding Libraries from Instrumentation

Should you wish to not instrument a library that is part of your project you can exclude it by using the following configuration closure in your application’s build.gradle file:

mpulseAndroid {
  exclude ~/.*do-not-instrument.*/
}

Notice that the exclude function inside the mpulseAndroid closure accepts Groovy Patterns using the Pattern operator.

If you wish to exclude the contents of a longer directory path that contains libraries you are using in your project, you should use the ${File.separator} path separator token:

mpulseAndroid {
  exclude ~".*${File.separator}special-libs${File.separator}.*"
}

Send a Custom Timer

The mPulse Android SDK can be used to send a Custom Timer.

You can track the time it took for an action to occur, such as an image upload or an attachment file download, using Custom Timers.

At the start of your action, call startTimer() by giving it a timerName. startTimer() will return a unique Timer ID (String) and will keep track of the start time:

String timerID = MPulse.sharedInstance().startTimer("MyTimer");
// -> "MyTimer-d4d67062-7064-42b5-85ed-4e69d8824ef9"

At the end of your action, call stopTimer() by passing in the Timer ID. mPulse stops the timer and sends a beacon to the server:

MPulse.sharedInstance().stopTimer(timerID);

You may also directly specify a timer name and value using sendTimer(name, value):

// value is in milliseconds
MPulse.sharedInstance().sendTimer("MyTimer", 4);

By default, the View Group, A/B Test and Custom Dimensions for the timer will be copied at the time startTimer() was called. If you wish to use the View Group, A/B Test and Custom Dimensions copied when stopTimer() was called, you can specify true for the updateDimensions parameter:

// stops the timer and updates dimensions
MPulse.sharedInstance().stopTimer(timerID, true);

If you wish to cancel a timer (and not send a beacon to mPulse), you can call cancelTimer():

// cancel the timer
MPulse.sharedInstance().cancelTimer(timerID);

Both startTimer() and sendTimer() accept a final parameter of MPulseMetricTimerOptions, which controls the behavior of Custom Timers while an Action is ongoing. See the Actions documentation for details:

MPulseMetricTimerOptions options = new MPulseMetricTimerOptions();

// include on the Action beacon (instead of sending a separate beacon)
options.duringAction = MPulseMetricTimerOptions.DuringAction.INCLUDE_ON_ACTION_BEACON;

// if the same Custom Timer was used twice on this Action, SUM the results
options.onActionDuplicate = MPulseMetricTimerOptions.OnActionDuplicate.SUM;

String timerID = MPulse.sharedInstance().startTimer("MyTimer", options);

// or

MPulse.sharedInstance().sendTimer("MyTimer", 100, options);

Send a Custom Metric

You may increment a Custom Metric by using sendMetric():

MPulse.sharedInstance().sendMetric("MyMetric", 23);

sendMetric() accepts a final parameter of MPulseMetricTimerOptions, which controls the behavior of Custom Metrics while an Action is ongoing. See the Actions documentation for details:

MPulseMetricTimerOptions options = new MPulseMetricTimerOptions();

// include on the Action beacon (instead of sending a separate beacon)
options.duringAction = MPulseMetricTimerOptions.DuringAction.INCLUDE_ON_ACTION_BEACON;

// if the same Custom Metric was used twice on this Action, SUM the results
options.onActionDuplicate = MPulseMetricTimerOptions.OnActionDuplicate.SUM;

MPulse.sharedInstance().sendMetric("MyMetric", 23, options);

Set View Groups

You may get, set, and reset the View Group. Once set, the View Group will be associated with every subsequent beacon.

View Group strings are limited to 100 characters, and can include any of the following:

  • 0-9
  • a-z
  • A-Z
  • (space)
  • _ (underbar)
  • - (dash)

Set a View Group using setViewGroup():

MPulse.sharedInstance().setViewGroup("MyViewGroup");

Reset the View Group using resetViewGroup():

MPulse.sharedInstance().resetViewGroup();

Get the current View Group using getViewGroup():

String viewGroup = MPulse.sharedInstance().getViewGroup();

In addition, for each network request beacon, you can override the global View Group for that beacon by creating a filter and calling setViewGroup() on the MPFilterResult.

You can call setViewGroup() even if the result is un-matched. For example, in ALL (Blacklist) mode, you can call setMatched(false) so the network request is still monitored, and call setViewGroup() to set that request’s View Group. If multiple filters set the View Group, the result is undefined (the last filter will take precedence).

See the Network Request Filtering section for details.

Set A/B Test

You may get, set, and reset the A/B Test. Once set, the A/B Test will be associated with every subsequent beacon.

Set a A/B Test using setABTest():

MPulse.sharedInstance().setABTest("A");

Reset the A/B Test using resetABTest():

MPulse.sharedInstance().resetABTest();

Get the current A/B Test using getABTest():

String abTest = MPulse.sharedInstance().getABTest();

Set Custom Dimensions

You may get, set, and reset Custom Dimensions. Once set, the Custom Dimensions will be associated with every subsequent beacon.

Set or reset a Custom Dimension using setDimension():

MPulse.sharedInstance().setDimension("MyDimension", "new value");

Reset the Custom Dimension using resetDimension():

MPulse.sharedInstance().resetDimension("MyDimension");

Reset all Custom Dimensions using resetAllDimensions():

MPulse.sharedInstance().resetAllDimensions();

Get a list of all Custom Dimensions using getDimensions():

String[] dimensions = MPulse.sharedInstance().getDimensions();

Global Settings

The MPulseSettings class can be used to configure multiple SDK settings at once. MPulseSettings can be given to initializeWithAPIKey() to apply settings at startup, or later to updateSettings() to update multiple settings at once.

MPulseSettings has getters and setters for configuring the View Group, A/B Test, Custom Dimensions, Network Filters and Action settings.

When using MPulseSettings, any items that have not been set will not be changed:

MPulseSettings settings = new MPulseSettings();
settings.setViewGroup("Default");
settings.setABTest("A");
settings.setActionMaxResources(100);

// configure settings at init
MPulse.sharedInstance().initializeWithAPIKey(MPULSE_API_KEY, getApplicationContext(), settings);

// change settings later
MPulse.sharedInstance().updateSettings(settings);

Actions

The mPulse Android SDK allows you to monitor Actions, which are distinct user interactions.

Actions can be started at any time by calling startAction(), and can stopped by either calling stopAction(), or, by having the SDK automatically stop the Action once all network activity has finished.

The two Action modes are called Wait mode and Timeout mode:

  • Wait mode will wait for stopAction() to be called, and the duration of the action will be from startAction() to stopAction()
    • This mode is best when you want to define the Action’s start and end times in your application
  • Timeout mode (default) will monitor background network activity to determine when the Action has ended, and will set the end timestamp when the final network request is complete
    • This mode is best when the Action triggers multiple network requests. The SDK will monitor all of those requests automatically.
    • By default, the mPulse SDK will wait for 1,000ms after the final network request to see if any additional network requests are started (and if so, wait for those requests to complete)
    • This mode should only be used when the Action triggers network activity

All network requests during the Action will be included on the Action beacon’s Waterfall.

There can only be a single Action ongoing at a time.

Starting an Action

To start an Action, you call the startAction() API:

// start an Action without a name
MPulse.sharedInstance().startAction();

// or, start an Action with a specific name
MPulse.sharedInstance().startAction("MyAction");

// or, start an Action with a name or other settings
MPulseSettings settings = new MPulseSettings();
settings.setActionName("MyAction");
settings.setActionTimeout(2000);
settings.setActionMaxResources(200);
settings.setTimeoutForStop();

MPulse.sharedInstance().startAction(settings);

Starting an Action while an existing Action is ongoing will abort the previous Action.

Wait Mode

In Wait mode, the mPulse Android SDK will wait for stopAction() to be called. The duration of the Action will be from startAction() to stopAction().

Any network activity that occurred during the Action will be included on the Action’s Waterfall.

Example:

// start an Action
MPulse.sharedInstance().startAction("MyAction");

// ... do stuff ...

// stop the Action
MPulse.sharedInstance().stopAction();

Timeout Mode

In Timeout mode, the mPulse Android SDK will monitor all network activity. Once network requests begin to start, the Action will remain active until all network requests have finished.

After the last network request has finished, the SDK will wait the Action Timeout (default 1,000ms) to see if any additional network activity was triggered by the last request. If not, the duration of the Action will be set to the end of the final network request. If new activity is triggered during the waiting period, the SDK will wait until all network activity has finished again.

Action Settings

You can set global Action settings that will apply to all Actions, as well as overriding the global Action settings when starting a new Action.

Settings:

  • Action Collection Behavior: Whether to use Wait or Timeout mode
  • Action Timeout: How long, in Timeout mode, the SDK waits after the last network request has finished to ensure no additional network requests were started
  • Action Max Resources: The maximum number of network requests that will be included on an Action’s Waterfall. In Timeout mode, this does not limit how many network requests will be waited for, just how many network requests will be reported in the Waterfall.

Configuring global Action settings:

// Timeout in milliseconds
MPulse.sharedInstance().setActionTimeout(2000);

// Maximum number of resources on an Action's Waterfall
MPulse.sharedInstance().setActionMaxResources(200);

// Wait mode
MPulse.sharedInstance().setActionCollectionBehavior(MPulseSettings.ActionCollectionBehavior.WAIT);

You can overwrite the global Action settings when starting an Action:

// start an Action with a name and other settings, overwriting the global Action settings
MPulseSettings settings = new MPulseSettings();
settings.setActionName("MyAction");
settings.setActionTimeout(3000);
settings.setActionMaxResources(300);
settings.setTimeoutForStop();

MPulse.sharedInstance().startAction(settings);

Custom Metrics and Custom Timers during Actions

Custom Metrics and Custom Timers that occur while an Action is ongoing can be included on that Action beacon. Otherwise, Custom Timers and Custom Metrics will generate their own beacon.

The benefit of including Custom Timers and Custom Metrics on the Action beacon is that it ensures the context is kept – the Timer and Metric are linked directly to the Action.

When starting a Custom Timer or sending a Custom Metric, you can decide the what to do if an Action is ongoing. The MPulseMetricTimerOptions class configures this:

  • MPulseMetricTimerOptions.DurationAction: What to do with a Custom Timer or Custom Metric when an Action is happening
    • SEND_DIRECT_BEACON: Send the Custom Timer/Custom Metric as a Custom Timer/Custom Metric beacon
    • INCLUDE_ON_ACTION_BEACON: (default) Include the Custom Timer/Custom Metric on the Action beacon

If the Custom Timer / Custom Metric is set to INCLUDE_ON_ACTION_BEACON, you should also decide what happens when a Custom Timer / Custom Metric is repeated during the same Action. An Action can only include a single named Custom Timer / Custom Metric per Action (Timer1 and Timer2 can both be included, but Timer1 can’t be included twice).

There are 4 options for what happens when a Custom Timer / Custom Metric occurs repeatedly during the same Action:

  • MPulseMetricTimerOptions.OnActionDuplicate: What to do with a Custom Timer or Custom Metric when it is repeated during the same Action
    • OVERWRITE: Overwrite the old value
    • IGNORE: Ignore the new value
    • SUM: Add the two values together
    • SEND_DIRECT_BEACON: (default) Convert the new value to an individual Custom Timer / Custom Metric beacon

Example usage:

MPulseMetricTimerOptions options = new MPulseMetricTimerOptions();

// include on the Action beacon (instead of sending a separate beacon)
options.duringAction = MPulseMetricTimerOptions.DuringAction.INCLUDE_ON_ACTION_BEACON;

// if the same Custom Timer was used twice on this Action, SUM the results
options.onActionDuplicate = MPulseMetricTimerOptions.OnActionDuplicate.SUM;

String timerID = MPulse.sharedInstance().startTimer("MyTimer", options);

Troubleshooting

Build Failure (Gradle)

If you see build failures similar to these:

Error:Uncaught translation error: com.android.dx.cf.code.SimException: local variable type mismatch: attempt to set or access a value of type java.lang.Object using a local variable of type int. This is symptomatic of .class transformation tools that ignore local variable information.

or

com.android.build.api.transform.TransformException: com.android.ide.common.process.ProcessException: java.util.concurrent.ExecutionException: java.lang.UnsupportedOperationException

Then your build most likely failed because the mPulse Android Gradle Plugin failed to instrument a JAR in your application. This often happens when one of your JARs is obfuscated.

Finding JAR files that failed to instrument

To find out which of your JARs failed to instrument, run Gradle from the command line with the flags --debug, --info and --full-stacktrace. With these flags set, you will be able to see which of your JARs the mPulse SDK attempted to instrument before failing the build:

$ gradle assembleDebug --debug --info --full-stacktrace
...
MPulseAndroidTransform: Weaving file from /some/path/to/a/file.jar
MPulseAndroidTransform: woven class com.example.app.a.b.c
...

Should you see this followed by an exception this may indicate that the file.jar is failing the build. You can exclude it from instrumentation in your build.gradle file by using an exclude directive:

android { /* ... */ }

/* add this to your code to exclude file.jar from being instrumented */
mpulseAndroid {
  exclude ~/.*file.*/;
}

dependencies { /* ... */ }

Runtime Exceptions after Upgrading from 2.x to 2.2.x

After upgrading from the mPulse Android SDK from version 2.x to 2.2.x, you may encounter the following runtime exception:

Process: com.example.App, PID: 1234
  java.lang.NoClassDefFoundError: Failed resolution of: Lcom/soasta/mpulse/android/MPLog;
  /* Long stacktrace pointing to code in third party instrumented library such as Volley */

To prevent this error, you will need to run the following:

$> gradle clean
...
$> rm -rf build/

This will remove all build artifacts in the .gradle/ and build/ directories of your project.

The same should be done in any subprojects and folders that also contain a build/ or .gradle/ directory.

No Beacons Being Sent

If you are not seeing beacons in the mPulse dashboards, please ensure the app has been configured correctly:

  • Ensure Gradle is configured properly:
    • classpath 'com.soasta.mpulse:...' was added to the project’s build.gradle
    • apply plugin: "com.soasta.mpulse.android" was added to the application’s build.gradle after apply plugin: "com.android.application"
    • compile 'com.soasta.mpulse:...' was added to the application’s build.gradle
  • Ensure you are using the correct mPulse API Key in initializeWithAPIKey()
  • Ensure initializeWithAPIKey() is being called after an Activity has been created (and not in Application.onCreate())
  • If you are using ProGuard, ensure sure you’ve updated proguard-rules.pro per the instructions
    • If you see beacons for Debug builds, but not for Release builds, this is a common cause
  • Ensure you’ve updated your AndroidManifest.xml with the correct permissions
  • Ensure you don’t see a Unable to refresh Config warning in the logs (see below)
  • Ensure you don’t see a Activity context not available warning in the logs (see below)
  • Ensure you see the following lines in the ADB log after the application has started:

    E/MPulse.MPulseInternal: [main] mPulse Mobile build: n.n.n
    E/MPulse.MPulseInternal: [main] mPulse initialized.
    E/MPulse.MPSession: [pool-n-thread-n] mPulse session has started.
    
  • If you are trying to send a Custom Timer or Custom Metric, ensure they have already been defined in the mPulse app configuration

  • Using a system proxy such as Fiddler or Charles, validate that:

    • There is a Config request to https://c.go-mpulse.net/api/config.json?...
    • There is a beacon being sent to https://*.mpstat.us or https://*.akstat.io
  • Enabling mPulse Android SDK debug logs by executing MPLog.setDebug(true) and MPLog.setTrace(true)

Unable to Refresh Config (log message)

The following message in your ADB log indicates that config.json could not be fetched:

W/MPulse.MPulseInternal: [pool-1-thread-1] Unable to refresh Config.
    java.util.concurrent.TimeoutException
    at java.util.concurrent.FutureTask.get
    at android.os.AsyncTask.get
    at com.soasta.mpulse.android.config.MPConfig.initWithURL
    at com.soasta.mpulse.android.config.MPConfig.refresh
    at com.soasta.mpulse.android.MPulseInternal$1.run
...

If you see this message, it means that mPulse was unable to initialize because it could not fetch the mPulse app configuration. No beacons will be sent.

Please ensure your app can connect to c.go-mpulse.net and that it is not blocked by the application or a firewall.

Also ensure the Android application has the correct permissions in the manifest.

Activity Context Not Available (log message)

The following message in your ADB log indicates the application may not have been configured properly:

W/MPulse.MPDemographics: Activity context not available...

If you see this message, it means that build.gradle was not configured properly. No beacons will be sent.

Please ensure the apply plugin line is in your project’s build.gradle file:

apply plugin: "com.soasta.mpulse.android"

Debug Logging

To enable debug logging, add the following import:

import com.soasta.mpulse.core.MPLog;

Then enable debug output:

MPLog.setDebug(true);

You can enable trace logging (which is more detailed than debug logging) as well:

MPLog.setTrace(true);

Compilation Errors

If the application is not compiling, please check the following:

  • If the application is being built with Gradle, ensure Gradle is configured properly:
    • classpath 'com.soasta.mpulse:...' was added to the project’s build.gradle
    • apply plugin: "com.soasta.mpulse.android" was added to the application’s build.gradle after apply plugin: "com.android.application"
    • compile 'com.soasta.mpulse:...' was added to the application’s build.gradle

Compatibility with other JVM Languages

The mPulse Android SDK is optimized for Java but can be used in conjunction with other languages and tooling running on top of the Dalvik JVM.

If you are using one of the following features/technologies in your project:

  • Kotlin
  • Java 8
    • Using Jack
    • Native

Please consider using one of the following 2 Gradle plugins in conjunction with the mPulse Android SDK Gradle Plugin.

GradleAspectJ-Android

Github Project Website: https://github.com/Archinamon/android-gradle-aspectj

Enable the plugin in your project’s build.gradle:

buildscript {
    repositories {
        jcenter()
        mavenCentral()
    }

    dependencies {
        // Add the next line to your dependencies so the plugin can be loaded 
        // with mpulse-android-gradle-plugin: 
        classpath 'com.archinamon:android-gradle-aspectj:<most-recent-version-here>'
        classpath 'com.soasta.mpulse:mpulse-android-gradle-plugin:<your-version-here>'
    }
}

And apply the plugin in your application’s build.gradle:

// Apply the plugin before com.soasta.mpulse.android
apply plugin: "com.archinamon.aspectj"
apply plugin: "com.soasta.mpulse.android"

Once GradleAspectJ-Android has been added, the mPulse Android SDK will utilize it for the Aspects that are included in the mPulse Android SDK.

AspectJX

Github Project Website: https://github.com/HujiangTechnology/gradle_plugin_android_aspectjx

Enable the plugin in your project’s build.gradle:

buildscript {
    repositories {
        jcenter()
        mavenCentral()
    }
    dependencies {
        // Add the next line to your dependencies so the plugin can be loaded 
        // with mpulse-android-gradle-plugin: 
        classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.2'
        classpath 'com.soasta.mpulse:mpulse-android-gradle-plugin:<your-version-here>'
    }
}

And apply the plugin in your application’s build.gradle:

apply plugin: 'android-aspectjx'
apply plugin: "com.soasta.mpulse.android"

Opening Support Tickets

When opening new support tickets, please include the following information:

  • Platform: Android
    • Android SDK version
    • Gradle version
  • mPulse SDK version
  • Complete debug logs (i.e. logcat) from a device or emulator with MPLog.setDebug(true) and MPLog.setTrace(true)
  • If possible, the project and app build.gradle files
  • If possible, a compiled APK with the mPulse SDK integrated
  • If possible, code samples of:
    • mPulse initialization
    • Beacon filtering (if used)
  • If possible, the full project source code

Known Issues

Release Notes

The mPulse Android SDK can be found on JCenter and Maven.

2.6.0 (2019-04-10)

New Features:

  • Adds support for Action Beacons
  • Action Beacons: Custom Timers and Custom Metrics are now included on the Action Beacon
  • Action Beacons: Configurable limit for the maximum number of resources to include per Action Beacon
  • Logging: Adds support for MPLog.setTrace(true) to enable trace-level logging

Bug Fixes:

  • Improves OkHttp3 monitoring by hooking into onResponse() and onFailure()
  • Cleans up use of deprecated Apache HttpClient libraries
  • Includes <uses-library> for org.apache.http.legacy for apps that need it
  • Network Request Filters are now applied in the order they were added (previously, no order was maintained)
  • Fixes SecurityException if ACCESS_NETWORK_STATE is missing

2.6.0-beta1 (2019-01-07)

New Features:

  • Adds support for Action Beacons

2.5.1 (2019-01-28)

New Features:

  • Additional support for monitoring OkHttp3 requests

Bug Fixes:

  • Fixes an exception in OkHttp3Aspect

2.5.0 (2018-11-02)

New Features:

  • Support for Java8
  • Support for GradleAspectJ-Android and AspectJX Aspect plugins

2.4.4 (2018-08-16)

Bug Fixes:

  • Protect against NullPointerException when fetching config.json in some cases

2.4.3 (2018-06-22)

New Features:

  • Adds support for RetroFit2

2.4.2 (2018-05-23)

Bug Fixes:

  • Network filtering is now only applied only to Network beacons (and not Metric or Timer beacons)

2.4.1 (2018-04-26)

New Features:

  • Additional support for OkHttp3

2.4.0 (2018-03-22)

New Features:

  • Network Filters return a MPFilterResult, which can also set the View Group

2.3.1 (2018-03-05)

New Features:

  • New APIs for simple black/whitelist filters, e.g. addUrlBlackListFilter()
  • New API for enableFilteredNetworkMonitoring()

Bug Fixes:

  • Fixed Trailing Text and End of Text filters, and RegEx capture groups for View Groups
  • Fixes race condition with setting the Network Filtering mode via the API vs. what’s set in the mPulse App configuration

2.3.0 (2017-11-29)

New Features:

  • Network Filtering added

Bug Fixes:

  • Timers, Metrics and Dimensions set before config.json is fetched now work
  • setDimension resets the Custom Dimension if the value is empty

2.2.3 (2017-03-20)

New Features:

  • Gradle 3.x support

Bug Fixes:

  • initializeWithAPIKey() will only initialize once, even if called multiple times

2.2.2 (2016-11-29)

New Features:

  • excludes Gradle directive added

2.2.1 (2016-11-18)

New Features:

  • Now uses the Gradle Transform API (for builds on Windows)

Bug Fixes:

  • Fixes two possible exceptions in the SDK

2.2.0 (2016-10-31)

New Features:

  • OkHttp3 support

2.1.0 (2016-07-18)

Breaking Changes:

  • Renamed to mpulse-android and mpulse-android-gradle-plugin

Bug Fixes:

  • Fixes an exception

2.0.1 (2016-05-23)

Bug Fixes:

  • Increase config.json timeout to 30s
  • Blacklist Adobe Omniture JAR (causes build failures)

2.0.0 (2016-05-09)

New Features

  • First mPulse Android SDK version 2.x