Android Classic Installation

πŸ“˜

If you're using Heap Classic and thinking of switching to our latest offerings, check out the full breakdown of the differences between our SDKs here.

πŸ“˜

For notes on the latest SDK versions, see our Android changelog.

πŸ‘

Heap will continue to support this Classic SDK with critical bug fixes and security updates.

Base Installation

Please review the following list of requirements and known limitations to ensure your project is prepared for installation.

Before you get started with the instructions below, we recommend you first review Before Installing: Key Considerations in our Help Center.

Requirements and Known Limitations

πŸ“˜

We host through Maven Central.

  • Your app’s compileSdkVersion should be set to 16 or above.
  • The Heap Android SDK does not support React Native. See our React Native installation guide for Android support for React Native apps.
  • The build plugin supports versions 3.0.x, 3.1.x, 3.2.1+, 3.3.x, 4.0.x, 4.1.x, 4.2.x, 7.0.x, 7.1.x, and 7.2.x of the Android Gradle plugin. AGP 2.x support has been deprecated.
  • The Heap Android SDK supports Android build tool version 24.0.3+ or greater, except for version 26.0.0 (26.0.1+ is fine).
  • To learn more about what events and properties the Heap Android SDK captures, see the mobile and Android sections of Autocaptured Data.
  • When developing apps with Instant Run, the Heap Android SDK will only record sessions and screenviewsβ€”interaction events like taps will not be captured. To test interaction event capture during development, you should disable Instant Run.
  • If you are using Windows, Android SDK 1.4.1 or greater is required.
  • A project structure with two build.gradle files, one at the root level and one in the same folder as the app code, as in the image below:

πŸ‘

We support Kotlin as a development language for Android.

πŸ‘

As of Android 1.4.0, we support obfuscated class names via Proguard or Dexguard.

Installation Instructions

❗️

In the instructions below, remember to replace your app ID with the ID of the environment to which you want to send data. You can find this ID on the Account > Manage > Projects page by clicking on the project and pulling it up in the side menu.

The following instructions should support any Android app.

πŸ“˜

If your project targets Android Gradle Plugin 8.0 or higher, you'll need to use our modern Gradle plugin instead of the Classic plugin shown below. Follow the steps in the Heap Gradle Plugin install documentation first, then jump down to the initializing Heap section below.

In build.gradle at the root level of your project, modify the buildscript section as follows:

buildscript {
  // At the top of the buildscript block, add a property for the SDK version.
  ext.heapVersion = '1.10.+'
  // ...

  dependencies {
    // Within buildscript.dependencies, add the classpath dependency below.
    // Note the double quotes, which are required to interpolate the version.
    classpath "com.heapanalytics.android:heap-android-gradle:$heapVersion"
  }
}
  • Modify the app’s build.gradle, within whichever folder your app code lives (for example, app/build.gradle):
  • Apply the Heap build plugin after the Android plugin:
apply plugin: 'com.android.application'
// Insert line below to apply our plugin
apply plugin: 'com.heapanalytics.android'
  • Add the client library as a dependency:
dependencies {
  // Insert line below to include our client library as a dependency. Note the
  // double quotes, which are required to interpolate the version.
  implementation "com.heapanalytics.android:heap-android-client:$heapVersion"

  // If you are on an older version of the Gradle build plugin (pre-3.1) you should
  // use the commented line below instead of the one above. The "compile" directive
  // is deprecated as of 3.1.
  // compile "com.heapanalytics.android:heap-android-client:$heapVersion"
  // ...
}

Initializing the Heap app

There are two ways to initialize the Heap Android SDK: via auto-init configuration via gradle at build-time, or programmatically at runtime. We recommend the build-time auto-init method for most cases, but the programmatic method can be useful if you’d like to have additional flexibility in specifying the app ID at runtime.

Build-time Initialization

In the app’s build.gradle file, add the following to the defaultConfig section:

android {
    defaultConfig {
        // Add this section to enable Heap event capture.
        ext {
          heapEnabled = true
          heapAutoInit = true
          heapEnvId = "YOUR_APP_ID"
        }
        // ...
    }
    // ...
}

Programmatic Initialization

In the app’s build.gradle file, add the following to the defaultConfig section:

android {
    defaultConfig {
        // Add this section to enable Heap event capture.
        ext {
          heapEnabled = true
        }
        // ...
    }
    // ...
}

Modify the onCreate method of your app’s entry point per the following (either an Application subclass or the activity with the android.intent.action.MAIN action set in AndroidManifest.xml):

import com.heapanalytics.android.Heap;
// ...

class MainActivity extends AppCompatActivity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Replace YOUR_APP_ID with your Heap app ID of the environment you wish to send data to
    Heap.init(getApplicationContext(), "YOUR_APP_ID");
    // …
  }
}
import com.heapanalytics.android.Heap;

class MainActivity : AppCompatActivity() {
   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       // Replace YOUR_APP_ID with the Heap app ID of the environment you wish to send data to
       Heap.init(applicationContext, "YOUR_APP_ID");
       // …
   }

   // …
}

