The App Clinic: Cricket

RETO MEIER: Hello, and welcome
to the App Clinic. My name is Reto Meier, and I’m
the tech lead on the Android Developer Relations team. And today I’ll be designing the
ultimate Cricket tracking app for Android. If you’re wondering why I’m
not joined by my usual co-host, Ian Ni-Lewis, well,
despite 4 hours of excruciating training, Ian still
can’t reliably determine an LBW decision without
referencing both Hot Spot and Hawkeye. And even then, half the time,
he’ll forget to check the pitched outside leg. So rather than subject came to
the written examination on the Duckworth-Lewis method, I’ve
decided to host today’s App Clinic solo. Now, I’m the sort of person
who considers Pictionary a torture roughly in line
with water boarding. So the focus of my design will
center on architecture. I’ll be using apps that let you
follow cricket scores to provide some context. But the same techniques and
approaches will work just as well for a range of apps,
particularly other sports like baseball or any code of
football, whether that’s throwing, kicking, catching
a round or any other shaped ball. Now fair warning, I took many
of these screen shots during day two and three of the second
Ashes test, so any members of the Australian test
squad suffering from PTSD should look away. As engineers, it can be tempting
to start designing our apps in terms of the data
we have access to, then considering how to display
that data. Instead of building the ultimate
hammer and then packaging it in a shiny box,
invest some time examining the problem as a user without
considering how you’d go about solving it. So let’s take a look at the
problems the existing apps already solve. Cricinfo is celebrating its 20th
anniversary this year, and they’ve always been
my go-to site for following the cricket. What I really like about their
mobile app is that the info you’re most likely to want– live match scores– is front and center. Swiping left and right allows
you to move between all different currently-live
matches. Beyond that, everything else–
fixtures, news, video, et cetera– are all within
easy reach directly from the front page. Cricbuzz takes a similar
approach to live scores, but has limited the front page
to a list view of current news articles. The other content is still
available, but they’ve moved off the main UI and into this
navigation spinner. Now, I actually prefer this
approach in general, as it makes the app landing page
a little less cluttered. So in terms of solving problems,
we can see that both apps are providing live scores,
upcoming fixtures, cricket news, photo galleries,
and access to the rich world of cricket statistics. In terms of priorities,
the focus of both apps is live scores. So let’s dive in here
a little deeper. When you select a live match in
Cricinfo, you’re shown the standard score summary. It shows the current inning
score, the batsman, bowler, and even the last few balls
from the current and previous innings. Below all of that, we
have our commentary. Now, like the landing page,
everything is available by interacting directly
with the UI. You can swipe or click these
icons to move between the summary score, full score,
commentary and news views. Clicking on a particular player
will take at their stats page. This is really the heart of the
app, and they’ve done a great job of fitting a lot of
information into a small area. Cricbuzz has a very similar
matched score display, but its moved the navigation into
the overflow menu. They’ve also incorporated
a couple of really cool features. Specifically, they’ve got score
tracking and live audio commentary. Now, I actually think audio
commentary is a big enough feature that it deserves
promotion right to the action bar. Now, note that both
of these apps have used a refresh button. Now, a big part of my
architectural redesign is going to talk about how to
eliminate the refresh button from apps like this. Things like every refresh button
are a great example of how implementation can sometimes
drive visual design. As engineers, we need a way to
call the method that initiates the downloads. And then you add a visual
control who’s event handler will trigger that
method, right? Well, no. If you start with your idealized
visual design, you wouldn’t include a
refresh button. You’d just make sure that the
scores were always up-to-date. Much like a save button,
why would I ever not want to save my work? Now, just because you have a
save method doesn’t mean you need to have a save
control on screen. And it’s the same thing
with refresh. Now I never start a project
without sketching out my UI. And I can’t draw for
sh– love or money. But this is really an important
place to start. By defining the user experience
early, you add useful constraints around what
your app needs to do and how it needs to do it. That clarity is what lets you
build something that’s targeted to solving real
problems, rather than a collection of features you
built because you could. Now I took those raw sketches
and used the design guidelines to try and put together some
mocks that sort of had that simple and consistent feel
in line with the Android visual language. In addition to the two apps that
we just looked at, I also took some inspiration from the
ABCs cricket site, which is a really clean design without
being too spartan. So I’ve really tried to sort of
merge those philosophies. Now, I’m clearly no designer,
but for today’s app clinic, I’ve at least taken my pencil
sketches and turned them into some primitive mocks
for us to look at. For the real deal, the Android
design and action team are going to transform them
into real mocks for next week’s show. So this is the first
of the mocks. I think it’s important to
remember that a lot of developers can get lost in the
weeds of potential, of what their app could do. So we get so caught up in what
we think we might be able to build in the long term that we
lose sight of why we built the app in the first place. So my guiding principle for
software design, both visual and architectural, is to focus
on the simplest way of providing the most important
information. And I do that by asking
why has someone downloaded this app? And the easiest way of answering
that question is to ask it yourself. Why would I downloaded
this app? Now for me, it was to track the
scores of the Ashes test. So, like Cricinfo and Cricbuzz,
when you open the app, you get the live scores
for all of the ongoing matches, front and center. And you can swipe to transition
between them. For the remaining space, I was
tossing up between displaying either just all kinds of news
or upcoming fixtures. And to make a choice, I tried to
imagine the user experience based on someone’s intention
when opening app for the first time when downloading. Or even once it’s installed,
every time that they open the app. Now if you’re checking for an
upcoming match, that takes exactly however long it takes
for you to find the match that you’re trying to look for. That’s a fixed time cost that’s
entirely dependent on my implementation on how long
it takes for you to get to that point within the app. Now if you open they app to read
cricket news, the time cost is variable. And it’s dependent on how much
time the user wants to spend reading the news. So the time taken to navigate
to news is really only an incremental additional time cost
on top of the time that they were already planning
to spend reading. So by displaying fixtures, we’re
removing time from a critical path of one of those
user interactions. Now, for navigation to other
features, I’ve actually gone with a sliding drawer. Mainly because it’s the new
hotness, but also because I think it’s a really elegant
solution to navigating around a lot of heterogeneous
content. Now this is the case for an app
like this, where you have a lot of different features
which could theoretically each be separate apps. But they’ve been bundled
together for convenience or because they’re thematically
similar. So a navigation drawer, a
sliding drawer, is a really neat way of being able
to have that sort of meta layer on top. Now really, all of this is
window dressing for the real money, the live match display. Now, following the same
principles of focus, I’ve tried to keep the match activity
as simple as I can. You land on this score summary,
where I’ve used country flags to add a little
bit of visceral reaction, something that only a
national flag seems to be able to invoke. Now, the commentary is
immediately below. And the whole thing is
just a vertical– vertically scrolling
list view. Now, you can do swiping
horizontally, and that will switch between the summary view,
the full score view, or related news based
on that match. So we’ve got a two-dimensional
scroll, which will let you do the change the content that
you’re displaying or the content within that view. Same as the other two apps we
looked at, clicking on a particular player will take you
to their stats page and clicking on a country will take
you a country page, which is going to include stats,
recent results, and upcoming fixtures. Now, any sport that includes
five-match series that last five days each is going to
produce a lot of statistics. And any sport that includes an
afternoon tea break is going to give you a lot of
opportunities to delve into those stats. Now, in this tablet mock up,
I’ve tried to give an idea of the sort of space you’ve
got available when optimizing for tablets. Now, to me, it seems obvious
that you’re going to want to drop a summary and other list
views over here on the left-hand side. And then you’ve got almost 2/3
of the remaining display space as prime real estate to do
things like commentary, player stats, not to mention even more
detailed things, like match statistics, player versus
player breakdowns, a multitude of graphs, and of
course, even the possibility of adding things like Hawkeye
directly within the tablet experience. Now, the mobile phone app is an
ideal way to keep track of a series or a match, but done
the right way, a tablet app actually introduces the
opportunity to deliver a true cricket companion that gives
you an immersive experience that’s richer and more easily
accessible than the information already
available web. And we already know that
users spend more time in apps on tablets. So creating a rich tablet
experience is a great opportunity to drive that
deeper user engagement. Now the last feature I want to
talk about from my visual mock ups is starring a match. Now, starring is a pretty
well-understood metaphor in Android that’s generally
associated with bookmarking something or marking something
as important. Now, within my app, I’m going
to take it as an explicit signal that the user is
interested in this match. And as an implicit signal that
she might be interested in one of more of the teams or even
the location with match is being played. Now, we can use this
information in a number of ways. First, by adding a shortcut to
starred matches directly from our navigation drawer, but
also as a way of enabling notifications for
match events. Now, by default, I’m going to
trigger a notification for every heart-breaking wicket,
every change of innings, and every merciful stumps
for every match that has been starred. And I will include a flag within
the settings menu to let users de-select any of those
particular match events. Now, the notification itself
should show everything related to that event, so the inning
score, the wicket details, and when you expand the
notification, the commentary associated. Ideally, you shouldn’t have to
click on the notification to enter the app to be able to
understand the full context around the event that
has triggered it. There’s a range of actions that
you can associate with each notification, anything from
links to the video clip to sharing the data or even an
option to cancel further notifications for the remainder
of the game when it all just becomes
too depressing. Now, the real trick is making
sure that these notifications are timely but don’t
drain the battery. And that’s really the
underlining philosophy of my entire design. Moving beyond the visual design,
we need to create an information architecture
that will let us bring these mocks to life. Now, we need to consider
three factors in our software design. What do we need to show? When do we need to update
what we’re showing? And how do we perform these
updates efficiently? Now fundamentally, the
answers to those questions are pretty simple. Show users what they’re
expecting to see. Do updates as often as you need
to, but don’t do updates if they’re not necessary. And perform them using a
combination of Google Cloud Messaging, sync adapters,
and the volley library. And of course, you want to do
all of that in a way that makes it look as though it’s
happening by magic. Now, I’ll forgive you for
thinking that those answers are a little simplistic. Certainly, I understand that a
simple design can look very different once you’ve
implemented it in the real world. So before we dive in, let’s take
a look at a few simple techniques we can use to add
a little bit off magic. We’re going to do that by
offering some features which I think users will appreciate but probably weren’t expecting. Now, when we looked at Cricbuzz,
I mentioned that they’re live commentary option
is a big enough deal that it should get promoted to the
action bar directly, but what if you don’t have access
to a live audio stream? Fear not. You can take advantage of
Android’s text-to-speech library to create your own
dynamic commentary. This is a massive features for
folks like me, who want to follow a match while I’m driving
to and from work. In fact, you can take this a
step further and include an option to automatically trigger
dynamic commentary when the user is driving using
the new location-based services activity
detection APIs. But of course, the real magic
comes for an app that seems to have been built especially
for you. And that means showing
you exactly what you expect to see. Now, when you open the app to
the landing page, there’s likely to be several cricket
matches being played, including tests, one-dayers,
Twenty20, domestic and international. So how do you make sure that the
match I downloaded the app to track is the first one
displayed in this list? Now at I/O last year, I talked a
lot about context and taking advantage of what your phone
knows about you to create a personalized experience that
will make your app feel as though it was custom built
for each of your users. So how do we find out what match
each user wants to watch without asking them first? Well, for a start, we can assume
that the teams involved in a starred match are likely
to be of interest. Similarly, we can keep track
of which matches the user has watched. Over time, we should be able to
see a pattern to understand which teams or which grounds
the user is interested in the games of. But that doesn’t help
us the first time that the app is opened. For that we need to be a
little bit sneakier. So let’s start with
the most obvious. Check where they are using
location-based services. Request the course location
information and then reverse geocode they’re last-known
location to figure out which country they’re in. You can even go a step further
and figure out which state or province they’re in to
understand which domestic site that they’re likely
interested in. But I live in the US,
so that’s really not going to work. So what else can we try? Well, another good signal is the
locale that the device is configured to. It’s a strong signal, but my
device doesn’t let me choose an Australian locale. Well, if I asked you what the
score was on the cricket, you’d assume I was interested in
Australia and it’s not just because I’m a masochist, but
because I have an unmistakable Aussie accent. Now, it turns out that the
Android voice recognition lets you select your accent as
well as your language. So using this code, you can see
which language variation has been selected. Boom, now you can use my accent
as a way to guess which country I support. And suddenly you’ve got the
opportunity to customize the UI for me and put the Aussie
matches right at the top of the list. Now, this might seem like a
lot of work for a fairly trivial modification. But now, the first time I open
your app, there’s a very good chance that I’ll be presented
with the exact match that I downloaded this app in order
to find out the score for. That’s a really powerful,
positive signal that I’ve done the right thing, that I’ve
downloaded the right app, that the person who developed it is
on the same wavelength as me. Other ways we can find out what
people are interested in. We can take advantage of
Google+ integration. So we can use the explicitly and
implicitly tracked teams from our friends to help inform
the app of the matches that we are likely to
be interested in. And as a bonus, by using Google+
sign in, you can now synchronize those starred
matches across all of the user’s devices. So, now we know the matches that
you’re user has indicated that they’re definitely
interested in and the ones that they are likely to
be interested in. So how else can we use that
data to improve the performance and usability
of our app? Well, we could start by sending
it all to your server. Now, this is an important step,
as it’s going to help us is ensure that we only perform
updates as often as needed to ensure that we can eliminate
the refresh button. Now, that means that the data
being displayed needs to be constantly up-to-date. And for sports scores, that
means getting updates as soon as they happen, but without
wasting bandwidth and battery requesting updates in
between overs or during the drinks break. Now, updates are going to fall
into two broad categories, background and foreground. When the app is open and the
user is looking at it, they’re either going to be browsing,
looking at news, stats, upcoming fixtures, and so on. Or they’re going to be watching a match as it happens. Now, in the latter case, you
should be looking to implement the best practices for creating
apps that transfer the data in battery-efficient
ways, so that when they’re browsing around your site,
they’re not draining the battery every time they
click a link. Now, I like to call this
the big cookie model of data transfers. In real terms, that means
minimizing the number of radio state transitions caused by your
app transmitting data. To do that, you need to
pre-fetch enough data so as to prevent additional downloads,
usually within the next two to five minutes, without just
cheating by downloading everything on your server. Now typically, that’s going
to look like around five megs of data. Now, what you download is
whatever you think the user is likely to request within that
next five-minute time window. It’s another good opportunity
to use those implicitly tracked teams to pre-fetch
commentary from matches that they’re likely to observe or
which news stories they’re likely to read. Pre-fetched data is available
instantly and has zero incremental cost in terms
of battery life. So it’s generally good
practice to be pretty aggressive with what you choose
to pull down ahead of time, while all the time being
conscious of the associated bandwidth cost. When we do need transfer data,
you want to batch all of your transfers together. It’s more efficient to transfer
a lot of data at once rather than spreading
it out over time. So if you need to pull down
commentary for new match, you should take that as an
opportunity to preempt your next batch of pre-fetch news
stories and score updates. The easiest way to do this is
by bundling all of your transfers together within
a sync adapter. Then within each of these
methods, you can make a more fine-grain choice regarding what
data you actually want to transfer each time a sync
adapter is called. Now, for example, fixtures. You probably don’t need to be
updating them more than once a day, whereas news headlines will
more likely want to be much more frequent. Now, when it comes to real-time
updates, there’s a temptation to set up a timer
that just pings your server for an update every minute
while your app is in the foreground. Certainly, that’s an approach
that I took years ago, back in the days of Google desktop. Before I knew better, I wrote
myself a widget that tracked scores on Cricinfo
by scraping a particular page every minute. It was perfect. While the match was ongoing,
I got those constant bowl-by-bowl updates. Unfortunately, it had a bug
that included a race condition, which, when
triggered, meant that the widget missed the
end of a match. So it would get a 404 but would
keep pinging the site over and over, every minute of
every hour of every day. It was only brought to my
attention when the company’s tech ops folks wondered why I
was downloading one and a quarter gig of data every
week for a month while I was on holiday. So regular updates, foreground
or background, need to be carefully managed. In fact, foreground updates are
really just a special case of background updates, one
which happens much more frequently. So let’s take a look at how
they can work together. And we’ll start by taking a
closer look at the background update case. Now, we have starred updates
for which we want notifications. We have implicitly tracked teams
for which we want to do regular updates to keep the
app fresh, and updates on fixtures and stats that probably
only need to happen once a day. You may even argue that only
starred matches need to be updated in the background, but
personally, I think that there’s value in keeping the app
up-to-date even when it’s not running, as long as we can
do so in a way that doesn’t drain the battery. If you do it right, you minimize
latency at start up. You can make sure that the app
is still useful even if you don’t have connectivity right
when you open it. So, like the visual design, I
start my update architecture with pen and paper. Now, this design translates
into this flow chart. So let’s step through it. And we’ll start with our
starred matches. Now, these are the games our
users have explicitly marked as important and for whom we’re
delivering notifications while that app is in
the background. Now, matches that of being
observed while in the foreground, for which we want
to have those real-time updates, they fit into
the same category. For those updates, both the
foreground and background case, we’re going to
rely entirely on Google Cloud Messaging. We’ll set a flag on the server
to decide whether we want to have every bowl updates or if
we just want significant events like wickets
or end of innings. But rather than just sending a
push message notifying the client of impending update, we
can just send the entire update within the GCM payload. Now, every GCM message can
contain up to 4K of data. One over’s worth
of commentary’s typically around 1K. So you can safely send the
commentary for each bowl of an observed match or the details of
a fallen wicket, including the commentary, for background
notifications. Now, the result is a
significantly decreased latency for those updates and
a simpler, more efficient update implementation where
you’re not having to figure out how to modify the timing
of your update based on the current state of the match. And you never doing updates
more frequently than you need to. Now, for matches that we aren’t
actively tracking, we can use Google Cloud Messaging
to tickle the client when there are updates related to the
teams we implicitly track. We do want to initiate an update
for every new news update or new fixture or new
match for teams we aren’t actively tracking. So we can prioritize
pre-fetching information related to the teams we
think are the most relevant to our users. Now, given that the data is
changing on the server, it again makes sense for these
updates to be driven from the server side using GCM. But we can make them even more
efficient by having the client influence the frequency with
which we actually receive these updates. Now, I like to implement a usage
back off pattern backed by a sync adapter. So every time we perform a
redundant update, defined as two updates that happen in
between the app being closed and being reopened, we double
the amount of time that we wait before we performed the
next background update. Now, that same approach will
work either by changing the frequency of a periodic sync
set for sync adapter or by setting a flag on the service
to each of those client updates to say how frequently
we should be performing this tickles. The update itself will be formed
by triggering a sync adapter in exactly the same way
as it should happen when the app is opened. And you want to get that
fresh data when the user starts browsing. Now alternatively, or
additionally, you can use further context to modify the
background updates and browsing pre-fetch rates
of your application. For example, a user standing
still, browsing the app, is much more likely to browse
for longer than one who is walking around. So you can use activity
detection to increase pre-fetch amount, or the
frequency of prefetches, based on the fact that they’re
standing still. Similarly, you can use the
tilting activity to determine when to initiate daily updates,
like fixture changes, every morning when you user
picks up their device rather than specifying an
arbitrary time. Finally, there’s one more piece
of magic that we can build which sits at the
confluence of background updates and implicitly tracked
teams, series notifications. So by tracking the teams that we
think users are interested in, we can send them infrequent
notifications to alert them of significant
events related to a particular team. This can be a really effective
way to help drive engagement by reminding people
to use your app. But it’s important to be very
careful not to become spammy. I’d recommend only sending
notifications once per series. It would be great to know that
the Ashes is about to begin, but I don’t necessarily want to
be told every single match that Australia is playing. Now, it may even make sense
to add a “stop these notifications” action to the
notification itself. Or go the other way, and perhaps
include an action to star every match
in that series. So they get one prompt and are
then able to opt in or opt out of getting further
notifications. So we’ve covered all the
technologies already. But let’s quickly review the
technologies that we should be using to perform all
of these updates. Now, I’m not going to go into
too much detail because I’ve already been talking for
a very long time. But I’ll share some the
resources that you can use to find out how to implement what
I’ve been talking about. So everything in this design
is driven from your server, with Google Cloud Messaging
either transmitting the data directly or initiating a sync
adapter update through tickling the client. The Google Cloud Messaging APIs
are described in detail at developers.andro and you can find out lots of detail on
implementing sync adapters in this new Android training class
on transferring data using sync adapters. For populating list views,
particularly useful for things like news, you can use volley,
which you can find out all about from Ficus Kirkpatrick’s
awesome IO talk from earlier this year. One of the challenges of
having server-generated notifications based on matches
that you’re syncing across multiple devices is avoiding
spending your users with the same notifications on their
phone and on their tablet. Or if you’re someone like me,
on four of their phones and seven of their tablets. Now, one of the great new
features in Google Cloud Messaging is user notifications
are just part of the upstream messaging API. It’s available through
Google Play services. Now, this API lets you send a
message to other instances of your application. So if you dismiss a notification
on one device, you’re able to send a
notification to the client running on every device that
that notification is no longer relevant and it will
disappear. This is something you can see
in the latest version of Google Calendar. You can find our more details
from Francesca Nerieri’s IO talk from earlier this year,
where he went into a lot of detail and Google Cloud
Messaging and how you can use it within your app. That was a lot of information
to digest in a relatively short period of time. I hope you enjoyed this slightly
different take on the App Clinic. As always, we’d love to hear
your thoughts and feedback. In the meantime, I’ll leave
you with these key points. The refresh button is dead. Google Cloud Messaging allows
you to eliminate all unnecessary transfers
while maintaining those low latency updates. The transfers themselves should
all be handled by the sync adapter, which is not
only efficient, but also handles things like connectivity
changes to make sure your transfers always
get through. Context, anything from your
users’ location to their accent can help provide those
magical touches that will cause people to fall in
love with your apps. And if you’re an Australian
cricket fan, it’s probably best to avoid installing any
these apps for at least the next six to 12 months. Thank you for joining us this
week on the App Clinic. Check out developers.googl or the Android Dev YouTube channel
to find out more about our upcoming episodes of this and
other Android developer shows. My name is Reto Meier.

4 thoughts on “The App Clinic: Cricket

  1. Today's App Clinic is LIVE right now. @Reto Meier is going to do a visual redesign and architectural deep-dive into building the perfect sports-score tracking app.

    Using cricket apps ESPNcricinfo and CricBuzz as inspiration, he'll start by creating some mocks, and then dive into using GCM and SyncAdapters to create an app that keeps you up to date on the latest scores with near zero latency — without draining your battery.

    #AndroidDev #AppClinic #TheAshes

Leave a Reply

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