Who can use this feature?
- Available with Mobile add-on.
- Available for admins, architects, and standard users.
Integrating Fullstory’s Jetpack Compose support has a few extra steps after integrating our main SDK into your app. Before you begin, follow the setup process described in our Getting Started with Android Capture article.
Fullstory Jetpack Compose support was added in Fullstory for Mobile Apps 1.43.0
.
Minimum Jetpack Compose version |
|
Maximum Jetpack Compose version |
Added in Fullstory for Mobile Apps |
After implementing the instructions from the article mentioned above, proceed with the steps below:
- Enable Jetpack Compose support in your app’s fullstory gradle config. You need to explicitly enable Jetpack Compose support in your application because there are some key differences between Fullstory for Jetpack Compose and Classic Android that you should be aware of.
- Choose a selector version in your app’s fullstory config. Doing so ensures that future versions of the Fullstory plugin do not change the behavior of your privacy rules.
-
Use
Modifier.fsMask()
,Modifier.fsUnmask()
, andModifier.fsExclude()
as appropriate, on Jetpack Compose Composables to implement your code-first privacy rules. Although privacy rules work on classes, it may be preferable to directly apply masking rules to Composable objects in this version of the Fullstory plugin to ensure that changes in Jetpack Compose keep your application private. -
Use
Modifier.fsAddClass(String)
or otherModifier
helper methods on Composables to provide semantic information on elements that you might want to add selector-based privacy rules to or search for in the future. Fullstory for Jetpack Compose requires that you tag views directly in code that you might later interact with in the Fullstory web interface.
Enabling Jetpack Compose Support
Follow the same Getting Started with Android Capture help documentation for standard Android integration.
Once that is complete, enable Jetpack Compose support by setting composeEnabled
to true
in the fullstory
properties block (the same block where the org id is set) of the App’s build.gradle
file. You should also set composeSelectorVersion
to 5 (explained below)
fullstory {
orgId ...
...
composeEnabled true
composeSelectorVersion 4
}
Using Jetpack Compose in Library Modules
Follow the instructions for Using Fullstory in Library Modules with an additional dependency for the Fullstory compose AAR.
dependencies {
...
implementation 'com.fullstory:compose:<PLUGIN VERSION>@aar'
}
Differences Between Classic Android and Jetpack Compose
Fullstory for Jetpack Compose supports Private by Default.
Fullstory for Jetpack Compose supports session replay Fullcapture with Private by Default, just like Fullstory for Classic Android. All Jetpack Compose UI elements will be masked by default, captured automatically, and visible in playback without any manual instrumentation. But there are a few key differences you should be aware of.
Fullstory for Jetpack Compose only supports manual attributes set in code.
The main difference between Fullstory’s Classic Android and Jetpack Compose implementation is that in order to unmask or exclude views, our current support for Jetpack Compose requires developers to take a code-first approach and to attribute views with Modifier.fsAddClass(String)
or other Modifier
helper methods. These helper methods can set privacy rules directly (i.e., Modifier.fsUnmask()
) or add to selector annotations for selector-based rules (i.e., Modifier.setAttribute(String, String)
).
@Composable
fun Counter (count: Int, updateCount: (Int) -> Unit) {
Button(
modifier = Modifier.fsUnmask()
onClick = { updateCount (count + 1) },
colors = ButtonDefaults.buttonColors (
backgroundColor = if (count > 5) Color. Green else Color.White
)
) {
Text("I've been clicked $count times")
}
}
Tap/Click Events
Jetpack Compose support captures most click events on views, similar to the Classic Android SDK. However, some click events, like those generated from a PressInteraction
, are not currently captured. You will still see where the end-user is tapping on the screen (small blue dot), but the Jetpack Compose support does not currently support surfacing every possible click event.
Selectors
Selectors need to be added to all Composables that you wish to build usage analytics for.
Adding consistent and quality automatic selectors is not currently supported. However, if you want to search for if a user tapped on a Button
or other element, you need to add selector information to that Composable using any of Modifier.fsAddClass(String)
, Modifier.fsTag(String)
, Modifier.fsId(String)
, or Modifier.fsAttribute(String, String)
. You can then use the coded values in searches, build metrics based on element usage, configure watched elements and use all the tools Fullstory provides with the selector that you configure.
Note that in order to use manually configured selectors, you need to set composeSelectorVersion
to at least version 1
. While we strive to always preserve backwards compatibility, we may need to change how selectors are computed or matched that might not be possible to do without some breaking changes. Those changes will be guarded by a new composeSelectorVersion
which will guarantee that your app’s rules and analytics won’t change until you opt-in to that new version.
Manual selectors can be enabled by setting composeSelectorVersion
to a number greater than 0
in the fullstory
grade properties (where you set the org id). Setting this to a number greater than 0
will enable selectors to be shown that are manually annotated (via Modifier.fsAddClass(String)
and our other API methods that are invoked on a Modifier
in Jetpack Compose). More information on valid composeSelectorVersion
values, as well as what is captured, can be found in the Selector Versioning section below.
Selector Versioning
composeSelectorVersion value | Selector Information in Playback |
---|---|
0 | All selectors other than androidcomposeview are omitted. |
1 |
Only Composables manually-annotated by the |
2 |
New Feature: Support for adding automatically generated Bug Fix: Composables annotated with |
3 |
New Feature: Automatically generated New Feature: Support for capturing of unmasked text on Composables. Search for and filter elements by text. |
4 |
Breaking change: The New Feature: Propagate |
5 | New Feature: Support for adding automatically generated layout-id attributes on Composables. |
Modifier Helper Methods
Manual annotation of Composables
that will show up in selectors on playback are achieved through Fullstory-specific helper methods on androidx.compose.ui.Modifier.
Manual Selector Annotation Methods
Modifier Method | Description | View Method Analogue |
---|---|---|
Modifier.fsAttribute(name: String, value: String) | Adds an attribute to the selector with the given name value pair. | https://developer.fullstory.com/mobile/android/auto-capture/set-attribute/ |
Modifier.fsAddClass(cls: String) | Adds the specified class to the selector | https://developer.fullstory.com/mobile/android/auto-capture/add-class/ |
Modifier.fsId(id: String) | Adds an id to the specified selector, similar to setting an Android layout XML id | N/A |
Modifier.fsTag(tag: String) | Sets a tag attribute of the selector | https://developer.fullstory.com/mobile/android/auto-capture/set-tag-name/ |
Privacy Rule Convenience Methods
Modifier Method | Description |
---|---|
Modifier.fsExclude() | Equivalent to invoking Modifier.fsAddClass("fs-exclude") |
Modifier.fsMask() | Equivalent to invoking Modifier.fsAddClass("fs-mask") |
Modifier.fsUnmask() | Equivalent to invoking Modifier.fsAddClass("fs-unmask") |
Modifier.fsExcludeWithoutConsent() | Equivalent to invoking Modifier.fsAddClass("fs-exclude-without-consent") |
Modifier.fsMaskWithoutConsent() | Equivalent to invoking Modifier.fsAddClass("fs-mask-without-consent") |
Modifier.fsUnmaskWithConsent() | Equivalent to invoking Modifier.fsAddClass("fs-unmask-with-consent") |
Known Issues
- Some list views (like
LazyList
) are drawn incorrectly during playback when using Jetpack Compose <1.1.0
. - Fully transparent views are drawn (without transparency) during playback when using Jetpack Compose <
1.1.0
. - Some transparent elements will not draw correctly during playback.
- We have observed occasional performance impact in some cases while scrolling.
- Some controls (like
NavigationBarItem
) will not capture the icon properly and will show up as an X during replay.
Note: Transitioning from the Jetpack Compose Early Access program
For customers that previously were part of Fullstory Jetpack Compose Early Access program in a build prior to Fullstory for Mobile Apps 1.39.0, an important behavior change occurred.
Please see this article for more information.