Improving Android autocapture

The Android View Autocapture SDK is Heap's solution for automatically capturing user interactions in Android apps built with the native Android View framework. This autocapture experience is accomplished using the Heap Gradle Plugin to instrument your app's code with direct calls into Heap's SDK. Those calls collect information about the interaction, create an event, and send it to Heap without any additional code necessary.

When instrumenting your code, Heap attempts to piggyback on specific listeners and callback methods that provide the basis for an interaction. In other cases, Heap attempts to attach its own listeners to views to listen for interactions. This means that, in some cases, if a listener isn't attached to a view, then the interaction cannot be captured automatically.

For example, consider this simple form layout (layout properties omitted for brevity):

<LinearLayout>
  <EditText android:id="@+id/edit_first_name" />
  <EditText android:id="@+id/edit_last_name" />
  <CheckBox android:id="@+id/checkbox_accept_terms" />
  <Button android:id="@+id/button_submit" />
</LinearLayout>

In code, we might hook up this simple layout like so:

class MainActivity : AppCompatActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    
    // Attach a listener to the button.
    findViewById<Button>(R.id.button_submit).setOnClickListener {
      // Handle submit and perform form validation.
    }
  }
}
public class MainActivity extends AppCompatActivity {
	@Override protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    
    // Attach a listener to the button.
    findViewById(R.id.button_submit).setOnClickListener(view -> {
      // Handle submit and perform form validation.
    });
  }
}

In the above example, Heap is able to autocapture all clicks on the submit button by instrumenting the OnClickListener attached to the button. However, any changes made in the edit fields aren't captured and changes to the check box state are also not captured. The reason being, those views don't have a listener attached to them, so there's nowhere for Heap to piggyback on the interaction.

If you want to capture interactions for a view, and aren't seeing them automatically captured by Heap, in most cases you can just add a listener.

Below is a table of the types of interactions that we capture, the view types that support those interactions, and any listeners that must be set to the view in order for Heap to capture an interaction. You can use this table of views and listeners to enhance your data capture experience.

InteractionSupported TypesRequired Listener
View ClickAll subclasses of View.View.OnClickListener must be set to the target view.
In-Text Link ClickTextView and its subclasses.In-text link must be generated using a ClickableSpan that overrides the onClick method.
Dialog Button ClickAll dialog types that implement DialogInterface (e.g. AlertDialog).DialogInterface.OnClickListener must be set to the target dialog button.
Dialog List Item ClickPlatform native and AndroidX implementations of AlertDialog.Must attach a DialogInterface.OnClickListener to the target dialog's list using AlertDialog.Builder.setItems().
List Item ClickAll subclasses of AdapterView.AdapterView.OnItemClickListener must be set to the target list.
Spinner Item SelectedAll subclasses of AdapterView, but works best with Spinner and its subclasses.AdapterView.OnItemSelectedListener must be set to the target view.
Toggle Control Value ChangedAll subclasses of CompoundButton (e.g. ToggleButton, CheckBox, Switch) except RadioButton.CompoundButton.OnCheckedChangeListener must be set to the target view.
Radio Group Value ChangedRadioGroup and its subclasses.RadioGroup.OnCheckedChangeListener must be set to the target view.
Text Input Value ChangedEditText and its subclasses.TextWatcher must be set to the input field using TextView.addTextChangedListener().
Date Value ChangedDatePickerDialogDatePickerDialog.OnDateSetListener must be set to the target dialog.
Time Value ChangedTimePickerDialogTimePickerDialog.OnTimeSetListener must be set to the target dialog.
SeekBar Value ChangedSeekBarSeekBar.OnSeekBarChangeListener must e set to the target view.
Slider Value ChangedMaterial component library implementations of Slider and RangeSlider.No required listeners needed for value change capture. Heap will attach its own listener.

It's important to note that Heap will make a best effort attempt to differentiate between user driven interactions and programmatic interactions. For instance, if the user clicks on a CheckBox to change its value and there's a listener attached, Heap will capture that interaction. However, if you change the checked value of a CheckBox using the setChecked method in code, Heap will attempt to ignore that interaction as it isn't indicative of user behavior, even though it might be the side effect of another user interaction. This is true of all interaction events that are designated as a "Changed" event in the above table.