Last Thursday at Google I/O 2017, we announced the winners of this year's Google Play Awards. Grab some popcorn and watch the award ceremony, we think it's just as fun as The Oscars. This year, we included a category to celebrate the achievements of developers who publish outstanding apps that have positive social impact.
In introducing this awards category, we were inspired by the UN's 17 Sustainable Development Goals. With the ability to reach over 1 billion active Android devices around the world, we think that app developers have a tremendous opportunity to impact Zero Hunger (SDG #2), Good Health and Wellbeing (SDG #3) and Quality Education (SDG #4), and many others. Read on to find out more about how this year's winner and finalists and impacting these goals.
Our work in supporting developer success in this area on Android and Google Play is just beginning. We would like to encourage Android developers with a focus on social impact to get in touch with us here at Google Play and to tell us about their app or game. It doesn't matter where you are based, what problems you are solving, or which countries you are targeting, we would like to hear your story and maybe we can help you grow faster and improve your app's quality.
The Google Play Award category winner, ShareTheMeal, generates large scale, global awareness for "Zero Hunger" and its users' donations pay for school meals, which are provided by the World Food Programme, in regions around the world experiencing food insecurity. Over 13 million meals have been donated via the app since launch!
This is a running, cycling and walking tracker app with a social impact twist. Charity Miles earns money for charity on your behalf for every mile you move, via its brand fitness exercise sponsors! Users have already donated $2 million to charity by recording over 40 million miles!
Peek Acuity allows anyone with an Android phone to easily measure visual acuity, which is one of the components of vision. It is designed by eye care professionals to be used to help identify people who need further examination by, for example, an optometrist or ophthalmologist. In developing countries, over XM [confirm number with Peek Vision] struggle with vision impairment and many don't have easy access to an eye care professional.
This app lets anyone translate phrases and words from Portuguese for Brazilian Sign Language (Libras) or from English to American Sign Language (ASL). This significantly reduces barriers to communication between the millions of people who depend on Libras or ASL as their lingua franca and others who have not had the opportunity to learn this form of communication.
This is not just a game, it's a quest to help scientists fight dementia! It sounds too good to be true but this really is a game, where simply by having loads of fun chasing creatures around magical seas and swamps, you can help to fight a disease that currently affects 45 million people worldwide. In fact playing SEA HERO QUEST for just 2 minutes will generate the equivalent of 5 hours of lab-based research data.
If you're working on an app or game with a positive social impact, don't forget to get in touch via this form and tick the "Social Impact app" checkbox.
Android TV brings rich app experiences and entertainment to the biggest screen in your house, and with Android O, we’re making it even easier for users to access content from their favorite apps. We’ve built a new, content-centric home screen experience for Android TV, and we're bringing the Google Assistant to the platform as well. These features put content that users want to access a few clicks, or spoken words, away.
The new Android TV home screen organizes video content into channels and programs in a way that’s familiar to TV viewers. Each Android TV app can publish multiple channels, which are represented as rows of programs on the home screen. Apps add relevant programs on each channel, and update these programs and channels as users access content or when new content is available. To help engage users, programs can include a video preview, which is automatically played when a user focuses on a program. Users can configure which channels they wish to see on the home screen, and the ordering of channels, so the themes and shows they’re interested in are quick and easy to access.
In addition to channels for you app, the top of the new Android TV home screen includes a quick launch bar for users' favorite apps, and a special Watch Next channel. This channel contains programs based on the viewing habits of the user.
The APIs for creating and maintaining channels and programs are part of the TvProvider APIs, which are distributed as an Android Support Library module with Android O. To get started using these APIs, visit the Android O Developer Preview site for an overview, and try out the Android TV Channels and Programs codelab for a first-hand experience building an Android TV app for Android O.
Later this year, Nexus Players will receive the new Android TV home experience as an OTA update. If you wish build and test apps for the new interface today, however, you can use the Android TV emulator or Nexus Player device images that are part of the latest Android O Developer Preview.
The Google Assistant on Android TV, coming later this year, will allow users to quickly find and access content using their voice. Because the Assistant is context-aware, it can help users narrow down what content to play. Users will also be able access the Assistant to control playback, even while a video or music is playing. And since the Assistant can control compatible smart home devices, a simple voice request can dim the lights to create an ideal movie viewing environment. When the Google Assistant comes to Android TV, it will launch in the US on Android devices running M, N, and O.
We're looking forward to seeing how developers take advantage of the new Android TV home screen. We welcome feedback, so please visit the Android TV Developer Community on G+ to share you thoughts and ideas!
When constructing the UnreadConversation builder, you are required to pass in a name. This is the name of the conversation that is displayed to the user when messages arrive.
UnreadConversation.Builder unreadConvBuilder = new UnreadConversation.Builder(conversationName) .setReadPendingIntent(msgHeardPendingIntent) .setReplyAction(msgReplyPendingIntent, remoteInput);
For one-on-one conversations, this is simply the name of the other participant. For group conversations, it is best to choose one of two options for the name:
Getting text to sound natural using a TTS system is a challenging problem. There are teams working hard to improve this, but there are steps you can take to create a better user experience with the current capabilities. The Android Auto messaging API does not yet have an option for pairing participants with individual messages in a group conversation. This is problematic for drivers when there are multiple unread messages from multiple participants in a group conversation, as the drivers cannot see which group member sent which message. One solution is to prepend the sender's name to the message whenever the sender changes so that the names are read aloud to the driver.
CharSequence currentSender = null; for (Message message : myMessages) { StringBuilder messageText = new StringBuilder(); CharSequence sender = message.getSender(); // Maybe append sender to indicate who is speaking. if (!TextUtils.isEmpty(sender) && !sender.equals(currentSender)) { if (currentSender != null) { // Punctuation will briefly pause TTS readout between senders. messageText.append(". "); } currentSender = sender; messageText.append(sender.toString().toLowerCase(Locale.getDefault())); // Punctuation will separate sender from message in TTS readout. messageText.append(": "); } messageText.append(message.getText()); unreadConvBuilder.addMessage(messageText.toString()); }
Some things to note about the above sample code:
In searching for how to handle group messaging, you may have noticed UnreadConversation#getParticipants. This can be confusing as there is no mechanism to add multiple participants in the builder. The builder implementation populates the array with the conversation name passed to its constructor. Internally, Android Auto uses the singular UnreadConversation#getParticipant, which returns the first element of the participants array, to populate the title in the notification view.
The Android Auto team is working on ways to make messaging with drivers simpler and more intuitive for app developers. Stay tuned for future updates so that you can continue to deliver a great user experience!
The subscription business model is one of the best ways to make more regular, reliable, and recurring revenue on Android and Google Play. In fact, both developers and users love subscription apps so much that we’ve seen a 10X growth in consumer spend over the past three years and double the number of active subscribers in the past year. Thousands of developers are offering subscriptions through Google Play and are already seeing success with our billing platform. That’s why we’ve been working hard to help you take advantage of this opportunity and give you greater insights into your business and Android users.
You've got a high-performing product with fantastic features and compelling content, but your business can't succeed without acquiring new users. In addition to free trials, intro pricing, flexible billing periods, and more, we recently launched the ability to pay for subscriptions with Google Play balance. Although people have already been using gift cards to pay for Play content in over 20 countries, the use of gift cards to pay for subscriptions in regions where cash is a popular form of payment, such as Latin America, has resulted in as high as a 15% increase in subscription spend.
But it's not just about acquiring new customers, it's about retaining the ones you have. That's why we are introducing account hold, where we work with you to block access to your content or service if a user's form of payment fails. This directly links a payment failure to the user losing access to your content and/or premium features, which is enough to get them to go and choose a new form of payment. When Keepsafe–the developer of Keepsafe Photo Vault, a photo locker for private pictures and videos with over 50M downloads–integrated account hold, their renewal rate on Android increased by 25%. We have over a dozen developers in early access today, and we will be announcing public availability at the end of June.
We know data is vital to running your business, so we're excited to announce a new subscriptions dashboard in the Play Console, and a new report on Android app subscribers.
The dashboard brings together subscription data like new subscribers, cancellations, and total subscribers. It also displays daily and 30-day rolling revenue data, and highlights your top-performing products. This will give visibility into your subscription products and users and will help guide your business decisions.
In addition to products and features, understanding people's needs is core to building a successful subscription business. We talked to 2,000 Android app subscribers in the US and UK and asked them how and why they use the apps they do. The results shared in 'Subscription apps on Google Play: User insights to help developers win' report highlight some of the opportunities for you to grow your subscriptions user base, set pricing strategies and learn to keep your users engaged, including:
Complications are bite-sized pieces of information displayed directly on the watch face. They can also be great shortcuts into your favorite apps. We introduced the Complications API last year to enable watch faces to receive data from any app that the user selects, and display the data to the user in a way that is stylistically coherent. Today, we are introducing four new tools to make it easier for watch face developers to integrate with the Complications API:
It's never been easier to integrate complications into your watch faces.
We have provided Android view components for building watch friendly user interfaces since the launch of Android Wear 1.0. Developers have told us that they would like to see these components open sourced. So, starting at Google I/O, we are open sourcing some components and providing some Android Wear UI components in the Android Support Library. This brings a number of advantages, including more consistent APIs with the rest of the Support Library, more frequent releases, and better responsiveness to developer feedback. We will:
In the first wave of these changes, we migrated the WearableRecyclerView, BoxInsetLayout and SwipeDismissFrameLayout classes to the new Android Wear UI Library. We expect the migration process to continue during 2017, and developers will have until mid-2018 to migrate to the new UI components. For additional information, see Using the Wear UI Library.
To get started with these new tools, simply update the Android Support Library in Android Studio and update your gradle build files to import the new support libraries. In addition to the documentation links above, check out the Google I/O session - Android Wear UI development best practice - where lead engineers for these tools will be on-hand to explain the technical details.
We will continue to update these tools over the next few months, based on your feedback. The sooner we hear from you, the more we can include, so don't be shy! Let us do some of the heavy lifting for your Android Wear apps and watch faces.
Thousands of apps and millions of stores accept Android Pay, a simpler and more secure mobile payment experience. Android Pay is now available in 10 markets, with more coming soon, including Brazil, Canada, Russia, Spain and Taiwan. And in addition to our already announced Visa and Mastercard partnerships, we'll soon enable a streamlined mobile checkout experience for PayPal users.
Yesterday, we announced the Google Payment API, which lets people pay in app or online with any verified credit or debit card saved to their Google Account, via products like Google Play, Chrome and YouTube.
For users, the option to pay with Google means breezing through checkout without needing to remember and type multiple lines of payment details. You simply choose your preferred card, enter a security code or authenticate with your Android device, and check out.
Developers who adopt this API can enable an easy-to-use checkout experience for their customers. Sign up for early access to the new Google Payment API.
In the upcoming months, we'll also enable people in the U.S. to send or receive payments via the Google Assistant. On your Google Home or Android device, it's as simple as saying "Ok Google, send $10 to Jane for pizza." All you need is a debit card linked to your Google account.
We're also announcing new ways for merchants to engage and reward customers before they walk into the store and after they've left.
The Card Linked Offers API drives customer loyalty by providing a new channel to deliver targeted offers, and Panera Bread is one of the first merchants who will roll out this new capability nationally. MyPanera members who save their loyalty card to Android Pay can discover offers and learn about new menu items, surfaced by Android Pay when they are at the store. The offer is redeemed when you use your MyPanera account at checkout.
We're also making it easier for Android Pay users to add loyalty programs. For example, Walgreens Balance Rewards® members who manually apply their loyalty account with a phone number and use Android Pay will receive a notification on their phone that easily enables them to link that loyalty card to Android Pay for future visits. This experience is powered by our smart tap technology, which Walgreens has fully deployed across their 8,000+ U.S. stores.
There's more—we're collaborating with Clover, a First Data company, to expand our smart tap technology beyond national retailers to businesses of all sizes. With the upcoming integration of smart tap in Clover's developer APIs, you'll be able to build Android apps for loyalty, coupon and gift card redemption and new features, such as order ahead and tap for pick up.
Visit developers.google.com/payments for the latest on all of our Google Payment, Loyalty and Offers APIs.
The Android operating system provides a strong foundation for building apps that run well on a wide range of devices and form factors. That being said, we've listened to developer feedback; Issues like complex lifecycles and the lack of a recommended app architecture make it challenging to write robust apps.
We need to make it easier — and more fun — to write robust apps, empowering developers to focus on areas where they can innovate. Today we're announcing a guide to Android app architecture along with a preview of Architecture Components. Rather than reinventing the wheel, we're also recognizing the work done by popular Android libraries.
We know that there's more than one way to write Android applications. What we're providing is a set of guidelines that can help you architect an Android application to work best with the unique ways that Android interacts. The Android framework has well-defined APIs to handle contact points with the OS, such as Activities, but these are entry points into your application, not building blocks for your application architecture; Framework components don't force you to separate your data model from your UI components, or provide a clear way to persist data independent of the lifecycle.
Android Architecture Components work together to implement a sane app architecture, while they individually address developer pain points. The first set of these components helps you:
Lifecycle Components New lifecycle-aware components provide constructs to tie core components of your applications to lifecycle events, removing explicit dependency paths.
A typical Android observation model would be to start observation in onStart() and stop observation in onStop(). This sounds simple enough, but often times you'll have several asynchronous calls happening at once, all managing the lifecycles of their component. It's easy to miss an edge case. The lifecycle components can help.
Lifecycle, LifecycleOwner, and LifecycleObserver
The core class for all of this is Lifecycle. It uses an enumeration for the current lifecycle state along with an enumeration for lifecycle events to track the lifecycle status for its associated component.
LifecycleOwner is an interface that returns a Lifecycle object from the getLifecycle() method, while LifecycleObserver is a class that can monitor the component's lifecycle events by adding annotations to its methods. Putting this all together, we can create lifecycle-aware components that can both monitor lifecycle events and query the current lifecycle state.
public class MyObserver implements LifecycleObserver { public MyObserver(Lifecycle lifecycle) { // Starts lifecycle observation lifecycle.addObserver(this); ... } public void startFragmentTransaction() { // Queries lifecycle state if (lifecycle.getState.isAtLeast(STARTED)) { // perform transaction } } // Annotated methods called when the associated lifecycle goes through these events @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) public void onResume() { } @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) public void onPause() { } } MyObserver observer = new MyObserver(aLifecycleOwner.getLifecycle());
LiveData is an observable lifecycle-aware data holder class. Your UI code subscribes to changes in the underlying data, tied into a LifecycleOwner, and LiveData makes sure the observer:
This helps to eliminate many pathways for memory leaks, and reduces crashes by avoiding updates to stopped activities.
LiveData can be observed by many listeners, each tied to a lifecycle owner such as a Fragment or Activity.
ViewModel is a helper class that contains UI data for an Activity or Fragment that serves to separate view data ownership from UI controller logic. A ViewModel is retained as long as the scope of its Activity/Fragment is alive, including when the Activity/Fragmentis destroyed and recreated due to a configuration change; This allows ViewModel to make UI data available to the recreated activity or fragment instance. Wrapping UI data stored within the ViewModel with LiveData provides the data an observable lifecycle-aware home. LiveData handles the notification side of things while the ViewModel makes sure that the data is retained appropriately.
The Android Architecture Components also simplify data persistence with the Room library. Room provides an object-mapping abstraction layer that allows fluent database access while harnessing the full power of SQLite.
The core framework provides built-in support for working with raw SQL content. Although these APIs are powerful, they are fairly low-level and require a great deal of time and effort to use:
Room takes care of these concerns for you while providing an abstraction layer over SQLite.
There are three major components in Room:
To use Room, you annotate the Java data objects you wish to persist as entities, create a database containing these entities, and define a DAO class with the SQL to access and modify the database.
@Entity public class User { @PrimaryKey private int uid; private String name; // Getters and Setters - required for Room public int getUid() { return uid; } public String getName() { return name; } public void setUid(int uid) { this.uid = uid; } public void setName(String name) { this.name = name; } } @Dao public interface UserDao { @Query("SELECT * FROM user") List getAll(); @Insert void insertAll(User... users); } @Database(entities = {User.class}, version = 1) public abstract class AppDatabase extends RoomDatabase { public abstract UserDao userDao(); }
Architecture Components are designed to be standalone, but they're most effective when they're incorporated into an effective app architecture. Today we're launching a Guide to App Architecture that shows how to build a robust, modular, and testable app using Architecture Components. The Guide has three main goals:
We recommend all developers who have had to deal with these problems read the Guide; Even if you're happy with your existing app architecture, the Guide will have useful principles and insights.
We're planning to continue being opinionated, and to continue to introduce new Architecture Components to make it easier for Android developers to make informed choices when architecting their applications. We encourage you to try the preview and provide feedback on what we're doing, because we're all in this together to make robust Android app development easier and more fun.
To learn more about Android Architecture, check out:
Today the Android team is excited to announce that we are officially adding support for the Kotlin programming language. Kotlin is a brilliantly designed, mature language that we believe will make Android development faster and more fun. It has already been adopted by several major developers — Expedia, Flipboard, Pinterest, Square, and others — for their production apps. Kotlin also plays well with the Java programming language; the effortless interoperation between the two languages has been a large part of Kotlin's appeal.
package helloWorld fun main(args: Array) { println("Hello World!") }
equals()
hashCode()
toString()
public class Customer { private String name; private String email; private String company; public Customer(String name) { this(name, "", ""); } public Customer(String name, String email) { this(name, email, ""); } public Customer(String name, String email, String company) { this.name = name; this.email = email; this.company = company; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getCompany() { return company; } public void setCompany(String company) { this.company = company; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Customer customer = (Customer) o; if (name != null ? !name.equals(customer.name) : customer.name != null) return false; if (email != null ? !email.equals(customer.email) : customer.email != null) return false; return company != null ? company.equals(customer.company) : customer.company == null; } @Override public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + (email != null ? email.hashCode() : 0); result = 31 * result + (company != null ? company.hashCode() : 0); return result; } @Override public String toString() { return "Customer{" + "name='" + name + '\'' + ", email='" + email + '\'' + ", company='" + company + '\'' + '}'; } }
data class Customer(var name: String, var email: String = "", var company: String = "")
var neverNull: String = "something" var mightBeNull: String? = null // "?" indicates this can be null if (neverNull.length > 0) { // This is OK … } if (mightBeNull.length > 0) { // Compiler catches this error for you … }
fun orderPizza(size: Size, pepperoni: Boolean, mushrooms: Boolean, ham: Boolean, pineapple: Boolean, pickles: Boolean, sausage: Boolean, peppers: Boolean, onion: Boolean) { ... } // Wait… did I just order pickles on my pizza? // Why do we even have that option? orderPizza(Size.LARGE, true, false, false, false, true, false, true, false)
fun orderPizza(size: Size, pepperoni: Boolean = false, mushrooms: Boolean = false, ham: Boolean = false, pineapple: Boolean = false, pickles: Boolean = false, sausage: Boolean = false, peppers: Boolean = false, onion: Boolean = false) { ... } orderPizza(Size.LARGE, ham = true, mushrooms = true)
// Please don't put this in your app! when { password.equals("password") -> println("Insecure password!") password.length < 4 -> println("Too short!") else -> { println("Secure password!") } }
if (obj is String) { // Compiler casts obj to a String for you. // (Would work with && instead of nested ifs too.) if (obj.length > 0) { … } }
// Assume reasonable implementations of Cat and Dog when (obj) { is Cat -> obj.meow(...) is Dog -> obj.woof(...) else -> { … } }
toPigLatin
// The "String." prefix indicates that this method should // extend the existing String class fun String.toPigLatin() : String { ... } val plainOldString : String = "some text" // Can now call toPigLatin as if were a method on String println(plainOldString.toPigLatin()) // Or: println("some text".toPigLatin())
data class Order(val itemCode: String, val quantity: Int, val price: Float)
fun getOrder(...): Order { ... return Order(itemCode, quantity, price); }
Order
what
howMany
howMuch
val (what, howMany, howMuch) = getOrder(...)
fun allStrings(collection: Collection)= collection.all { it is String }
fun generatePage(withEmphasis : Boolean) { val result = html { head { title { +"Kotlin Builders" } } body { h1 { +"Kotlin Builders" } p { +"This is " if (withEmphasis) b { +"really " } +"interesting" a(href = "https://goo.gl/rHwJio") { +"More here" } } } } println(result) }
html
head
body
withEmphasis
if (withEmphasis)
Earlier this year, we began testing Android Instant Apps, a new way to run Android apps without requiring installation. Thanks to our incredible developer community, we received a ton of feedback that has helped us refine the end-to-end product experience.
Today, we're opening Android Instant Apps to all developers, so anyone can build and publish an instant app. There are also more than 50 new experiences available for users to try from a variety of developers, such as HotPads, Jet, the New York Times, Vimeo, and One Football. While these experiences have only been live for a short amount of time, the early data shows positive results. For example, Jet and HotPads are seeing double digit increases in purchases and leads generated.
Feedback from our early partners has directly shaped the development tools we're making available to all of you today.
To get started building an instant app, head over to developer.android.com and download the latest preview of Android Studio 3.0 and the Android Instant Apps SDK. You'll continue to use a single codebase. Android Studio provides the tools you need to modularize your app so that features can be downloaded as needed. Every app is different, but we've seen with our early partners that with the latest tools, instant app development typically takes about 4-6 weeks.
Once you've built your app, the Play Console provides support for distributing your instant app. You just upload your instant app APKs together with your installable APK.
Instant Apps continues to ramp up on the latest Android devices in more than 40 countries. And with Android O, we've gone further, building a new, more efficient runtime sandbox for instant apps, sharable support libraries to reduce app size, and launcher integration support.
To learn more, visit g.co/InstantApps. We're also hosting a session "Introduction to Android Instant Apps" on Thursday, May 18 from 1:30-2:30 PM PT at the conference to dig deeper into the topic. You'll also be able to watch the live stream on Google I/O YouTube channel.
We are excited to see what experiences you create with Instant Apps!