Update your app to support future predictive back gesture

1. Introduction

Last Updated: 2022-04-11

In Android 13, we've added APIs that serve as the foundation of upcoming support for a predictive back gesture.

This feature will let a user preview the result of a Back gesture before they fully complete it – basically allowing them to decide whether to stay in the current view or complete the action and return to the Home screen, a previous activity, or a previously visited page in a WebView. Here's an example of what that's going to look like:

This animation shows an approximation of a future implementation\n            of what it looks like for a user to open the Chrome browser,\n            view the Chrome browser on an Android mobile device, then swipe\n            back to see the Home screen as the next destination displayed\n            behind it.

In the case of this codelab, we're going to fix a survey fragment that implements a WebView.

Goal of this codelab

This codelab shows you how to prepare an AndroidX app that intercepts system Back by migrating it to support predictive back gesture with a WebView, by using the APIs that implement the ahead-of-time back navigation model. In other words, for the new animations to work, the system needs to know ahead of time if the app is intercepting the back navigation gesture.

What you'll build

In this codelab, you'll use AndroidX API libraries to handle Back gestures in the Sunflower app.

What you'll learn

  • How to intercept the on-back invocation for AndroidX
  • How to return the Back event to the system
  • Other options for handling Back gestures
  • The new user experience coming in Android 13+ providing a more predictive back gesture navigation

What you'll need

2. Plan support for predictive back gesture

Use AndroidX APIs to implement this feature

This codelab is designed for apps that already use AndroidX.

You'll be implementing OnBackPressedDispatcher and OnBackPressedCallback to support Back navigation.

Other options

We've got other options for handling this feature, depending on different needs your app may have:

  • For apps unable to use AndroidX - If this is you, we've got you covered. Use the new OnBackInvokedDispatcher and OnBackInvokedCallback platform classes we're introducing in Android 13, which enable you to use the ahead-of-time APIs without requiring AndroidX. See the documentation for details.
  • For apps temporarily unable to migrate - If this is you, we've also got you covered! You can opt out from the predictive back gesture if it's not possible to migrate to either the AndroidX libraries or the platform APIs at this time. See the documentation for details.

3. Before you begin

Install Android Studio

Install Android Studio and the Android 13 SDK.

Obtain a device

You can use a virtual or physical Android device to run the app you build using this codelab.

Enable gesture navigation

If you run a new emulator instance with API level 29, Gesture Navigation might not be turned on by default. To enable gesture navigation, select System settings > System > System Navigation > Gesture Navigation.

Get the code

Get the code in one of the following ways:

Download the zip

Download via Git

If you'd prefer to download the code using Git, follow these steps:

  1. Install Git.
  2. Clone starter-code or main branch to get the app for this exercise:

Terminal

// Get starter app.
git clone --branch starter-code \
https://github.com/googlecodelabs/handling-back-navigation.git

Run the app

Complete the following steps:

  1. Open and build the app in Android Studio.
  2. Create a new virtual device, and select Tiramisu. Alternatively, you can connect a physical device that runs API level 33 or higher. info-avocado.png
  3. Run the Sunflower app.

info-avocado.png

Next you'll establish a baseline and walk through a poor experience that is part of the Sunflower app.

4. Establish a baseline

Our starting point is the Sunflower app, which includes a survey presented in a WebView that handles Back gestures poorly. When a user swipes from the left or right edge to go back in the WebView, the app returns them to a previous fragment instead of going back to the previous page, causing them to lose any unsubmitted data.

Explore the demo

Starting from the main screen, let's walk through main workflow of your app to review the poor experience with the WebView functionality.

  1. In the default screen of the Sunflower app, tap PLANT LIST.

