Android Developers Blog
The latest Android and Google Play news for app and game developers.
🔍
Platform Android Studio Google Play Jetpack Kotlin Docs News

22 Ekim 2025

Bringing Androidify to XR with the Jetpack XR SDK


Link copied to clipboard
Posted by Dereck Bridie, Developer Relations Engineer
Samsung Galaxy XR is here, powered by Android XR! This blog post is part of our Android XR Spotlight Week, where we provide resources—blog posts, videos, sample code, and more—all designed to help you learn, build, and prepare your apps for Android XR.







With the launch of Samsung Galaxy XR, the first device powered by Android XR is officially here. People can now enjoy many of their favorite apps from the Play Store in a whole new dimension: the third dimension!


The third dimension is a spacious one, with plenty of room for your apps too. Get started today using whichever tools work for your app. For example, you can use the Jetpack XR SDK to build immersive XR experiences using modern Android development tools such as Kotlin and Compose.


In this blog post, we’ll tell you about our own journey as we brought the whimsy of our beloved Androidify app to XR, and we'll cover the basics of what it takes to bring your apps to XR too.


A tour through Androidify

Androidify is an open source app that lets you create Android bots, using some of the latest technologies like Gemini, CameraX, Navigation 3, and of course, Jetpack Compose. Androidify was initially designed to look great on phones, foldables, and tablets by creating adaptive layouts.


 


Androidify looks great across multiple form factors


A key pillar of adaptive layouts is reusable composables. Jetpack Compose helps you create bite-sized UI components that can be laid out in different ways to create intuitive user experiences, no matter what type of device the user is on. In fact, Androidify is compatible with Android XR with zero modifications to the app!



Androidify adapts to XR using its large-screen-responsive layout with no code changes


Apps that have no special handling for Android XR can be multi-tasked in an appropriately sized window and work much like they would on a large screen. Because of this, Androidify is already fully featured on Android XR with no additional work! But we didn't want to stop there, so we decided to go the extra mile and create an XR-differentiated app to bring a delightful experience to our XR users.


Orienting yourself in XR

Let’s go over key basic concepts for Android XR, starting with the two modes apps can be run in: Home Space and Full Space.


Apps in Home Space (left) and an app in Full Space (right)


In Home Space, multiple apps can be run side-by-side so users can multitask across different windows. In that sense, it’s a lot like desktop windowing on a large screen Android device, but in virtual space!

 
In Full Space, the app has no space boundaries and can make use of Android XR’s full spatial features, like spatial UI and controlling the virtual environment.


While it might seem tempting to make your app run only in Full Space, your users might want to multi-task with your app, so supporting both promotes a better user experience.


Designing for Androidify’s new dimension

A delightful app starts with a great design. Ivy Knight, Senior Design Advocate on Android DevRel, took on the task of taking existing designs for Androidify and coming up with a new design for XR. Take it away, Ivy!


Designing for XR required a unique approach, but actually still had a lot in common with mobile design. We started by thinking about containment: how to organize and group our UI elements in subspace, either by clearly showing boundaries or by subtly implying them. We also learned to embrace all the various sizes of spatial UI elements, which are meant to adjust and move in response to the user. As we did with Androidify, build with adaptive layouts, so you can break your layouts down into parts for your spatial UI.


Starting the design with Home Space


Luckily, Android XR lets you start with your app as it is today for Home Space, so we could transition to the expanded XR designs by just adding a window toolbar and Full Space transition button.


We also considered possible hardware features and how the user would interact with them. The mobile layouts for Androidify adapt across various postures, class sizes, and the number of cameras to give more photo options. Following this model, we had to adapt the camera layout for headset devices as well. We also needed to make adjustments for text to work to account for the proximity of the UI to the user.


Designing for the bigger shift to Full Space


Full Space was the biggest shift, but gave us the most creative room to adapt our design. 





From tablet to XR



Androidify uses visual containment, or panes, to group features with a background and outline, like the "Take or choose a photo" pane. We also used components like the top app bar to create natural containment by framing the other panes. Finally, intrinsic containment is suggested by the proximity of certain elements to others, such as the "Start transformation" bottom button, which is near the "Choose my bot color" pane.


