In-App Updates (Android Dev Summit ’19)

In-App Updates (Android Dev Summit ’19)


[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]

2 thoughts on “In-App Updates (Android Dev Summit ’19)

Leave a Reply

Your email address will not be published. Required fields are marked *