[MUSIC PLAYING]
ALESSANDRO DOVIS: Hello, everyone.
I'm Alessandro.
I'm a software engineer on Google Play.
And I'm working on dynamic delivery and app updates.
PIETRO MAGGI: Hi, I'm Pietro.
I work at Google as Android developer advocate.
AMRIT SANJEEV: And I'm Amrit Sanjeev.
I'm a partner developer advocate at Google.
So let's start with a quick recap of in-app updates.
This year at I/O, we introduced in-app updates
API, which allowed you, developers,
to inform your users when a new update is available for them
in Play Store.
Now, many of you might be thinking,
why do you need a new API when there is auto updates in Play.
But in the real world, a lot of users
actually turn off auto updates because they
are concerned about how much data bandwidth it's using.
Moreover, there are many users who actually set this up
in a way that it only works when they connect it to Wi-Fi.
And they don't connect to Wi-Fi for extended periods of time.
Which means that these users are experiencing the older
version of the app and not seeing all the new features,
bug fixes, and security updates that you are actually
rolling out.
There are two ways in which you can actually
show in-app updates.
One is an Immediate flow, where when the user clicks to update,
the rest of the UX is completely managed by the Play library.
This is the easiest way to integrate.
But if you want more control over the UX,
you also have the Flexible flow.
Here, when the user chooses to click Update,
the control is returned back to the app.
And the user can continue to use the app while the update
downloads in the background.
This way, when the download is completed,
the Play library then informs the app
that the download is complete.
Then you choose an appropriate time
to tell the user to complete installation.
And talking about some of the benefits
that you have from a developer's perspective,
you're communicating the update size upfront.
This is a factor that people use to decide whether they should
update immediately or not.
It also respects all the Play distribution rules.
Which means if you're actually rolling this out only
to a small percentage of your users, in a certain channel,
only those users who are in that channel
and are in that bucket, the small percentage,
will actually receive these updates.
This is not a feature that was possible with many
of the libraries out there, which
used something like Remote Config
to show the dialog to the user.
It also means that because your users are updating faster,
there are less versions of your code
which are supported in production, thereby
reducing your support costs.
And it's really simple and easy to integrate.
And from a user's perspective, there
is a clear reduction in install friction.
Not only that, the user can update the app
without leaving the app at all.
And the update is actually downloaded in the background,
so the user's workflow is not interrupted
while the update is getting downloaded
There's also some smarts into this API.
Imagine your device is running out of battery,
or it's not connected to the internet.
In such conditions, this API does not actually
prompt the user to update because those
are conditions under which the users are most
likely not to update.
So these smarts are also there in the app.
Now quickly looking at some of the results
that we have seen with partners who've adopted this.
Riafy, which is a recipe app from India,
has seen over 40% of their users upgrading within the first 30
days after they've rolled this API out into production.
Not only that, they've seen a nearly 40%
reduction in the time taken for 50% of their users
to upgrade to the new version.
The second example that I want to call out is RedBus.
RedBus actually saw that the time taken
for 40% of their users to upgrade to the new version
was reduced from 10 to 3 days after they introduced
this API into their codebase.
And lastly, I want to call out Swiggy, which is
a food delivery app from India.
They saw an increase of 0.7 million users
updating the app after they introduced this API.
As these numbers suggest, the apps
clearly benefit from users updating quickly.
And the users also benefit because they
see the new features and bug fixes
much earlier in the cycle.
Now I want to hand it over to my colleague Pietro
to talk to you about testing.
Go to you.
PIETRO MAGGI: Thank you, Amrit.
Since the introduction of in-app updates at this year I/O,
one of the main feature requests that we got from users
is, how we can test in-app update easily?
And testing here is really in three phases--
during development, at the time of the release,
and to support the existing release, to look at bugs
and so on.
So for testing during development,
we have the FakeAppUpdateManager,
where you can use your unit test to control
and check out the logic and UI of your in-app updates.
So you can set it up so that there is an update available.
Then you call all of your code and UI.
And then you can drive the update in this way.
You can simulate that the user has accepted the update.
You can start the download, and you can simulate
that the download completes.
So this allows you to do unit testing
and check how your update code works.
Next is testing when you have a new release,
so when you want to introduce a beta tester.
And one other feature we introduce at I/O
this year is internal app sharing.
With internal app sharing, what you do
is that you upload in-app bundle or an APK.
The Play generates for you a sharable URL.
And the tester can use this URL to test
that application and the bundle with dynamic delivery
on the device.
We are now announcing that we are enabling
the use of internal app sharing to test your in-app updates API
flow.
So how does it work, internal app sharing?
On the Console, you have this web page,
where you upload the APK or the app bundle.
And it's generating for you the link.
You need to set up who can upload the APK and the app
bundle and who can use the link that is generated.
The other thing to remember is that Play
is going to sign a specific--
we have a different certificate, your application in this case.
So if you are using third-party SDK that
needs to have the certificate, you need to download from here.
And you can use in this case, like for every other time
that you're using internal app sharing, the [INAUDIBLE]..
The version code is not important
that you increment every time the version code
because Play is going to place a new version code for you when
you upload a new APK or a new bundle.
In the configuration of the console,
you need to enable internal app sharing on the device,
on the client.
So you open the Play application on the device.
In the settings, you tap seven times on the version code.
You get a new toggle to enable internal app sharing,
and you turn it on.
And you are good to go testing using internal app sharing.
For in-app updates, it's a bit tricky
to get the flow at the beginning.
So the idea is that you install a version with internal app
shading.
You can use then the same upload, the same version.
Get a new link with a new version code generated by Play.
You open the link on the device.
And you get the pop-up with the update.
I have a video to explain this a bit more clearly.
So you get the pop-up with the update.
At this moment, you can go in your application,
and then in-app updates API will see the update at the moment.
So you need to follow the link.
Don't click on the Update button from the Play Store.
And then in your application, you
can check that the in-app update works.
The first place where you can do testing
is for versions that are ready to be released.
If you have a bug--
someone is reporting a bug in the version
that you released three months ago,
it's not updating correctly.
We have the new version we're releasing now.
We are announcing that shortly we
will make available historical virtual links, where
you can download an APK from an older version using the very
similar flow and test with this link
the update with the new version.
So look out for more information in coming weeks
about the historical virtual links
we will make available shortly.
Next is Alexandro that is going to talk
about some new exciting features coming in in-app updates.
ALESSANDRO DOVIS: Yeah, thank you, Pietro.
So I'm going to tell you something more
about a few new features that we've
been working on after Google I/O based on some of your top asks.
So first of all, we're going to introduce
a couple of new signals that will help you essentially
decide when to trigger an in-app update, which flow to trigger,
and how promptly, how much to promote it in your UI.
And these are the update priority and the app staleness.
Secondly we are exposing some more fine-grained information
about the progress of the update as the update is downloading.
So we're going to go through each of them
individually very soon.
But first, let's take a look at a snippet of code
to give some more context to this.
So here, I've got a snippet in my demo app.
And here, I'm fetching from the API the AppUpdateInfo
to detect whether there is an update available or not.
And if I see that the update is available,
now I have to decide what to do.
I need to decide whether to trigger in-app update
and which flow to use.
And this is exactly the situation
that will be made simpler by the signals
that we are going to expose.
So the first signal is priority.
The priority essentially represents the importance
of an update.
So something that has a higher priority
is something that you can see that should be
of higher value for your user.
The priority is something that you
define when you release your app for each of your releases.
And then it's being propagated through our systems
and gets back to you at runtime via the API.
And at that point, you can decide
to show a different user experience based
on the priority of the update.
So more concretely, the update priority
is an integer value that goes between 0 and 5.
And we do mandate the exact semantics
of each of the individual values because we
want to make sure that you have the freedom
to tailor the semantics of these values
and to define the thresholds based on your app freshness
needs.
So let's go back to the snippet of code
and see how I'm using that in practice.
So here I'm doing something rather straightforward.
Let me highlight the new part.
So here I'm doing like, if the priority is bigger than 3,
then I'm triggering the Immediate flow.
Otherwise, I'm pulling back to the Flexible flow.
And here, the number 3 is purely arbitrary for my app.
So you might tailor this value and tweak it
depending on your needs.
And this is a very simplified decision
tree, where I'm using that signal as a single signal.
But you can imagine to use it in combination with other signals
that we provide or that you already
have to make the best decision possible in this case.
Let's move on to the second signal, which is the app
staleness.
So app staleness tells you how long
the device has known about an update
being available for the user.
So essentially, if your user has had the app,
and he has been out-of-date for a longer time,
the staleness will be higher.
And so probably, that user will need to update it more eagerly.
And here is an example of how I'm using that.
So here, what I'm doing is if the staleness
is bigger than 90 days, then I'm triggering the Immediate flow.
If it's between 30 and 90 days, then I'm
triggering the Flexible flow.
And something that is implicit in here that I want to call out
is that if the app is fresher than 30--
well, if it's less stale than 30 days,
then I'm not triggering an in-app update at all.
So this is also a very important decision to make,
like when to decide to trigger the update at all,
because sometimes you don't want to notify
your users unnecessarily if the app is already
fresh enough, right?
And now let's move on.
And let's assume that you have triggered the Flexible flow.
You have triggered the Flexible flow,
and the user has decided to consent.
So the update is started.
And the user most likely will stay in the app
as the update is downloading.
But at the same time, the user might
want to know how the update is going,
how the download is going.
And they might want to do it without having
to get out of the app because that's the whole point.
So to enable such a more immersive experience
so that the user stays in the app,
we are going to expose a couple of new bits of information
as the app is downloading, which is like the amount of bytes
we have downloaded so far and the total amount of bytes
that we will need to download for the update.
What does this enable?
So if you look at the right-hand side of the screen,
there is my demo app, where an in-app update
is in progress Flexible flow.
And you see there at the bottom, my app
is showing a progress bar that I'm updating in real time,
so that the user in real time can
see how the download is going.
And on the left-hand side of the screen,
you can see how that is done in code.
So here, I'm using a listener that I register in the API
to receive progress while the update is happening.
And what I'm doing in the listener is pretty simple.
So whenever I receive an update and a progress state
with InstalStatus.DOWNLOADING, then I'm
updating my UI with the latest values of bytesDownloaded
into downloads.
And all these features-- the update priority,
the app staleness, and the more fine-grained information about
the progress of an update--
are going to be rolled out very soon.
So please come and talk to us if you
would like to be the first ones to try them out.
And with this, I'm giving it back
to Pietro, who's talking to you about the Play Core Kotlin
extension.
PIETRO MAGGI: Thank you, Alessandro.
So come and ask us in the Sandbox.
We have seen these exciting new features
that are coming in in-app updates API.
But Play Core is something that you
can use in Java and in Kotlin.
And Android now is a "Kotlin first" platform.
So we already announced it today in this morning talk
on dynamic delivery about the play Core KTX.
But the Play Core KTX supports also in-app updates.
So the Play Core KTX is an [? idiomatic ?] API
that support Kotlin.
And we are leveraging a few features of Kotlin.
The idea is that we want to simplify the API surface.
And we want to be opinionated on how
to use the in-app updates API.
So we want to drive the developers to use it
in the right way.
And we want to leverage all the power of Kotlin
with coroutines and flow.
So to get an example, it's much simpler,
the in-app update flow, then the dynamic delivery.
There are less status here, But it's the same concept.
So you can register for a flow and collect the events coming
from the underlying Play Core API
so you can know when the update is available,
it is in progress, and it's downloaded.
The other thing is that using coroutines,
it's much easier to end all the cancelation and the cleanup.
In this simple, I'm using a viewModelScope.
But the idea is that you can attach this flow
to your own coroutine scopes and link this
to the lifecycle of your application or the UI
that you want to use there.
And the last thing is that for developers that are not yet
comfortable using Kotlin flow or they cannot use experimental
Kotlin features, we are exposing a couple of suspended
functions, so coroutines, where you can request
the AppUpdateInfo.
And you can request that when the update is complete.
And this allows you to simplify a lot the usage of the Play
Core API, avoiding the use of the task returned by the Play
Core API.
This library is already available.
So we are really open to get feedback.
It's fully functional.
We are implementing most of the features of Play Core.
And if you want to know more about the Play Core KTX,
I suggest you take a look at the recording
of the video of the session of this morning
on dynamic delivery, where my colleagues
have introduced a part of the Play Core KTX
covering the dynamic delivery.
So again, this is a very quick overview of the Play Core KTX.
You can come to the Sandbox, talk to us,
ask information, download the library, and start to test it.
And please, provide feedback.
So thank you everybody for coming today,
and update your app.
[APPLAUSE]
[MUSIC PLAYING]