About Jetpack Compose

About Jetpack Compose

Make sure you have installed at least the minimum LogRocket SDK version: 1.17.2. Jetpack Compose UI 1.5 support was added in LogRocket version 1.19.3. Apps using Proguard minification should use a LogRocket version of at least 1.25.0.

The LogRocket SDK will work with Jetpack Compose in the same way as the existing Android SDK outlined in these Android docs, with some limitations outlined below.

You can find an overview of Jetpack Compose on the Android developer site. Compose UI elements are not stored and rendered as standard Android views. Because of this, Jetpack Compose capture in LogRocket is a new capture system separate from Native Android View capture.

Jetpack Compose capture can be disabled by setting initialization configuration option: options.setEnableJetpackCompose(false).

Self Hosted

If your LogRocket server is self hosted, mobile SDK version 1.17.2 requires a minimum server version of 16.462.0. If your server is between versions 16.329.0 - 16.461.0, you can capture Jetpack Compose UIs with mobile SDK version 1.16.10 and setting initialization configuration option: options.setEnableJetpackCompose(true), though we recommend updating your LogRocket server and SDKs to the latest available version.

Redaction

Complete masking rules still apply, such as Automatically Sanitize Text and Sanitize Network Data.

You can redact specific Jetpack Compose elements by adding a testTag or layoutId with value"lr-hide" or another custom Redaction Tag value. See details here on how to add redaction tag objects in addition to the default "lr-hide".

Examples:

// Example 1 - use .testTag()
Text(
  text = "example",
  modifier = Modifier.testTag("lr-hide")
)


// Example 2 - set up other testTags to be redacted in your init call
SDK.init(
  ...
  options -> {
    ...
    options.addRedactionTag("MyRedactionTag");
  }
)
Text(
  text = "example",
  modifier = Modifier.testTag("MyRedactionTag")
)


// Example 3 - use .layoutId()
Text(
  text = "example",
  modifier = Modifier.layoutId("lr-hide")
)


// Example 4 - configure a class to be used for layoutId redaction in your init call
class RedactionId constructor(id: String) {
    override fun equals(other: Any?): Boolean {
        return other is RedactionId // will redact all RedactionId instances
    }
}
SDK.init(
  ...
  options -> {
    ...
    options.addRedactionTag(RedactionId(""));
  }
)
Text(
  text = "example",
  modifier = Modifier.layoutId(RedactionId("some id"))
)

AndroidView

If you need to redact any AndroidView Composables , you will need to redact the entire AndroidView, and not individual Views inside that AndroidView.

Example:

AndroidView(
  factory = { context ->
    ...
  },
  update = {
    ...
  },
  modifier = Modifier.testTag("lr-hide")
)

View Allowlisting

Individual child nodes of a redacted Jetpack Compose element can be allowed for view capture by adding a testTag or layoutId with value"lr-show" or another custom Allow Tag value. See details here on how to add allow tag objects in addition to the default "lr-hide".

Examples:

// Example 1 - use .testTag()
Column(Modifier.testTag("lr-hide")){
	Text("uncaptured text")
	Text("uncaptured text")
  Text(
    text = "captured text",
    modifier = Modifier.testTag("lr-show")
  )
}


// Example 2 - set up other testTags to be allowed in your init call
SDK.init(
  ...
  options -> {
    ...
    options.addAllowTag("MyAllowTag");
  }
)
Column(Modifier.testTag("lr-hide")){
	Text("uncaptured text")
	Text("uncaptured text")
  Text(
    text = "captured text",
    modifier = Modifier.testTag("MyAllowTag")
  )
}


// Example 3 - use .layoutId()
Column(Modifier.layoutId("lr-hide")){
	Text("uncaptured text")
	Text("uncaptured text")
  Text(
    text = "captured text",
    modifier = Modifier.layoutId("lr-show")
  )
}


// Example 4 - configure a class to be used for layoutId redaction in your init call
class RedactionId constructor(id: String) {
    override fun equals(other: Any?): Boolean {
        return other is RedactionId // will redact all RedactionId instances
    }
}
SDK.init(
  ...
  options -> {
    ...
    options.addAllowTag(AllowId(""));
  }
)

Column(Modifier.testTag("lr-hide")){
	Text("uncaptured text")
	Text("uncaptured text")
  Text(
    text = "captured text",
	  modifier = Modifier.layoutId(RedactionId("some id"))
  )
}

AndroidView

The same restriction applies for allowlisting AndroidView Composables as for redacting them , you will need to either allow or redact the entire AndroidView, and not individual Views inside that AndroidView.

Navigation

As with our prior Android Native SDK, Jetpack Compose screens may not be meaningful on their own. As such, we recommend using the Manual Page Identification API to best track navigation events.

Selectors

A full description of LogRocket Selectors and how to use them in the dashboard can be found here .

Jetpack Compose views are rendered in 3 phases. The Layout phase defines where UI elements are placed on the screen. When users interact with an element on screen, they are interacting with a node in the Layout Tree. The LogRocket SDK defines Selectors based on the node types and modifiers in the Layout Tree.

ComponentValueNote
NodeNameClass name of the Layout node's measure policy
.testTagValue provided in .testTag() ModifierObject values are converted to String by calling .toString()
#idValue provided in .layoutId() ModiferObject values are converted to String by calling .toString()

Example:

// This Compose element can be referenced in LogRocket with selector:
//   TextController.HeaderText#abc123
Text(
  text = "My App",
  modifier = Modifier.testTag("HeaderText").layoutId("abc123")
)

Touch Events

The SDK will capture touch events with the text and selector that was touched. Any touch on an AndroidView Composable will appear as a click on the entire AndroidView, and not the individual View inside that AndroidView. Touch HeatMap support was added in SDK version 1.17.1.