info-avocado.png

  1. In the plant catalog, tap any plant. (For this example, we'll use the avocado fruit.)

plant-catalog.png

  1. In the info screen for the plant you tapped, tap the thumbs-up icon (in the top right corner) to rate the plant.

info-avocado.png

  1. Start filling out the survey, but stop when you get to Question #3.

survey-page-1.png

survey-page-2.png

survey-page-3.png

  1. Swipe inward from the left (or the right) edge of the screen to use the Back gesture. Note that, instead of taking you to Question #2 in the survey, swiping Back takes you to the plant detail fragment (in this example, the Avocado information page). This causes you to lose your answers, and makes for a poor user experience.

sunflower-back-nav-returns-to-the-plant-detail.gif

Let's now jump in to start to fix these issues!

5. Enable the predictive back gesture

Our app already uses AndroidX, so you'll use the Back navigation APIs. These already support the ahead-of-time model.

Target Android 13

In our app's Studio project, update the app's build configuration to target Android 13, as shown in the following code snippet.

build.gradle (Project)

buildscript {
   ext {
       // Sdk and tools
       minSdkVersion = 29
       compileSdkPreview = "Tiramisu"
       targetSdkPreview = "Tiramisu"

...
}

Include the AndroidX 1.6.0-alpha03 dependency

In build.gradle, set appCompatVersion to 1.6.0-alpha03.

build.gradle (Project)

buildscript {
   ext {

       // App dependencies
       appCompatVersion = '1.6.0-alpha03' // Built original with changes

...
}

Enable the predictive back gesture

To enable the predictive back gesture APIs, set enableOnBackInvokedCallback to true in the manifest.

AndroidManifest.xml

<application
   ...
   android:enableOnBackInvokedCallback="true" // Enables this feature.
   ... >
...
</application>

Declare and register OnBackPressedCallback to handle Back gestures

Create the callback and override the handleOnBackPressed method to handle Back gestures. For the WebView use case, let's use the Back gesture to go back in the page stack until there are no more pages.

SurveyFragment.kt

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
...
val onBackPressedCallback = object: OnBackPressedCallback(true) {
  override fun handleOnBackPressed() {
    when {
      webView.canGoBack() -> webView.goBack()
      }
    }
  }
  requireActivity().onBackPressedDispatcher
    .addCallback(onBackPressedCallback)
...
}

Try out what you've built

Now you're going to test that the WebView navigation works properly.

  1. In Android Studio, build and run the app again.
  2. Just as you did when you first ran the demo, tap a plant of your choice and then tap the thumbs-up icon, then fill out the survey until you reach Question #3.
  3. Swipe inward from the left (or right) edge of the screen to use the Back gesture. The WebView should return you to Question #2 in the survey.

This is the exact behavior we want. However, we're only halfway there—it's still not completely fixed yet. Let's continue to see what we mean:

  1. From Question #2, swipe back to Question #1, then swipe back once more in an attempt to return to the plant detail fragment.

sunflower-back-nav-stuck-survey.gif

Notice that you can't go back from Question #1 to the plant detail fragment. This is because:

  • Your WebView handles Back navigation by avoiding leaving the WebView when using on-Back navigation.
  • Your app needs to return the Back navigation to the system once it no longer needs it. Let's go to the next section to fix that!

6. Fix the Back gesture

In the previous step, our app intercepted the Back gesture without returning it to the plant detail fragment in the previous steps. As a result, our users cannot leave the app and are stuck in the WebView with a poor user experience.

Enable or disable Back navigation with OnBackPressedCallback

  1. Override the doUpdateVisitedHistory method to determine if the Back navigation should be intercepted. The logic to handle Back navigation is the following:
    • If there are more pages to go back to in the WebView (webView.canGoBack()), OnBackPressedCallback method should be enabled.
    • Conversely, if there are no more pages to go back to in the WebView, the OnBackPressedCallback method should be disabled. As a result, the Back gesture will go back to the topmost fragment in the back stack.

SurveyFragment.kt

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
  ...
  // Present the HTML form to the user.
  webView.loadUrl("https://atom-summer-cadet.glitch.me/")
  webView.settings.javaScriptEnabled = true
  webView.addJavascriptInterface(WebAppInterface(requireContext()), "Android")

  ...
  requireActivity().onBackPressedDispatcher
    .addCallback(onBackPressedCallback)

  disableOnBackPressedCallback(webView, onBackPressedCallback)
}
...

private fun disableOnBackPressedCallback(webView: WebView, onBackPressedCallback: OnBackPressedCallback) {
  webView.webViewClient = object: WebViewClient() {
    override fun doUpdateVisitedHistory(view: WebView?, url: String?, isReload: Boolean) {
      // Disable the on-back press callback if there are no more questions in the
      // WebView to go back to, allowing us to exit the WebView and go back to
      // the fragment.
      onBackPressedCallback.isEnabled = webView.canGoBack()

      }
    }
  }
  1. To test the WebView again, fill out the survey once again until you reach Question #3.
  2. Using Back gestures, navigate all the way back to the plant detail view. You should be able to do this without a problem.

Here's an example of how all this should look after you've fixed it:

sunflower-back-nav-fixed.gif

7. Congratulations

Congratulations! You covered a lot of content. We hope you've got a better understanding of the options and APIs to start updating your app toward the predictive back gesture offered in Android.

What this will look like in future versions of Android

In upcoming versions of Android, you'll start experiencing the predictive back gesture, as shown in the following animation. We strongly recommend that you start implementing these changes as soon as possible!

animation.gif

What we've covered

  • How to enable your app to start using the APIs that support the predictive back gesture
  • How to intercept on-back invocation for AndroidX
  • How to return the Back navigation to the system
  • Other options to handle Back gestures
  • The new UX experience coming in Android 13, providing a more predictive back gesture

Completed codelab

// Get completed app.
git clone --branch main \
https://github.com/googlecodelabs/handling-back-navigation.git

Additional materials

Reference docs