Android Custom Configuration
Using Legacy Gradle Syntax with Heap
All of our quick start examples assume that your application is using the latest Gradle syntax available in Gradle 7.0+ as the Heap Gradle Plugin only supports Android Gradle Plugin 7.2+ which requires Gradle 7.3.3 or higher. However, some applications have lengthy configuration already in place that uses the legacy Gradle syntax which is still valid in newer versions of Gradle. To setup Heap using legacy Gradle syntax, follow the steps below.
- In your project-level
build.gradle
file, add Maven Central as a repository, then add the Heap Gradle Plugin to your classpath.
buildscript {
repositories {
...
// Add Maven Central as a repository if it isn't already present.
mavenCentral()
}
dependencies {
...
// IMPORTANT: Ensure that AGP 7.2+ is used. Anything below 7.2 will not work.
classpath 'com.android.tools.build:gradle:7.2.0'
// Add the Heap Gradle Plugin to the classpath.
classpath "io.heap.gradle:heap-plugin:0.3.+"
}
}
- At the top of your app-level
build.gradle
file, apply the Heap Gradle Plugin to enable autocapture of supported UI interactions.
apply plugin: 'com.android.application'
// Apply the Heap Gradle Plugin. This MUST come after the Android application plugin.
apply plugin: 'io.heap.gradle'
Automatic Initialization of Autocapture
The simplest way to initialize Heap, as shown in all of our quick start guides, is to call Heap.startRecording
when your application launches. However, it’s also possible to enable automatic initialization of Heap using Gradle. This is useful when you have different build types and product flavors and want to customize how Heap is initialized in each of those variants.
- Wherever you call
Heap.startRecording
in your code to start tracking at app startup, remove or comment out those lines. Automatic and manual initialization are mutually exclusive, so you’ll want to ensure that there’s only a single source of initialization in your app. - In your app-level
build.gradle
file, add anext
block inside of yourdefaultConfig
to set Heap initialization properties for all variants. To enable automatic initialization, set theheapAutoInit
flag totrue
and setheapEnvId
to the string representation of your target environment ID.
android {
defaultConfig {
...
ext {
heapAutoInit = true
heapEnvId = "YOUR_ENVIRONMENT_ID"
}
}
}
android {
defaultConfig {
...
(this as ExtensionAware).extensions.extraProperties.apply {
set("heapAutoInit", true)
set("heapEnvId", "YOUR_ENVIRONMENT_ID")
}
}
}
- To customize how Heap is initialized in other build types or product flavors, such as having different environment IDs for debug or release builds, add additional
ext
blocks to the specific build types you want to customize and override the desired properties. The below example shows how to set a different environment ID for debug builds.
android {
defaultConfig {
...
// Default properties for all build types and product flavors.
ext {
heapAutoInit = true
heapEnvId = "YOUR_PRODUCTION_ENVIORNMENT_ID"
}
}
buildTypes {
debug {
// Sending all events from debug mode to a different environment ID
// heapAutoInit is still true. Pulled from defaultConfig
heapEnvId = "YOUR_DEVELOPMENT_ENVIRONMENT_ID"
}
}
}
android {
defaultConfig {
...
// Default properties for all build types and product flavors.
(this as ExtensionAware).extensions.extraProperties.apply {
set("heapAutoInit", true)
set("heapEnvId", "YOUR_PRODUCTION_ENVIORNMENT_ID")
}
}
buildTypes {
getByName("debug") {
// Sending all events from debug mode to a different environment ID
// heapAutoInit is still true. Pulled from defaultConfig
(this as ExtensionAware).extensions.extraProperties.apply {
set("heapEnvId", "YOUR_DEVELOPMENT_ENVIRONMENT_ID")
}
}
}
}
Below is a full listing of properties supported by the Heap Gradle Plugin for use in automatic initialization.
All property names are case sensitive.
Property | Type | Default | Description |
---|---|---|---|
heapAutoInit | Boolean | false | Boolean setting to enable initialization configuration at build time. If this is false , you must initialize Heap programmatically.If this is true , you must also set heapEnvId to a stringified 53-bit integer. |
heapCaptureAdvertiserId | Boolean | false | Boolean setting to enable Advertiser ID capture. |
heapDisableTextCapture | Boolean | false | Boolean setting to disable text capture on views. |
heapEnabled | Boolean | true | Boolean setting to enable build-time instrumentation for autocapture. If this is set to false , UI interactions will not be autocaptured. |
heapEnvId | String | null | The Environment ID to use for initialization configuration at build time. This setting only takes effect if heapAutoInit is set to true . It must be set to the 53-bit stringified integer Env ID that you wish to send data to.Setting heapEnvId to an invalid or empty string when heapAutoInit is set to true will result in Heap failing to initialize at run-time. Likewise, failure to set heapEnvId or setting heapEnvId to null when heapAutoInit is true will result in Heap failing to initialize at run-time. |
Disable Autocapture
If you want to use Heap, but don’t want to automatically capture user interactions, follow these steps to disable autocapture.
Option 1
The quickest way to disable autocapture without making large changes to your app is to tell the Heap Gradle Plugin to not instrument your code for autocapture.
To do this, add the following block of code to your app-level build.gradle
file:
android {
defaultConfig {
...
// Add this block. If an ext block already exists, simply add the below property.
// If the property already exists, make sure it's set to false.
ext {
heapEnabled = false
}
}
}
android {
defaultConfig {
...
// Add this block. If an ext block already exists, simply add the below property.
// If the property already exists, make sure it's set to false.
(this as ExtensionAware).extensions.extraProperties.apply {
set("heapEnabled", false)
}
}
}
Option 2
The second option is to strip out the Heap Gradle Plugin and related autocapture dependency, leaving only the Heap Android Core SDK remaining.
In the app-level build.gradle
file, remove the Heap Gradle Plugin.
plugins {
id 'com.android.application'
// Remove this line.
id 'io.heap.gradle' version '0.3.+'
}
plugins {
id("com.android.application")
// Remove this line.
id("io.heap.gradle") version "0.3.+"
}
Further down in the same file, remove the Android View Autocapture SDK and add the Android Core SDK if you haven’t already.
dependencies {
// Add this line if it doesn't exist.
implementation 'io.heap.core:heap-android-core:0.6.+'
// Remove this line.
implementation 'io.heap.autocapture:heap-autocapture-view:0.6.+'
}
dependencies {
// Add this line if it doesn't exist.
implementation("io.heap.core:heap-android-core:0.6.+")
// Remove this line.
implementation("io.heap.autocapture:heap-autocapture-view:0.6.+")
}
Be sure to clean up any references to ViewAutocaptureSDK
in your code, then sync Gradle and rebuild your project. If you’re using automatic initialization, you’ll also want to remove any Heap specific properties from your app-level build.gradle
file and be sure to add a startRecording
call into your app to enable manual event tracking with Heap.
Add Custom Object Data to Event Properties
Heap already accepts number, boolean, and string data as values for event properties, but there might be times where you want to include custom objects as property values. While all JVM objects have a toString
method, this is often used for custom logging or display purposes, which might not be the exact data that you want to track. To prevent alterations to your existing implementations, we’ve introduced a new interface, HeapProperty
, that your objects can implement to be used as event property values.
An example implementation might look something like this:
data class Book(
val title: String,
val author: String,
val year: Int
): HeapProperty {
// Existing toString implementation used for display.
override fun toString(): String {
return "$title by $author"
}
// Only tracking the book title as an event property.
override fun toHeapPropertyValue(): String {
return title
}
}
public class Book implements HeapProperty {
private String title;
private String author;
private int year;
// Existing toString implementation used for display.
@Override
public String toString() {
return title + " by " + author;
}
// Only tracking the book title as an event property.
@Override
public String toHeapPropertyValue() {
return title;
}
}
After implementing the HeapProperty
interface, objects of this class can now be passed into track
calls as a custom property value. While objects of this type can also be used with the addEventProperties
API, it’s important to note that the properties are stored as strings behind the scenes and will not update if the object is updated.
Customizing SDK Logs
Setting the Log Level
The Heap Android SDKs output logs at industry-standard log levels based on the severity and usefulness of the log message being printed. You can customize how much is logged to the console (Logcat, in this case) by setting the log level like so:
import io.heap.core.Heap
import io.heap.core.logs.LogLevel
...
Heap.setLogLevel(LogLevel.DEBUG)
import io.heap.core.Heap;
import io.heap.core.logs.LogLevel;
...
Heap.setLogLevel(LogLevel.DEBUG);
Heap can be customized to print logs at the following log levels:
LogLevel.NONE
: Heap will not print any log messages.LogLevel.ERROR
: Heap will only print the most critical log messages, such as when the SDK encounters an error and needs to shut down.LogLevel.WARN
: Heap will print warning messages for recoverable errors, such as when unexpected data types are passed into the SDK or the network is unreachable. Also includes fromERROR
logs.LogLevel.INFO
: Heap will print messages that are useful in a production environment, such as when recording starts/stops, when a batch of events is successfully sent, or when a new session has begun.
This level is recommended for production environments so that developers can see Heap lifecycle messages in their own logging environment. Also includesERROR
andWARN
logs.LogLevel.DEBUG
: Heap will print messages that the implementing developer may find helpful. Messages may include things such as invalid environment ID value, truncated event names, or attempting to track an event before recording has started.
This level is recommended for implementing developers during the development process to help with debugging normal installation and tracking issues. Also includesERROR
,WARN
, andINFO
logs.LogLevel.TRACE
: Heap will print messages that help the Heap team diagnose SDK issues. Heap support may ask the implementing developers to enable this log level to gain better insight into issues developers may have encountered when implementing the Heap SDK.
Full event details are also printed at this level.
This level is recommended when gathering information to send to Heap support personnel. Heap support may also ask that this level be turned on to help debug installation and tracking issues that require extra investigation. Also includesERROR
,WARN
,INFO
, andDEBUG
logs.
Routing Logs to Custom Destinations
In addition to customizing how much is printed by setting the log level, you can also customize where logs are printed by setting a custom log channel. By default, all logs are printed to Logcat with the same output level as the Heap log level name (the only difference being TRACE
is printed to Log.v
). If you’re using a logging library like Timber or Arbor and want to send all logs through those channels instead, simply make a new LogChannel
and pass it to Heap like so:
import io.heap.core.Heap
import io.heap.core.logs.LogChannel
import io.heap.core.logs.LogLevel
class TimberLogChannel : LogChannel {
// Only one method to override.
override fun printLog(
logLevel: LogLevel,
message: String,
source: String?,
throwable: Throwable?
) {
// Send Heap logs to different locations based on LogLevel.
when(logLevel) {
LogLevel.TRACE -> Timber.v(throwable, message)
LogLevel.DEBUG -> Timber.d(throwable, message)
LogLevel.INFO -> Timber.i(throwable, message)
LogLevel.WARN -> Timber.w(throwable, message)
LogLevel.ERROR -> Timber.e(throwable, message)
LogLevel.NONE -> {
// Print nothing.
}
}
}
}
import io.heap.core.Heap;
import io.heap.core.logs.LogChannel;
import io.heap.core.logs.LogLevel;
public class TimberLogChannel implements LogChannel {
@Override
public void printLog(
@NonNull LogLevel logLevel,
@NonNull String message,
@Nullable String source,
@Nullable Throwable throwable
) {
switch(logLevel) {
case LogLevel.TRACE: { Timber.v(throwable, message); } break;
case LogLevel.DEBUG: { Timber.d(throwable, message); } break;
case LogLevel.INFO: { Timber.i(throwable, message); } break;
case LogLevel.WARN: { Timber.w(throwable, message); } break;
case LogLevel.ERROR: { Timber.e(throwable, message); } break;
case LogLevel.NONE: { /* Print nothing. */ }
}
}
}
Capture Advertiser and Vendor ID
You are able to capture the Android advertiser ID starting in Android Core 0.1.0 simply by setting the configuration option, captureAdvertiserId
, to true. Setting this option causes Heap to attempt to retrieve the Google Play advertiser ID and send as part of event payloads.
Starting in Android Core 0.5.0, this behavior has been updated to allow selection of either the Google Play or Amazon advertiser IDs. Additionally, you are now able to capture the Android vendor ID using Google's App Set ID for apps distributed through Google Play.
To enable advertiser or vendor ID capture, first start by setting the required initialization option.
Heap.startRecording(
context,
"YOUR_APP_ID",
Options(
captureAdvertiserId = true,
captureVendorId = true
)
)
Heap.startRecording(
context,
"YOUR_APP_ID",
new Options.Builder()
.setShouldCaptureAdvertiserId(true)
.setShouldCaptureVendorId(true)
.build()
)
Next, you'll need to add an Advertiser ID Provider or Vendor ID Provider to your application. These come in the form of an additional artifact that contains all of the required code and dependencies for the given identifier that you want to capture.
dependencies {
implementation 'io.heap.core:heap-android-core:0.7.4'
// Only include one advertiser ID provider per app config. (Version should match Core)
// Advertiser ID Providers:
implementation 'io.heap.core.identifier:ad-id-google:0.7.4'
implementation 'io.heap.core.identifier:ad-id-amazon:0.7.4'
// Vendor ID Providers:
implementation 'io.heap.core.identifier:vendor-id-google:0.7.4'
}
That's it! If your setup is correct, you'll see a log message when running your app that says "Heap vendor ID provider found" or "Heap advertiser ID provider found." If you see a message that no provider was found or more than one provider was found, be sure to check that you've cleaned and rebuilt and that you've only included one advertiser or vendor ID provider per app configuration.
Overriding Target Text Capture
When Heap generates an autocapture event, the SDK uses a set of rules to determine the target text that should be associated with the event. In most cases this is either the text assigned to the UI component or the text of the closest parent or child component. However, there are some cases where you might want to have a strong guarantee that the target text for event matches a specific value. This can be useful if your interaction target is a layout or a recycled component in a list or grid. For this, you can override the target text for a view.
This functionality is available starting in version 0.7.2 of the Heap Android View Autocapture SDK.
fun setupClickableView(title: String) {
val clickTarget = findViewById<LinearLayout>(R.id.some_clickable_layout)
ViewAutocaptureSDK.overrideTargetText(clickTarget, title)
}
public void setupClickableView(String title) {
LinearLayout clickTarget = findViewById(R.id.some_clickable_layout);
ViewAutocaptureSDK.overrideTargetText(clickTarget, title);
}
Updated 3 days ago