Completing Setup

  1. Add internet permission for the app so it can send data to Heap’s servers. In the manifest, add:
    <uses-permission android:name="android.permission.INTERNET" />
  2. Launch the application in the emulator or on a device. To see interaction events while developing, you must disable Instant Run.
  3. Data should be sent to Heap upon interactions! After a few minutes, navigate to Heap’s users view to see your recent data and validate that event data is being sent properly.

Review our Java and Kotlin documentation in our API docs to learn how to identify your users or send custom events and properties to Heap.

Licenses

To print license information included in the Heap Gradle plugin, please run gradlew tasks and refer to the β€œHeap tasks” section.

Verify Your Installation

Once installed, in your app to begin capturing data. In the Heap app, select the environment your data is being sent to and check the following to ensure your installation was successful.

Using Live

  1. Navigate to the Live page within your Heap account.
  2. Filter for your IP address so you can see your specific data flowing into Heap.
  3. Start interacting with your Android app and see the raw data come in!

Using Visual labeling

  1. Navigate to the Visual labeling page within your Heap account.
  2. Pair your device using Android Visual labeling.
  3. Begin performing actions within your app through Visual labeling interface and watch as Heap captures and displays the corresponding events in the web interface.

For full steps to use Visual labeling for Android, review the Android platform section of our Visual labeling guide.

Graph Sessions by Source

  1. Navigate to the Graph analysis module (Analyze > Graph).
  2. Graph Count of Sessions and group by the Source property. Click the Run Query button.
  3. You should see the Source property populated with values β€˜android’, β€˜ios’, β€˜web’, or β€˜server’ depending on where Heap is receiving data from.

Note that interactions on mobile web will have Source set to web. To differentiate between desktop and mobile web browsers, add an additional group-by clause using the Platform or Browser property. For example, events originating from WebViews embedded within iOS applications will have Source set to web, but the Browser property set to will often be populated by a value such as Android Browser that you can use to help distinguish these events from Android Chrome events.

What does your data look like?

As you take the time to test your installation, observe the data coming in. What kind of events are there? What properties are attached to them and what values are they populated with? This is important to note early on, as event definition relies on these property values. The key is to ensure the event can be defined by a set of properties that specifically refer to that particular interaction in the intended context.

Note: If you’re unable to define an event for a specific user action, or an event you’ve defined does not have all the properties you require, you will need to do one or both of the following:

  • Define additional element attributes in your application code. Review our docs on Autocaptured Data for Android for the complete set of properties captured by Heap.
  • Enrich the autocaptured data using our APIs. For additional details, see the Enrich Your Dataset Via APIs section of the Setting Up Heap guide.

Ignoring Sensitive Data and PII

In Android, layouts can be declared either through XML at development time or through programmatic instantiation at runtime. Heap provides two mechanisms for ignoring text from layout elements for each of these definition mechanisms.

In Layout XML, you can add heapIgnore as a view tag, either via the android:tag attribute:

<!-- Interactions with this button are ignored by Heap. -->
<Button
    android:id="@+id/my_secret_button"
    android:tag="heapIgnore"
    android:text="@string/my_secret_button_text" />
    
<!-- All interactions in this subtree are ignored by Heap. -->
<LinearLayout
    android:id="@+id/my_secret_container"
    android:tag="heapIgnore">
</LinearLayout>

or via a tag element:

<!-- Interactions with this button are ignored by Heap. -->
<Button
    android:id="@+id/my_secret_button"
    android:text="@string/my_secret_button_text">
    <tag android:id="@id/heapIgnore" android:value="true" />
</Button>
    
<!-- All interactions in this subtree are ignored by Heap. -->
<LinearLayout
    android:id="@+id/my_secret_container"
    android:tag="heapIgnore">
    <tag android:id="@id/heapIgnore" android:value="true" />    
</LinearLayout>

When defining the layout programmatically, at runtime, you can call Heap.ignore(view) to ignore a view and its subtree. For example, in order to ignore only interactions with a button within a layout:

LinearLayout mySecretContainer = new LinearLayout(this);
LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, 
                                             LayoutParams.MATCH_PARENT); 

Button mySecretButton = new Button(this);
mySecretButton.setText("My Secret Button Text");
mySecretContainer.addView(mySecretButton, layoutParams);

// Ignore all interactions with mySecretButton
Heap.ignore(mySecretButton);

setContentView(mySecretContainer, layoutParams);
val mySecretContainer = LinearLayout(this)
val layoutParams = LayoutParams(
   LayoutParams.MATCH_PARENT,
   LayoutParams.MATCH_PARENT
)

val mySecretButton = Button(this)
mySecretButton.setText("My Secret Button Text")
mySecretContainer.addView(mySecretButton, layoutParams)

// Ignore all interactions with mySecretButton
Heap.ignore(mySecretButton)