Spatial panels made for easy separation. To decide how to adapt your mobile designs for spatial panels, try removing surfaces starting with the surface that is the furthest back and then moving forward. See how many backgrounds you can remove and what remains. After we did this exercise for Androidify, the large green Android squiggle was what remained. The squiggle not only acted as a branding moment and background, but an anchor for the content in 3D space.


Establishing this anchor both made it easier to imagine how elements could move around it, and how we could use proximity to break out and translate the rest of the user experience.


Other design tips for helping your app get spatial


  • Let things be uncontained: Break out components and give them some real (spatial) space. It's time to give those UI elements some breathing space.

  • Remove surfaces: Hide the background, see what that does to your designs.

  • Motivate with motion: How are you using transitions in your app? Use that character to imagine your app breaking out into VR. 

  • Choose an anchor: Don’t lose your users in the space. Have an element that helps collect or ground the UI.


For more about XR UI design patterns, check out Design for Android XR on Android Developers.


Spatial UI basics


Now that we've covered Ivy's experience adapting her mindset while designing Androidify for XR, let's talk about developing spatial UI. Developing a spatial UI with the Jetpack XR SDK should seem familiar if you’re used to working with modern Android tools and libraries. You’ll find concepts you’re already familiar with, like creating layouts with Compose. In fact, spatial layouts are really similar to 2D layouts using rows, columns, and spacers:



These elements are arranged in SpatialRows and SpatialColumns


The spatial elements shown here are SpatialPanel composables, which let you display 2D content like text, buttons, and videos.

Subspace {

    SpatialPanel(

        SubspaceModifier

            .height(824.dp)

            .width(1400.dp)

    ) {

        Text("I'm a panel!")

    }

}


A SpatialPanel is a subspace composable. Subspace composables must be contained within a Subspace, and are modified by SubspaceModifier objects. Subspaces can be placed anywhere within your app’s UI hierarchy, and can only contain Subspace composables. SubspaceModifier objects are also really similar to Modifier objects: they control parameters like sizing and positioning.


An Orbiter can be attached to a SpatialPanel and move along with the content it’s attached to. They’re often used to provide contextual controls about the content they’re attached to, giving the content the primary focus. They can be placed at any of the four sides of the content, at a configurable distance.



An Orbiter is attached to the bottom of a SpatialPanel


There are many more spatial UI elements, but these are the main ones we used to create spatial layouts for Androidify.


Getting started with XR development

Let’s start with the project setup. We added the Jetpack XR Compose dependency, which you can find on the Jetpack XR dependencies page.


We added code for a button that transitions the user into Full Space, starting with detecting the capability to do so:


@Composable

fun couldRequestFullSpace(): Boolean =

   LocalSpatialConfiguration.current.hasXrSpatialFeature && 

   !LocalSpatialCapabilities.current.isSpatialUiEnabled

}


Then, we made a new button component that uses the Expand Content icon to our existing layouts, and gave it an onClick behavior:


@Composable

fun RequestFullSpaceIconButton() {

   if (!couldRequestFullSpace()) return

   val session = LocalSession.current ?: return


   IconButton(

       onClick = {

           session.scene.requestFullSpaceMode()

       },

   ) {

       Icon(

           imageVector =  

               vectorResource(R.drawable.expand_content_24px),

           contentDescription = 

               stringResource("To Full Space"),

       )

   }

}


Now, clicking that button just shows the Medium layout in Full Space. We can check the spatial capabilities and determine if spatial UI can be displayed – in that case, we’ll show our new spatial layout instead:


@Composable

fun HomeScreenContents(layoutType: HomeScreenLayoutType) {

   val layoutType = when {

      LocalSpatialCapabilities.current.isSpatialUiEnabled -> 

          HomeScreenLayoutType.Spatial

      isAtLeastMedium() -> HomeScreenLayoutType.Medium

      else -> HomeScreenLayoutType.Compact

   }


   when (layoutType) {

      HomeScreenLayoutType.Compact ->

          HomeScreenCompactPager(...)


      HomeScreenLayoutType.Medium ->

          HomeScreenMediumContents(...)

       

      HomeScreenLayoutType.Spatial ->

          HomeScreenContentsSpatial(...)

   }

}


