[AUDIO LOGO]
RAN NACHMANY: Welcome, everyone, to activity embedding,
large screens layout for multi activity apps.
My name is Ran, and I'm an engineer
on the Android Developer Relations team working
on large screens and foldables.
JON ECKENRODE: I'm Jon.
I'm a technical writer in Android Developer Relations.
I write documentation for large screens, tablets, foldables,
Chrome OS devices.
I wrote the activity embedding developer guide.
Activity embedding enables you to optimize activity based apps
for large screens quickly, easily,
with no code refactoring.
And it's being used today by top apps like Temu, WhatsApp,
and eBay.
Ran and I are going to show you how you too can take advantage
of this powerful technology.
Ran will get us started with some insights
into the inner workings of activity embedding.
RAN NACHMANY: Activity embedding allows
you to display two activities side by side, which is great
if your app is based on multiple activities
and you want to implement a canonical list data
layout without going through massive code refactoring.
Activity embedding will automatically
choose the right presentation based
on the available screen space and the settings
that you provide.
This means that you don't need to branch your code to handle
small and large screens.
Here is a sample app available on GitHub that shows you a list
of fruits.
When you click on a fruit, it launches a new activity showing
the lorem ipsum details of that fruit.
This is how it looks on a Pixel 7.
Now if I launch it on my Pixel Tablet or Pixel Fold,
those two activities that were stacked
will now be displayed side by side.
The library also handles screen and window size change
at runtime.
So if a user folds or unfolds their foldable device,
they will get the right layout automatically.
Activity embedding doesn't change the fundamental way
activity ordering on Android works.
It creates two containers or activity
stacks, primary and secondary.
The secondary is always considered at the top
above the primary one.
If the screen is small, the secondary one
will be displayed.
But if there is enough space, these two stacks
can be shown side by side.
Let's take a look.
When there is enough space to display both activities,
a list activity is displayed on the left and a detail activity
on the right.
When the user clicks on a button in the detail activity,
it launches a subdetail activity that
will be displayed on top of it.
As you can see, activities are stacked
in the secondary container as they are launched.
And the secondary container itself
is stacked on top of the primary container.
So activity stacking and back navigations
are consistent with the ordering of the activities
that you already have in your app
and whether your app is running on phone, tablet,
or foldable device.
I think it's time to see what it would take to add activity
embedding to your existing app.
So I'm going to hand it over to Jon,
who will go into some details of the implementation.
JON ECKENRODE: Thanks, Ran.
While I was working on the activity embedding
documentation, I thought, this sounds really easy.
So I decided to try it myself to see.
And you know what?
It is.
I was able to upgrade a basic app to a list detail layout
in a couple of hours using just the documentation and a sample
app as references.
Here's how I did it and how you can too.
But first I'm going to show you a lot of code snippets.
Don't worry about getting every detail.
We've created a code lab and learning
pathway that contain the same information,
so you can refer to those.
Links are in the presentation description.
Also I'll be showing Kotlin examples,
but the code lab is in Kotlin and Java.
You can implement activity embedding
in either of two ways, with an XML configuration file
or using the Jetpack WindowManager APIs.
Today we're going to look at the XML based approach.
To learn how to use the WindowManager APIs,
check out the code lab.
It goes into all the details and you'll
get to work hands on with a sample app.
You begin by adding the WindowManager library
dependency to your app.
WindowManager provides all the components
that enable activity embedding.
You also have to inform the system that your app has
implemented activity embedding.
You do that by adding the activity embedding
splits enabled property to the application element
in the app manifest.
If you're used to XML resource files,
creating an XML configuration file will be easy.
The configuration file defines all the rules
that control which of your app's activities
are combined in task window splits
and how they're presented.
To define a basic split, you use the split pair rule element.
The rule specifies two activities
that display on screen at the same time.
The split pair filter subelement identifies the activities.
The rule also sets properties for the split,
such as the split ratio, which specifies how much of the task
window the primary activity occupies
relative to the secondary.
You can also set the minimum display width
required for a split and whether the activities in the two
containers should finish together.
Another important rule is defined by the split
placeholder rule element.
Placeholders are activities that occupy
the secondary container of a split when no other content is
available.
For example, a placeholder activity
could occupy the secondary container of a list detail
split until an item from the list is selected.
When an item is selected, an activity
containing the item detail replaces the placeholder.
You do have to create a new placeholder activity class,
but it's typically simple because it just
fills the space so users know something goes there.
Kind of like this page intentionally left blank.
A split placeholder rule includes an activity filter
subelement, which specifies the activity the placeholder shares
a split with.
The rule also specifies the placeholder activity.
You can set properties for the placeholder,
including whether the activities in the primary container
finish when the placeholder finishes.
But what about activities you don't want to include
in splits, like modal dialogs?
For those, you use the activity rule element.
You specify an activity name in an activity filter subelement
and set the always expand attribute to true.
Now whenever the activity launches,
it occupies the entire task window.
OK.
Once you've created all your rules,
you need to make them available to the WindowManager rule
controller component.
Rule controller parses the XML configuration file
and makes the rules available to the system.
The easiest way to add rules to rule controller
is to use the rule controller API.
First you get a singleton instance of rule controller.
Then you add the rules from the XML configuration
file to rule controller with the set rules method.
The parse rules method parses the XML file.
You make the call in the on create method
of the primary activity.
Or even better, the on create method of the application.
That's to ensure your split rules are in effect when
any activities launch.
And you're done.
You created a couple of files.
You modified the app manifest and [INAUDIBLE] files.
But you didn't touch any of the app's existing Kotlin
or Java code.
And you didn't change the app experience
on phones or other small screen devices.
If you prefer to work entirely in code rather than XML,
check out the activity embedding code lab for how
to use the WindowManager APIs.
Now Ran will tell us how you can do even more with activity
embedding.
RAN NACHMANY: Thank you, Jon.
Canonical list detail layout improves user experience
on large screens.
Here we can see how eBay allows the user
to see details of a specific item
and browse through similar items without going back and forth.
But that's not all.
Let's take a closer look at how activities are
being launched and displayed.
Let's say we have activity A on the left and activity
B on the right each with its own container.
Now let's say we want to launch activity C. We
saw that activity C will be launched on top of B
using the same container.
However, you can customize that behavior.
We can launch activity C to the side of activity B,
meaning that we keep activity B visible.
This is what we call nested splits
and it is great for hierarchical navigation.
Please note that the z ordering places
activity C above activity B, which means that the navigation
order is kept when our app runs on phones and even
during configuration changes like when a user folds
or unfolds the Pixel Fold.
Activity embedding also supports horizontal splits,
which allows you to place one activity
at the top of the screen and another one at the bottom.
Horizontal splits can be super useful
when you want to provide a special delightful experience
for foldable devices in tabletop mode.
We can take a look at Google Meet.
When I'm unfolding my Pixel Fold,
Meet is using the entire screen to display this nice big video
interface.
However, holding my phone for the entire meeting
can be inconvenient.
So I would like to place it on a table in what we
call tabletop mode.
Meet adapts the UI to the new posture.
So the video is displayed at the top of the screen and controls
at the bottom.
This lets me relax and lean back while running
through the meeting without my hands hurting.
To achieve this behavior, Meet uses the WindowManager API
to dynamically add split rule when
it detects tabletop posture.
Let's take a quick look at the code.
First, we need to detect that the device is
in tabletop posture.
The easiest way to do so is to query WindowManager and look
for folding feature in the window layout info object,
as I do here.
We can detect if the device is in Tabletop mode
by looking at the hinge orientation, horizontal,
and the hinge state half open.
It's important to check the hinge orientation,
as this value defines half of the posture itself.
If it's horizontal, we are in tabletop.
If it's vertical, we are instead in book mode.
Once we know that the device is in tabletop mode,
we need to programmatically create and register
a filter group.
We start by defining a filter encapsulating both activities
that we want to display.
Next we define the split attributes,
specifying that we want the separation to happen
by the hinge and we want this split to be horizontal.
Then we can build our split rule combining the filter
and the split attributes and register it
with the rule controller.
Once we have that, we simply launch the controls activity
that we want to be placed at the bottom.
And that's it.
Users can now enjoy a [INAUDIBLE] experience.
Embedding activities from your own app
is great and super helpful when you design and build
for large screen devices.
But you can do more.
Starting with Android 13, you can embed activities
from other apps as well.
Cross application activity embedding
allows a tight visual integration between activities
that belong to different apps.
This enables the host app to provide a more immersive
experience and control the flow instead of pushing users
to completely different app.
For example, let's take a look at the wallpaper selector
that shows up in the Settings app of Pixel Fold.
The activity on the left belongs to the embedded host,
which is the setting app.
The activity on the right belongs
to the embedded app, which is the wallpaper picker app.
Another scenario is when a developer
wants to provide an option to perform a focused
task in a different app without leaving
the visual context of their own application
like opening a document preview from a file browser app.
Allowing another application to embed your activity
gives a lot of power to the host process.
And that's why this is an opt in feature,
meaning that you need to tell Android
that you want to allow specific activities to be embedded.
And there are two ways to do that.
In most cases where there is a tight integration between two
or more apps, you can define the SHA-1 certificate of the host
application that you want to approve
for embedding your activities.
You can specify one or more certificates.
But sometimes you have an activity
that is designed to be launched by multiple apps,
enabling developers to build SDKs
that are more tightly integrated with apps.
In this case, the host certificate
might not be known ahead of time,
so you can choose to opt in to being embedded by any app.
There is more that you can do, so go ahead and check
the WindowManager release notes for all the latest features.
Back to you, Jon, for any final thoughts.
JON ECKENRODE: Large screens are getting bigger every year,
literally and in popularity.
Optimize your apps for large screens today.
Don't wait.
It's a growing market opportunity
you don't want to miss.
Activity embedding can get you there
with minimal investment and no risk of broken code.
RAN NACHMANY: Try it on one list detail flow that you have,
then a few more.
In no time, you'll be exploring all kinds of use cases
that will make your app great on large screens.
Can't wait to see what you'll be doing with activity embedding.
[MUSIC PLAYING]