setContentView(mySecretContainer, layoutParams)

If you need to ignore interactions from a larger ViewGroup, you can do so by ignoring the view container:

LinearLayout mySecretContainer = new LinearLayout(this);
LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, 
                                             LayoutParams.MATCH_PARENT); 

Button mySecretButton = new Button(this);
mySecretButton.setText("My Secret Button Text");
mySecretContainer.addView(mySecretButton, layoutParams);

// Ignore all interactions with mySecretContainer, implicitly ignores
// interactions with mySecretButton
Heap.ignore(mySecretContainer);

setContentView(mySecretContainer, layoutParams);
val mySecretContainer = LinearLayout(this)
val layoutParams = LayoutParams(
   LayoutParams.MATCH_PARENT,
   LayoutParams.MATCH_PARENT
)

val mySecretButton = Button(this)
mySecretButton.setText("My Secret Button Text")
mySecretContainer.addView(mySecretButton, layoutParams)

// Ignore all interactions with mySecretContainer, implicitly ignores
// interactions with mySecretButton
Heap.ignore(mySecretContainer)

setContentView(mySecretContainer, layoutParams)

❗️

There are certain situations in which getParent() may return null for a view. In these cases, Heap will not be able to ignore events for a View in the ignored subtree. Due to this caveat, it is a best practice for Heap.ignore() to be scoped as closely to the PII-containing view as possible.

heapDisableTextCapture

Setting heapDisableTextCapture in your Gradle plugin configuration will prevent Heap from capturing the target text of elements. By default, Heap does not capture the contents of input fields, but does capture text from other rendered page elements. For limited disabling of text capture, heapIgnore may be sufficient.

For more information on Heap's data privacy options, see How do I use Heap to comply with data privacy legislation?

Disable Tracking

Starting with version 1.9.0 of the Heap Android SDK, it is now possible to disable event tracking for individual users at initialization time and after initialization as well. To disable tracking at initialization time, include an Options object in the initialization call to Heap like so:

import com.heapanalytics.android.config.Options;

public void onCreate() {
  super.onCreate();
  Options options = new Options();
  options.disableTracking();
  Heap.init(getApplicationContext(), "YOUR_APP_ID", options);
}
import com.heapanalytics.android.config.Options

override fun onCreate() {
  super.onCreate()
  val options = Options()
  options.disableTracking()
  Heap.init(getApplicationContext(), "YOUR_APP_ID", options)
}

Tto disable (or reenable) tracking after initialization, call Heap.setTrackingEnabled(boolean) with an argument of false (or true for re-enablement).

Events are not be autocaptured while tracking is disabled. In addition, the SDKs APIs for manual tracking, user identification, and user and event property updates function as no-ops.

Disable Capture of Advertiser ID

You can use the code snippet below to prevent Heap from capturing the advertiser ID and Android ID. If you are only looking to block the advertiser ID, remove the heapCaptureAndroidId line. By default, the Android SDK does not capture the advertiser ID. The androidID is more complicated due to it depending on various factors and can be explicitly set.

android {
    ...
    defaultConfig { 
        ...
        ext {
          heapEnabled = true
          ...
          heapCaptureAndroidId = false
          heapCaptureAdvertiserId = false
        }
    }
}

Troubleshooting

Using the Heap Android SDK is designed to be effortless, but occasionally issues arise for some installations.

If you’ve run into an issue, first update the SDK by pulling down the latest version. We adhere to the SemVer specification, so MINOR versions will always maintain backwards compatibility. We recommend keeping the SDK up to date with the MINOR version at all times, and the MAJOR version, if possible.

If a version update does not address your issue, please email us at [email protected].

Performance Impact

  • Event size: There is no maximum event size on Android.
  • SDK size: The Heap Android SDKadds approximately 400 KB to app bundles.
  • Network impact: Events are batched and sent to our servers every 15 seconds (in contrast to the Heap iOS SDK, this value cannot be adjusted). If no network connection is present, events are cached locally. Data will not be sent when the app is not being used. All data are sent to heapanalytics.com. Each interaction with your app will generate an event to be sent to Heap. A typical event on Android is around 0.5 KB. There is no limit to the number of offline events that can be cached.
  • Performance: Heap adds virtually zero performance overhead. Heap will never block the UI thread, and RAM is allocated only to process events before they are persisted (or while sending them to our servers). While we do a very small amount of view traversal on the UI thread for each event to fetch the properties from the UI objects, no disk or network IO happens on the UI thread. All blocking work of persisting data and sending data to Heap is all on background threads, and is primarily waiting on disk or network IO, and has very low CPU usage.
  • Storage: The data is stored in a SQLite database until it is successfully sent. Its size is a little larger than the aggregate sizes of all the events it stores. While online, this database should stay under a few hundred KB. While offline, it will grow with the number of events stored. If we overestimate events at 1 KB each, this should be about a megabyte per 1,000 events.

Changelog

For notable updates to the Heap Android library, see the Android Changelog.