RETO MEIER: Hi.
My name is Reto Meier, and I'm the tech lead for Google's
Android Developer Relations Team.
This efficient data transfer's DevByte is going to look at
techniques that you can use to reduce the battery drain of
your app without affecting the freshness of your data by
adapting the frequency of your updates based on context.
In other DevBytes, I've explored ways to analyze your
app's transfer profile and optimize it using techniques
like prefetching, bundling, and SyncAdapters in Google
Cloud Messaging.
The goal is to ensure that you never initiate a transfer that
isn't related to require data sync.
But if you have server data that changes rapidly, such as
breaking news, weather, or sports scores, treating an
update every time there's an update on the server is still
been tax your servers and drain your user's battery,
particularly when your app is in the background.
Now, the aim of this DevByte is to get beyond limiting
transfers to when they're valid and start considering
device state, user behavior, and impact on the user
experience to minimize the number of updates that we
actually perform.
In my DevByte on Google Cloud Messaging, you learned that
you can set your server messages to be delayed when
the device is idle.
As a result, your messages will be queued, and that queue
is collapsed, so that when your app only receives one
message when the device becomes active.
Now, that's a useful start, as it prevents multiple updates
from happening when the user isn't
actually using the device.
In other DevBytes on using the SyncAdapter, you saw how to
group all of your app's transfer methods within your
SyncAdapters on Perform Sync method.
A SyncAdapter can be triggered a number of ways, including
GCM [? TCLs, ?] client-side changes, scheduled updates, or
user actions, like selecting a new song, or browsing an
article that hasn't been prefetched.
Within our perform sync handle, we need to determine
which of these triggers are sufficient to initiate a new
transfer, starting with scheduled updates.
Periodic updates are a great way to ensure your app never
seems stale, and that users aren't left waiting for
significant amounts of data to be synced every time
you open the app.
Of course, stale is relative, not only to the type of data
that your app displays, but also how frequently a user
opens your app.
Periodic updates work well for apps like news readers, where
the frequency of news articles makes sending a GCM message to
every app whenever new articles are available.
Massive overkill.
And the freshness isn't critical unless the user
happens to be actively browsing it.
In this case, performing a background refresh every hour
might be a reasonable approach for users who open the app
several times a day, as it ensures that they see fresh
headlines every time the app, even if the device hasn't been
online for a while.
But it's wasteful for a user who only reads the news
headlines once each morning.
Now you can mitigate this by reducing the background update
frequency based on the recency of app usage.
In this snippet, we check to see if the app has been opened
since the last time we performed a refresh.
If not, we double the period between refreshes.
Now each time the app is opened, we reset that counter.
So as a result, your app fresher data for regular uses,
where those who open the app only once a day or once a week
are saved the resulting battery drain.
Now, if you're reducing the frequency of updates to reduce
the battery-hungry use of the cell radio, we might be able
to mitigate some of these choices based on the current
battery level, charging state, and connectivity time.
It's generally good practice to minimize background updates
when they don't result in notifications.
But the impact of performing updates while the device is
charging over the AC is negligible.
So you can reconsider some of those assumptions when the
device is connected to a charger.
Conversely, you can listen for a broadcast telling you that
the devices is low on juice, and reduce or eliminate
background updates completely until the device is charging.
Of course, just because you're connected to power doesn't
make your downloads free.
Even if you're not concerned with the power drain
associated with 3G radio, you should still be conscious of
the amount of data that your'e transferring.
You can also monitor the current internet connection to
help mitigate against that.
If we're connected over Wi-Fi, bandwidth use isn't an issue,
and power use is significantly lower than when compared to a
cell radio.
That means you can more aggressively react to sender
synced messages when client-side, or client-side
content provider changes when you're in the foreground, and
potentially, even in the background, especially when
we're also connected to power.
A good example of this scenario is when
the device is docked.
Monitoring for the device to be in a docked state can be a
useful shortcut, letting you know how to check for
connectivity and charging status, and potentially
modifying the frequency at which you perform syncs.
You can check the current device state each time you
receive a GCM TCL or a local content provider changes to
determine if should actually perform the update.
Or you can monitor changes in the device state to alter your
SyncAdapter settings to stop or start
listening for changes.
Likewise, you can send a message to server altering the
frequency at which you want to receive
this into sync messages.
For example, you may want to receive a TCL after there are
10 new headlines, or only when there is a breaking news story
in your area, or not more frequently than
once every 10 minutes.
You might also want to consider the context of the
user themselves.
Using the new activity recognition APIs, you can
choose to alter the foreground update frequency based on what
the user is doing.
In this example, we might artificially limit the update
rate when they're doing anything other than standing
still, on the basis that users are less likely to be looking
at the screen and browsing.
Now, we can use a similar technique as an alternative to
periodic updates.
Rather than update the app once every 24 hours to ensure
it's fresh in the morning, you might check for the tilting
activity after a prolonged period of being stationary as
an indication that the user had been asleep and has now
gotten up in the morning, so it's worth
refreshing their data.
Now having introduced a number of possible ways to skip or
delay transfers, it's important to check the cause
of the sync to ensure that you're not delaying transfers
that will affect the user experience directly.
Any manually initiated transfer--
so, anything that's necessary for the user to continue using
the app, or browsing--
needs to happen straightaway.
When using SyncAdapters, you can determine
this, as shown here.
Now in any case, while it can be useful to alter the
frequency at which we execute as sync, fundamentally, we're
still depending on techniques like SyncAdapters and and
Google Cloud Messaging, as described in other DevBytes in
this series, to ensure that we only ever consider performing
a sync when data changed, either on the
client or on the server.
Even then, we want to avoid performing a sync thing that
could be delayed without impacting the user.
In most cases, that means being very conservative with
background updates, and anything that doesn't result
in a notification being displayed.