Navigation

Learn more about the Sentry Navigation integration for the Android SDK.

The sentry-android-navigation library provides AndroidX Navigation support for Sentry using the SentryNavigationListener. The source can be found on GitHub.

On this page, we get you up and running with Sentry's Navigation Integration, so that it will automatically add a breadcrumb and start a transaction for each navigation event.

Sentry captures data by adding a NavController.OnDestinationChangedListener. To add the Navigation integration, install the Android SDK, then add the sentry-android-navigation dependency using Gradle:

Copied
implementation 'io.sentry:sentry-android:7.19.1'
implementation 'io.sentry:sentry-android-navigation:7.19.1'

Configuration should happen in the respective lifecycle callbacks, once you retrieve your NavController instance:

Copied
import androidx.navigation.NavController
import io.sentry.android.navigation.SentryNavigationListener

private val navController = findNavController(R.id.nav_host)
private val sentryNavListener = SentryNavigationListener(
  enableNavigationBreadcrumbs = true, // enabled by default
  enableNavigationTracing = true  // enabled by default
)

override fun onResume() {
  super.onResume()
  navController.addOnDestinationChangedListener(sentryNavListener)
}

override fun onPause() {
  super.onPause()
  navController.removeOnDestinationChangedListener(sentryNavListener)
}

By default, the navigation transaction finishes automatically after it reaches the specified idleTimeout and all of its child spans are finished. You can customize the timeout to your needs.

This snippet includes a sample Fragment with a couple of navigation events and captures an intentional message, so you can test that everything is working as soon as you set it up:

Copied
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.navigation.NavController
import io.sentry.android.navigation.SentryNavigationListener
import io.sentry.Sentry

class HomeFragment : Fragment() {

  private val sentryNavListener = SentryNavigationListener()

  override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
  ): View {
    // generated databinding
    return FragmentHomeBinding.inflate(inflater).apply {
        this.sendMessage.setOnClickListener {
            Sentry.captureMessage("Some message.")
        }
        this.openFirstFragment.setOnClickListener {
          findNavController().navigate(R.id.fragment_a)
        }
        this.openSecondFragment.setOnClickListener {
          findNavController().navigate(R.id.fragment_b)
        }
    }.root
  }

  override fun onResume() {
    super.onResume()
    findNavController().addOnDestinationChangedListener(sentryNavListener)
  }

  override fun onPause() {
    super.onPause()
    findNavController().removeOnDestinationChangedListener(sentryNavListener)
  }
}

By default, the Navigation integration captures route arguments as additional data on breadcrumbs and transactions. In case the arguments contain any PII data, you can strip it out by way of BeforeBreadcrumbCallback and EventProcessor respectively. To do that, manually initialize the SDK and add the following snippet:

Copied
import io.sentry.EventProcessor
import io.sentry.android.core.SentryAndroid
import io.sentry.SentryOptions.BeforeBreadcrumbCallback
import io.sentry.android.navigation.SentryNavigationListener

SentryAndroid.init(this) { options ->
  options.beforeBreadcrumb = BeforeBreadcrumbCallback { breadcrumb, hint ->
    if (SentryNavigationListener.NAVIGATION_OP == breadcrumb.category) {
      breadcrumb.data.remove("from_arguments")
      breadcrumb.data.remove("to_arguments")
    }
    breadcrumb
  }
  options.addEventProcessor(object : EventProcessor {
    override fun process(transaction: SentryTransaction, hint: Hint): SentryTransaction? {
      if (SentryNavigationListener.NAVIGATION_OP == transaction.contexts.trace.operation) {
        transaction.removeExtra("arguments")
      }
      return transaction
    }
  })
}
Help improve this content
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").