Keeping
data in sync with the cloud is an important part of many applications,
and the Google I/O App is no exception. To do this, we leverage the
standard Android mechanism for this purpose: a Sync Adapter.
Using a Sync Adapter has many benefits over using a more rudimentary
mechanism such as setting up recurring alarms, because the system
automatically handles the scheduling of Sync Adapters to optimize
battery life.
We store the data in a local SQLite database. However, rather than
having the whole application access that database directly, the
application employs another standard Android mechanism to control and
organize access to that data. This structure is, naturally, a Content Provider.
Only the content provider's implementation has direct access to the
SQLite database. All other parts of the app can only access data through
the Content Resolver. This allows for a very flexible decoupling
between the representation of the data in the database and the more
abstract view of that data that is used throughout the app.
The I/O app maintains with two main kinds of data: conference data
(sessions, speakers, rooms, etc) and user data (the user's personalized
schedule). Conference data is kept up to date with a one-way sync from a
set of JSON files stored in Google Cloud Storage, whereas user data goes through a two-way sync with a file stored in the user's Google Drive AppData folder.
Downloading Conference Data Efficiently
For a conference like Google I/O, conference data can be somewhat
large. It consists of information about all the sessions, rooms,
speakers, map locations, social hashtags, video library items and
others. Downloading the whole data set repeatedly would be wasteful both
in terms of battery and bandwidth, so we adopt a strategy to minimize
the amount of data we download and process.
This strategy is separating the data into several different JSON
files, and having them be referenced by a central master JSON file
called the manifest file. The URL of the manifest file is the only URL that is hard-coded into the app (it is defined by the MANIFEST_URL constant in Config.java). Note that the I/O app uses Google Cloud Storage to store and serve these files, but any robust hosting service accessible via HTTP can be used for the same purpose.
The first part of the sync process is checking if the manifest file
was changed since the app last downloaded it, and processing it only if
it's newer. This logic is implemented by the fetchConfenceDataIfNewer method in RemoteConferenceDataFetcher.
publicclassRemoteConferenceDataFetcher{// (...)publicString[] fetchConferenceDataIfNewer(String refTimestamp)throwsIOException{BasicHttpClient httpClient =newBasicHttpClient();
httpClient.setRequestLogger(mQuietLogger);// (...)// Only download if data is newer than refTimestampif(!TextUtils.isEmpty(refTimestamp)&&TimeUtils.isValidFormatForIfModifiedSinceHeader(refTimestamp)){
httpClient.addHeader("If-Modified-Since", refTimestamp);}}HttpResponse response = httpClient.get(mManifestUrl,null);int status = response.getStatus();if(status ==HttpURLConnection.HTTP_OK){// Data modified since we last checked -- process it!}elseif(status ==HttpURLConnection.HTTP_NOT_MODIFIED){// data on the server is not newer than our data - no work to do!returnnull;}else{// (handle error)}}// (...)}
Notice that we submit the HTTP If-Modified-Since header
with our request, so that if the manifest hasn't changed since we last
checked it, we will get an HTTP response code of HTTP_NOT_MODIFIED
rather than HTTP_OK, we will react by skipping the download and parsing
process. This means that unless the manifest has changed since we last
saw it, the sync process is very economical: it consists only of a
single HTTP request and a short response.
The manifest file's format is straightforward: it consists of
references to other JSON files that contain the relevant pieces of the
conference data:
The sync process then proceeds to process each of the listed data
files in order. This part is also implemented to be as economical as
possible: if we detect that we already have a cached version of a
specific data file, we skip it entirely and use our local cache instead.
This task is done by the processManifest method.
Then, each JSON file is parsed and the entities present in each one
are accumulated in memory. At the end of this process, the data is
written to the Content Provider.
Issuing Content Provider Operations Efficiently
The conference data sync needs to be efficient not only in the amount
of data it downloads, but also in the amount of operations it performs
on the database. This must be done as economically as possible, so this
step is also optimized: instead of overwriting the whole database with
the new data, the Sync Adapter attempts to preserve the existing
entities and only update the ones that have changed. In our tests, this
optimization step reduced the total sync time from 16 seconds to around 2
seconds on our test devices.
In order to accomplish this important third layer of optimization,
the application needs to know, given an entity in memory and its version
in the Content Provider, whether or not we need to issue content
provider operations to update that entity. Comparing the entity in
memory to the entity in the database field by field is one option, but
is cumbersome and slow, since it would require us to read every field.
Instead, we add a field to each entity called the import hashcode. The
import hashcode is a weak hash value generated from its data. For
example, here is how the import hashcode for a speaker is computed:
Every time an entity is updated in the database, its import hashcode
is saved with it as a database column. Later, when we have a candidate
for an updated version of that entity, all we need to do is compute the
import hashcode of the candidate and compare it to the import hashcode
of the entity in the database. If they differ, then we issue Content
Provider operations to update the entity in the database. If they are
the same, we skip that entity. This incremental update logic can be
seen, for example, in the makeContentProviderOperations method of the SpeakersHandler class:
The buildSpeaker and buildDeleteOperation
methods (omitted here for brevity) simply build the Content Provider
operations necessary to, respectively, insert/update a speaker or delete
a speaker from the Content Provider. Notice that this approach means we
only issue Content Provider operations to update a speaker if the
import hashcode has changed. We also deal with obsolete speakers, that
is, speakers that were in the database but were not referenced by the
incoming data, and we issue delete operations for those speakers.
Making Sync Robust
The sync adapter in the I/O app is responsible for several tasks,
amongst which are the remote conference data sync, the user schedule
sync and also the user feedback sync. Failures can happen in any of them
because of network conditions and other factors. However, a failure in
one of the tasks should not impact the execution of the other tasks.
This is why we structure the sync process as a series of independent
tasks, each protected by a try/catch block, as can be seen in the performSync method of the SyncHelper class:
// remote sync consists of these operations, which we try one by one (and// tolerate individual failures on each)finalint OP_REMOTE_SYNC =0;finalint OP_USER_SCHEDULE_SYNC =1;finalint OP_USER_FEEDBACK_SYNC =2;int[] opsToPerform = userDataOnly ?newint[]{ OP_USER_SCHEDULE_SYNC }:newint[]{ OP_REMOTE_SYNC, OP_USER_SCHEDULE_SYNC, OP_USER_FEEDBACK_SYNC};for(int op : opsToPerform){try{switch(op){case OP_REMOTE_SYNC:
dataChanged |= doRemoteSync();break;case OP_USER_SCHEDULE_SYNC:
dataChanged |= doUserScheduleSync(account.name);break;case OP_USER_FEEDBACK_SYNC:
doUserFeedbackSync();break;}}catch(AuthException ex){// (... handle auth error...)}catch(Throwable throwable){// (... handle other error...)// Let system know an exception happened:if(syncResult !=null&& syncResult.stats !=null){++syncResult.stats.numIoExceptions;}}}
When one particular part of the sync process fails, we let the system know about it by increasing syncResult.stats.numIoExceptions. This will cause the system to retry the sync at a later time, using exponential backoff.
When Should We Sync? Enter GCM.
It's very important for users to be able to get updates about
conference data in a timely manner, especially during (and in the few
days leading up to) Google I/O. A naïve way to solve this problem is
simply making the app poll the server repeatedly for updates. Naturally,
this causes problems with bandwidth and battery consumption.
To solve this problem in a more elegant way, we use GCM (Google Cloud
Messaging). Whenever there is an update to the data on the server side,
the server sends a GCM message to all registered devices. Upon receipt
of this GCM message, the device performs a sync to download the new
conference data. The GCMIntentService class handles the incoming GCM messages:
Notice that the onMessage method delivers the message to
the appropriate handler depending on the GCM message's "action" field.
If the action field is "sync_schedule", the application delivers the
message to an instance of the SyncCommand class, which
causes a sync to happen. Incidentally, notice that the implementation of
the SyncCommand class allows the GCM message to specify a jitter
parameter, which causes it to trigger a sync not immediately but at a
random time in the future within the jitter interval. This spreads out
the syncs evenly over a period of time rather than forcing all clients
to sync simultaneously, and thus prevents a sudden peak in requests on
the server side.
Syncing User Data
The I/O app allows the user to build their own personalized schedule
by choosing which sessions they are interested in attending. This data
must be shared across the user's Android devices, and also between the
I/O website and Android. This means this data has to be stored in the
cloud, in the user's Google account. We chose to use the Google Drive AppData folder for this task.
User data is synced to Google Drive by the doUserScheduleSync method of the SyncHelper
class. If you dive into the source code, you will notice that this
method essentially accesses the Google Drive AppData folder through the
Google Drive HTTP API, then reconciles the set of sessions in the data
with the set of sessions starred by the user on the device, and issues
the necessary modifications to the cloud if there are locally updated
sessions.
This means that if the user selects one session on their Android
device and then selects another session on the I/O website, the result
should be that both the Android device and the I/O website will show
that both sessions are in the user's schedule.
Also, whenever the user adds or removes a session on the I/O website,
the data on all their Android devices should be updated, and vice
versa. To accomplish that, the I/O website sends our GCM server a
notification every time the user makes a change to their schedule; the
GCM server, in turn, sends a GCM message to all the devices owned by
that user in order to cause them to sync their user data. The same
mechanism works across the user's devices as well: when one device
updates the data, it issues a GCM message to all other devices.
Conclusion
Serving fresh data is a key component of many Android apps. This
article showed how the I/O app deals with the challenges of keeping the
data up-to-date while minimizing network traffic and database changes,
and also keeping this data in sync across different platforms and
devices through the use of Google Cloud Storage, Google Drive and Google
Cloud Messaging.
02 September 2014
The Beautiful Design Summer 2014 Collection on Google Play
Posted by Marco Paglia, Android Design Team
It’s that time again! Last summer, we published the first Beautiful Design collection on Google Play, and updated it in the winter with a fresh set of beautifully crafted apps.
Since then, developers have been hard at work updating their existing
apps with new design ideas, and many new apps targeted to phones and
tablets have launched on Google Play sporting exquisite detail in their
UIs. Some apps are even starting to incorporate elements from material
design, which is great to see. We’re on the lookout for even more
material design concepts applied across the Google Play ecosystem!
Today, we're refreshing the Beautiful Design
collection with our latest favorite specimens of delightful design from
Google Play. As a reminder, the goal of this collection is to highlight
beautiful apps with masterfully crafted design details such as
beautiful presentation of photos, crisp and meaningful layout and
typography, and delightful yet intuitive gestures and transitions.
The newly updated Beautiful Design Summer 2014 collection includes:
Flight Track 5, whose gorgeously detailed flight info, full of maps and interactive charts, stylishly keeps you in the know.
Oyster,
a book-reading app whose clean, focused reading experience and
delightful discovery makes it a joy to take your library with you,
wherever you go.
Gogobot, an app whose bright colors and big images make exploring your next city delightful and fun.
Lumosity,
Vivino,
FIFA,
Duolingo,
SeriesGuide,
Spotify,
Runtastic,
Yahoo News Digest… each with delightful design details.
Airbnb, a veteran of the collection from this past winter, remains as they continue to finesse their app.
If you’re an Android designer or
developer, make sure to play with some of these apps to get a sense for
the types of design details that can separate good apps from great ones.
And remember to review the material design spec for ideas on how to design your next beautiful Android app!.
Join the discussion on
+Android Developers
25 August 2014
Powerful New Messaging Features with GCM
By Subir Jhanb, Google Cloud Messaging team
Developers from all segments are increasingly relying on Google Cloud
Messaging (GCM) to handle their messaging needs and make sure that
their apps stay battery-friendly. GCM has been experiencing incredible
momentum, with more than 100,000 apps registered, 700,000 QPS, and 300%
QPS growth over the past year.
At Google I/O we announced the general availability of several GCM capabilities, including the GCM Cloud Connection Server, User Notifications, and a new API called Delivery Receipt.
This post highlights the new features and how you can use them in your
apps. You can watch these and other GCM announcements at our I/O presentation.
Two-way XMPP messaging with Cloud Connection Server
XMPP-based Cloud Connection Server
(CCS) provides a persistent, asynchronous, bidirectional connection to
Google servers. You can use the connection to send and receive messages
between your server and your users' GCM-connected devices. Apps can now
send upstream messages using CCS, without needing to manage network
connections. This helps keep battery and data usage to a minimum. You
can establish up to 100 XMPP connections and have up to 100 outstanding
messages per connection. CCS is available for both Android and Chrome.
User notifications managed across multiple devices
Nowadays users have multiple devices and hence receive notifications
multiple times. This can reduce notifications from being a useful
feature to being an annoyance. Thankfully, the GCM User Notifications API
provides a convenient way to reach all devices for a user and help you
synchronise notifications including dismissals - when the user dismisses
a notification on one device, the notification disappears automatically
from all the other devices. User Notifications is available on both
HTTP and XMPP.
Insight into message status through delivery receipts
When sending messages to a device, a common request from developers
is to get more insight on the state of the message and to know if it was
delivered. This is now available using CCS with the new Delivery Receipt API.
A receipt is sent as soon as the message is sent to the endpoint, and
you can also use upstream for app level delivery receipt.
How to get started
If you’re already using GCM, you can take advantage of these new
features right away. If you haven't used GCM yet, you’ll be surprised at
how easy it is to set up — get started today! And remember, GCM is completely free no matter how big your messaging needs are.
To learn more about GCM and its new
features — CCS, user notifications, and Delivery Receipt — take a look
at the I/O Bytes video below and read our developer documentation.
Join the discussion on +Android Developers
05 August 2014
Material design in the 2014 Google I/O app
By Roman Nurik, lead designer for the Google I/O Android App
Every year for Google I/O, we publish an Android app for the conference
that serves two purposes. First, it serves as a companion for
conference attendees and those tuning in from home, with a personalized
schedule, a browsing interface for talks, and more. Second, and arguably
more importantly, it serves as a reference demo for Android design and
development best practices.
Last week, we announced that the Google I/O 2014 app source code
is now available, so you can go check out how we implemented some of
the features and design details you got to play with during the
conference. In this post, I’ll share a glimpse into some of our design
thinking for this year’s app.
On the design front, this year’s I/O app uses the new material design approach and features of the Android L Developer Preview
to present content in a rational, consistent, adaptive and beautiful
way. Let’s take a look at some of the design decisions and outcomes that
informed the design of the app.
Surfaces and shadows
In material design, surfaces and shadows play an important role in
conveying the structure of your app. The material design spec outlines a
set of layout principles
that helps guide decisions like when and where shadows should appear.
As an example, here are some of the iterations we went through for the
schedule screen: First iterationSecond iterationThird iteration
The first iteration was problematic for a number of reasons. First, the
single shadow below the app bar conveyed that there were two “sheets” of
paper: one for the app bar and another for the tabs and screen
contents. The bottom sheet was too complex: the “ink” that represents
the contents of a sheet should be pretty simple; here ink was doing too
much work, and the result was visual noise. An alternative could be to
make the tabs a third sheet, sitting between the app bar and content,
but too much layering can also be distracting.
The second and third iterations were stronger, creating a clear
separation between chrome and content, and letting the ink focus on
painting text, icons, and accent strips.
Another area where the concept of “surfaces”
played a role was in our details page. In our first release, as you
scroll the details screen, the top banner fades from the session image
to the session color, and the photo scrolls at half the speed beneath
the session title, producing a parallax effect. Our concern was that
this design bent the physics of material design too far. It’s as if the
text was sliding along a piece of paper whose transparency changed
throughout the animation.
A better approach, which we introduced in the app update on June
25th, was to introduce a new, shorter surface on which the title text
was printed. This surface has a consistent color and opacity. Before
scrolling, it’s adjacent to the sheet containing the body text, forming a
seam. As you scroll, this surface (and the floating action button
attached to it) rises above the body text sheet, allowing the body text
to scroll beneath it.
This aligns much better with the physics in the world of material
design, and the end result is a more coherent visual, interaction and
motion story for users. (See the code: Fragment, Layout XML)
Color
A key principle of material design is also that interfaces should be
“bold, graphic, intentional” and that the foundational elements of
print-based design should guide visual treatments. Let’s take a look at
two such elements: color and margins.
In material design, UI element color palettes generally consist of one primary and one accent color.
Large color fields (like the app bar background) take on the main 500
shade of the primary color, while smaller areas like the status bar use a
darker shade, e.g. 700.
The accent color is used more subtly throughout the app, to call
attention to key elements. The resulting juxtaposition of a tamer
primary color and a brighter accent, gives apps a bold, colorful look
without overwhelming the app’s actual content.
In the I/O app, we chose two accents, used in various situations. Most accents were Pink 500,
while the more conservative Light Blue 500 was a better fit for the Add
to Schedule button, which was often adjacent to session colors. (See the code: XML color definitions, Theme XML)
And speaking of session colors, we color each session’s detail screen
based on the session’s primary topic. We used the base material design
color palette with minor tweaks to ensure consistent brightness and
optimal contrast with the floating action button and session images.
Below is an excerpt from our final session color palette exploration file. Session colors, with floating action button juxtaposed to evaluate contrastDesaturated session colors, to evaluate brightness consistency across the palette
Margins
Another important “traditional print design” element that we thought about was margins, and more specifically keylines.
While we’d already been accustomed to using a 4dp grid for vertical
sizing (buttons and simple list items were 48dp, the standard action bar
was 56dp, etc.), guidance on keylines was new in material design.
Particularly, aligning titles and other textual items to keyline 2 (72dp
on phones and 80dp on tablets) immediately instilled a clean,
print-like rhythm to our screens, and allowed for very fast scanning of
information on a screen. Gestalt principles, for the win!
Grids
Another key principle in material design is “one adaptive design”:
A single underlying design system organizes interactions and
space. Each device reflects a different view of the same underlying
system. Each view is tailored to the size and interaction appropriate
for that device. Colors, iconography, hierarchy, and spatial
relationships remain constant.
Now, many of the screens in the I/O app represent collections of
sessions. For presenting collections, material design offers a number of
containers: cards, lists, and grids.
We originally thought to use cards to represent session items, but
since we’re mostly showing homogenous content, we deemed cards
inappropriate for our use case. The shadows and rounded edges of the
cards would add too much visual clutter, and wouldn’t aid in visually
grouping content. An adaptive grid was a better choice here; we could
vary the number of columns on screen size (see the code), and we were free to integrate text and images in places where we needed to conserve space.
Delightful details
Two of the little details we spent a lot of time perfecting in the
app, especially with the L Developer Preview, were touch ripples and the
Add to Schedule floating action button.
We used both the clipped and unclipped ripple styles throughout the
app, and made sure to customize the ripple color to ensure the ripples
were visible (but still subtle) regardless of the background. (See the code: Light ripples, Dark ripples)
But one of our favorite details in the app is the floating action
button that toggles whether a session shows up in your personalized
schedule or not:
We used a number of new API methods in the L preview (along with a fallback implementation) to ensure this felt right:
View.setOutline and setClipToOutline for circle-clipping and dynamic shadow rendering.
android:stateListAnimator to lift the button toward your finger on press (increase the drop shadow)
RippleDrawable for ink touch feedback on press
ViewAnimationUtils.createCircularReveal for the blue/white background state reveal
AnimatedStateListDrawable to define the frame animations for changes to icon states (from checked to unchecked)
The end result is a delightful and whimsical UI element that we’re
really proud of, and hope that you can draw inspiration from or simply
drop into your own apps.
What’s next?
And speaking of dropping code into your own apps, remember that all
the source behind the app, including L Developer Preview features and
fallback code paths, is now available, so go check it out to see how we implemented these designs.
We hope this post has given you some ideas for how you can use
material design to build beautiful Android apps that make the most of
the platform. Stay tuned for more posts related to this year’s I/O app
open source release over the coming weeks to get even more great ideas
for ways to deliver the best experience to your users.
Join the discussion on +Google Design
31 July 2014
Learn How UX Design can Make Your App More Successful
By Nazmul Idris, a Developer Advocate at Google who's passionate about Android and UX design
As a mobile developer, how do you create
5-star apps that your users will not just download, but love to use
every single day? How do you get your app noticed, and how do you drive
engagement? One way is to focus on excellence in design — from visual and interaction design to user research, in other words: UX design.
If you’re new to the world of UX design but want to embrace it to
improve your apps, we've created a new online course just for you. The UX Design for Mobile Developers
course teaches you how to put your designer hat on, in addition to your
developer hat, as you think about your apps' ideal user and how to meet
their needs.
The course is divided into a series of lessons, each of which gives
you practical takeaways that you can apply immediately to start seeing
the benefits of good UX design.
Without jargon or buzzwords, the course teaches you where you should
focus your attention, to bring in new users, keep existing users
engaged, and increase your app's ratings. You'll learn how to optimize
your app, rather than optimizing login/signup forms, and how to use
low-resolution wireframing.
After you take the course, you'll "level up" from being an excellent
developer to becoming an excellent design-minded developer.
Check out the video below to get a taste of what the course is like, and click through this short deck for an overview of the learning plan.
The full course materials — all the videos, quizzes, and forums — are
available for free for all students by selecting “View Courseware”.
Personalized ongoing feedback and guidance from Coaches is also
available to anyone who chooses to enroll in Udacity’s guided program.
If that’s not enough, for even more about
UX design from a developer's perspective, check out our YouTube UXD
series, on the AndroidDevelopers channel: http://bit.ly/uxdplaylist.
Android Developers at Udacity
Join the discussion on +Android Developers
30 July 2014
Google I/O 2014 App Source Code Now Available
By Bruno Oliveira, Tech Lead of the I/O app project
The source code for the 2014 version of the Google I/O app is now available. Since its first release on Google Play
a few weeks before the conference, the I/O app was downloaded by
hundreds of thousands of people, including on-site attendees, I/O
Extended event participants and users tuning in from home. If one of the
goals of the app is to be useful to conference attendees, the other
primary goal is to serve as a practical example of best practices for
Android app design and development.
In addition to showing how to implement a wide variety of features
that are useful for most Android apps, such as Fragments, Loaders,
Services, Broadcast Receivers, alarms, notifications, SQLite databases,
Content Providers, Action Bar and the Navigation Drawer, the I/O app
source code also shows how to integrate with several Google products and
services, from the Google Drive API to Google Cloud Messaging. It uses the material design approach, the Android L Preview APIs and full Android Wear integration with a packaged wearable app for sending session feedback.
To simplify the process of reusing and customizing the source code to
build apps for other conferences, we rewrote the entire sync adapter to
work with plain JSON files instead of requiring a server with a
specific API. These files can be hosted on any web server of the
developer's choice, and their format is fully documented.
Storing and syncing the user's data (that is, the personalized
schedule) is crucial part of the app. The source code shows how user
data can be stored in the Application Data folder
of the user's own Google Drive account and kept in sync across multiple
devices, and how to use Google Cloud Messaging to trigger syncs when
necessary to ensure the data is always fresh.
The project includes the source code to the App Engine app that can be reused to send GCM messages to devices to trigger syncs, as well as a module (called Updater) that can be adapted to read conference data from other backends to produce the JSON files that are consumed by the I/O app.
We are excited to share this source code with the developer community
today, and we hope it will serve as a learning tool, a source of
reusable snippets and a useful example of Android app development in
general. In the coming weeks we will post a few technical articles with
more detailed information about the IOSched source code to help bring
some insight into the app development process. We will continue to
update the app in the coming months, and as always, your pull requests
are very welcome!
Join the discussion on +Android Developers
29 July 2014
Grow with Google Play: Scaled Publishing and New App Insights
By Kobi Glick, Google Play team
If you're growing your business on Google Play, the Google Play Developer Console
is one of the most important tools at your disposal. At Google I/O, we
introduced a number of new changes that give you valuable insight into
how your app is performing. Here's an overview of some of the
improvements you can now take advantage of.
Publishing API for scaling your app operations
Today we're happy to announce that the Google Play Developer Publishing API
is now available to all developers. The API will let you upload APKs to
Beta testing, Staged rollout and Production, and integrate publishing
operations with your release processes and toolchain. The Publishing API
also makes it easier for you to manage your in-app products catalog,
provide tablet-specific screenshots, and localize your store listing
text and graphics. The Publishing API will help you focus on your core
business, with less time managing your releases, even as your business
grows to more apps and markets.
Actionable insights at the right time
Email notifications for alerts
Recently, we added Alerts in the Developer Console to let you know
when there are sudden changes in important stats like app installs,
ratings, and crashes. You can now turn on email notifications for Alerts
so that, even while you’re not in the Developer Console, you’ll be
informed of relevant events before they can have a broader effect on
your app. You can turn on email notifications for one or more of your
apps under Email Preferences in the Developer Console settings.
New Optimization Tips
You’ll now see new Optimization Tips with instructions when we detect
opportunities to improve your app. For example, we’ll let you know when
updated versions of APIs you use are available — such as new Google
Play in-app billing or Google Maps APIs. For games developers, we’ll
also surface opportunities to use Google Play game services that can
help improve users’ gaming experience and drive engagement. To see what
tips we suggest for you, go to your app in the Developer Console and
click on Optimization Tips.
Better data to inform your business decisions
Enhanced revenue statistics
To help you better understand your commercial success, we’ve enhanced
revenue statistics in the Finance section of the Developer Console. We
now let you see the average revenue per paying user (ARPPU) and give you
more ways to analyse buyer data, such as comparing returning buyers
(i.e., those who also made purchases in the past) to new buyers.
Bulk export of reviews
You can already engage with your users by reading and replying to
reviews in the Developer Console and we’ve now added bulk export of
reviews so you can download
and analyze your app’s reviews en masse. This is particularly useful if
you receive a large volume of reviews and want to perform your own
sentiment analysis.
Improved stats for beta releases and staged rollouts
Since last year’s launch, you’ve used beta testing to release alpha
and beta versions of your app, and staged rollout to gradually launch
your app to production. To help you make the most of this feature,
we’re now improving the way alpha, beta and staged rollout specific
stats are displayed. When viewing your app and crash statistics you can
now filter the app version by alpha, beta, or staged rollout to better
understand the impact of your testing.
Improved reporting of native crashes
If you develop in native code, we’ve improved the reporting and
presentation specifically for native crashes, with better grouping of
similar crashes and summarizing of relevant information.
Deep-linking to help drive engagement
Finally, we’ve also added website verification in the Developer Console, to enable deep-linking to your app
from search results. Deep-linking helps remind users about the apps
they already have. It is available through search for all apps that
implement app indexing. For example, if a user with the Walmart Android
app searches for “Chromecast where to buy”, they’ll go directly to the
Chromecast page in the Walmart app. The new App Indexing API is now open
to all Android developers, globally. Get started now.
We hope you find these features useful and take advantage of them so
that you can continue to grow your user base and improve your users’
experience. If you're interested in some other great tools for
distributing your apps, check out this blog post, or any of the sessions which have now been posted to the Google Developers Channel.
0 comments:
Post a Comment