Implementing the design for the Home Screen

Let’s go back to the spatial design for the Home Screen in Full Space to understand how it was implemented.




We identified two SpatialPanel elements here: one panel that the video card is in on the right, and one that contains the main UI. Finally, there’s an Orbiter attached to the top. Let’s start with the video player panel:


@Composable

fun HomeScreenContentsSpatial(...) {

   Subspace {

      SpatialPanel(SubspaceModifier

                   .fillMaxWidth(0.2f)

                   .fillMaxHeight(0.8f)

                   .aspectRatio(0.77f)

                   .rotate(0f, 0f, 5f),

      ) {

          VideoPlayer(videoLink)

      }

   }

}


We simply reused the 2D VideoPlayer component from the regular layouts into a SpatialPanel with no additional changes! Here’s what it looks like standalone:



The main content panel followed the same story: we reused medium panel content in a SpatialPanel.

SpatialPanel(SubspaceModifier.fillMaxSize(),

             resizePolicy = ResizePolicy(

                 shouldMaintainAspectRatio = true

             ),

             dragPolicy = MovePolicy()
) {

    Box {

        FillBackground(R.drawable.squiggle_full)

        HomeScreenSpatialMainContent(...)

    }

}


We gave this panel a ResizePolicy, which gives the panel some handles near the edges that let the user resize the panel. It also has a MovePolicy, which lets the user drag it around.



Placing them in the same Subspace makes them independent of each other, so we made the VideoPlayer panel a child of the main content panel. This makes the VideoPlayer panel move when the main content panel is dragged through a parent-child relationship.


@Composable

fun HomeScreenContentsSpatial(...) {

   Subspace {

       SpatialPanel(SubspaceModifier..., resizePolicy, dragPolicy) {

           Box {

               FillBackground(R.drawable.squiggle_full)

               HomeScreenSpatialMainContent(...)

           }

           Subspace {

              SpatialPanel(SubspaceModifier...) {

                  VideoPlayer(videoLink)

              }

           }

       }

   }

}


That’s how we did the first screen!


Moving on to the other screens

I’ll go over some of the other screens briefly too, highlighting specific considerations made for each one.

The creation screen in Full Space


Here, we used SpatialRow and SpatialColumn composables to create a layout that fits the recommended viewing space, again reusing components from the Medium layout.



Results Screen in Full Space: A bot generated with a prompt: red baseball cap, aviator sunglasses, a light blue t-shirt, red and white checkered shorts, green flip flops, and is holding a tennis racket.


The results screen shows the complimentary quotes using a feathering effect, allowing them to fade out near the edges of the screen. It also uses an actual 3D transition when viewing the input that was used, flipping the picture over in space.


Publishing to the Google Play Store

Now that the app is ready for XR with the spatial layouts, we went on to release it onto the Play Store. There’s one final, important change we made to the app’s AndroidManifest.xml file:


<!-- Androidify can use XR features if they're available; they're not required. -->

<uses-feature android:name="android.software.xr.api.spatial"
              android:required="false" />


This lets the Play Store know that this app has XR-differentiated features, showing a badge that lets users know that the app was made with XR in mind:



Androidify as shown in the Google Play Store on Android XR


When uploading the release, we don’t need any special steps to release for XR: the same app is distributed as normal to users on the mobile track as to users on an XR device! However, you can choose to add XR-specific screenshots of your app, or even upload an immersive preview of your app using a spatial video asset. On Android XR devices, the Play Store automatically displays this as an immersive 3D preview, allowing users to experience the depth and scale of your content before they install the app.


Start building your own experiences today

Androidify is a great example of how to spatialize an existing 2D Jetpack Compose app. Today, we showed the full process of developing a spatial UI for Androidify, from design to code to publishing. We modified the existing designs to work with spatial paradigms, used SpatialPanel and Orbiter composables to create spatial layouts that show when the user enters Full Space, and finally, released the new version of the app onto the Play Store.


We hope that this blog post helped you understand how you can bring your own apps to Android XR! Here’s a few more links that can help you on your way: