Make the most of Notifications with the redesigned Wear OS by Google


Posted by Hoi Lam, Lead Developer Advocate, Wear OS by Google

Today we announced that we are evolving the design of Wear OS by Google to help you get the most out of your time – providing quicker access to your information and notifications. Notifications can come from the automatic bridging of the phone’s notification or be generated by a local Wear app running on the watch. Whether you are a phone developer, a Wear app developer, or both, there are a few things you will need to know about the new notification stream.

The new notification stream

Until now, each notification took up the entire screen in Wear OS. Although this provided more space to include things like inline action, it also meant it took a long time for the user to go through all their notifications. The new notification stream is more compact, and can display multiple notifications on the same screen. This means users can process their notification streams more quickly.

What this means for developers

  • Concise notification content is even more important. The new unexpanded notification on Wear will show up to three lines of text. Because this is already more information than a single line unexpanded notification on the user’s phone, if your notification works on the phone unexpanded, it should be fine on Wear.
  • Brand notification with color. The default title and icon color for notification is white. Developers can now convey their brand identities by customizing the color of the title and icon tint using setColor.
  • Custom notification layout will no longer be supported. Previously developers used setDisplayIntent to inflate a custom activity inside the notification stream. We have found that the custom layout often does not take into account of the device form factor, and is difficult to keep up to date as Wear OS’s notification experience evolves. As a result, we will no longer support this in notifications.
  • Inline action is being reviewed. To save space, the new layout no longer display inline action in the stream and setHintDisplayActionInline will be ignored. Users can continue to access notification actions including inline action when they tap to expand the notification. Our design team is reviewing whether we should include inline action in a future release. As a result, before a decision is made, we are not deprecating the related APIs. We will keep the developer community updated in due course.

As always, the current best practices for notification still apply. In particular, for messaging apps developers, we strongly encourage the use of MessagingStyle notification and enabling on-device Smart Reply through setAllowGeneratedReplies.

We will start rolling these changes out in the next month, so watch for updates on your Wear OS by Google smartwatch!

Verifying your Google Assistant media action integrations on Android


Posted by Nevin Mital, Partner Developer Relations

The Media Controller Test (MCT) app is a powerful tool that allows you to test the intricacies of media playback on Android, and it’s just gotten even more useful. Media experiences including voice interactions via the Google Assistant on Android phones, cars, TVs, and headphones, are powered by Android MediaSession APIs. This tool will help you verify your integrations. We’ve now added a new verification testing framework that can be used to help automate your QA testing.

The MCT is meant to be used in conjunction with an app that implements media APIs, such as the Universal Android Music Player. The MCT surfaces information about the media app’s MediaController, such as the PlaybackState and Metadata, and can be used to test inter-app media controls.

The Media Action Lifecycle can be complex to follow; even in a simple Play From Search request, there are many intermediate steps (simplified timeline depicted below) where something could go wrong. The MCT can be used to help highlight any inconsistencies in how your music app handles MediaController TransportControl requests.

Timeline of the interaction between the User, the Google Assistant, and the third party Android App for a Play From Search request.

Previously, using the MCT required a lot of manual interaction and monitoring. The new verification testing framework offers one-click tests that you can run to ensure that your media app responds correctly to a playback request.

Running a verification test

To access the new verification tests in the MCT, click the Test button next to your desired media app.

MCT Screenshot of launch screen; contains a list of installed media apps, with an option to go to either the Control or Test view for each.

The next screen shows you detailed information about the MediaController, for example the PlaybackState, Metadata, and Queue. There are two buttons on the toolbar in the top right: the button on the left toggles between parsable and formatted logs, and the button on the right refreshes this view to display the most current information.

MCT Screenshot of the left screen in the Testing view for UAMP; contains information about the Media Controller's Playback State, Metadata, Repeat Mode, Shuffle Mode, and Queue.

By swiping to the left, you arrive at the verification tests view, where you can see a scrollable list of defined tests, a text field to enter a query for tests that require one, and a section to display the results of the test.

MCT Screenshot of the right screen in the Testing view for UAMP; contains a list of tests, a query text field, and a results display section.

As an example, to run the Play From Search Test, you can enter a search query into the text field then hit the Run Test button. Looks like the test succeeded!

MCT Screenshot of the right screen in the Testing view for UAMP; the Play From Search test was run with the query 'Memories' and ended successfully.

Below are examples of the Pause Test (left) and Seek To test (right).

MCT Screenshot of the right screen in the Testing view for UAMP; a Pause test was run successfully. MCT Screenshot of the right screen in the Testing view for UAMP; a Seek To test was run successfully.

Android TV

The MCT now also works on Android TV! For your media app to work with the Android TV version of the MCT, your media app must have a MediaBrowserService implementation. Please see here for more details on how to do this.

On launching the MCT on Android TV, you will see a list of installed media apps. Note that an app will only appear in this list if it implements the MediaBrowserService.

Android TV MCT Screenshot of the launch screen; contains a list of installed media apps that implement the MediaBrowserService.

Selecting an app will take you to the testing screen, which will display a list of verification tests on the right.

Android TV MCT Screenshot of the testing screen; contains a list of tests on the right side.

Running a test will populate the left side of the screen with selected MediaController information. For more details, please check the MCT logs in Logcat.

Android TV MCT Screenshot of the testing screen; the Pause test was run successfully and the left side of the screen now displays selected MediaController information.

Tests that require a query are marked with a keyboard icon. Clicking on one of these tests will open an input field for the query. Upon hitting Enter, the test will run.

Android TV MCT Screenshot of the testing screen; clicking on the Seek To test opened an input field for the query.

To make text input easier, you can also use the ADB command:

adb shell input text [query]

Note that ‘%s’ will add a space between words. For example, the command adb shell input text hello%sworld will add the text “hello world” to the input field.

What’s next

The MCT currently includes simple single-media-action tests for the following requests:

  • Play
  • Play From Search
  • Play From Media ID
  • Play From URI
  • Pause
  • Stop
  • Skip To Next
  • Skip To Previous
  • Skip To Queue Item
  • Seek To

For a technical deep dive on how the tests are structured and how to add more tests, visit the MCT GitHub Wiki. We’d love for you to submit pull requests with more tests that you think are useful to have and for any bug fixes. Please make sure to review the contributions process for more information.

Check out the latest updates on GitHub!

Exclusive new organic acquisition insights on the Google Play Console


Posted by Tom Grinsted, Product Manager, Google Play

We’ve updated the Play Console acquisition reports to give new insights into what users do on the Play Store to discover your app. It’s a great way to super-charge your App Store Optimization (ASO) and onboarding experience.

One of the things every developer wants to know is how people discover their app or game. User acquisition reports in the Google Play Console are a great way to understand this. For many apps and games, a stand-out source is Organic traffic — it’s usually the largest or second largest source of store listing visits and installs.

Organic traffic is made up of people who come to your store listing while exploring or searching the Play Store. These visitors might find your app in a seasonal collection, from featuring, or while searching for a specific use case or term.

Until recently, this traffic has been bundled together with no breakdown of data into user behavior. With our latest updates we have changed this by introducing new and exclusive acquisition insights to the Google Play Console. These enable you to understand what people in the Play Store do to discover your app or game. They reveal how many people discover your app through exploring the store, and how many search to find your app, and even the search terms they use!

App Store Optimization (ASO) is vital to driving your organic traffic and this update enables you to do this with more data and better understanding.

A new data breakdown

When you visit the user acquisition report, the first change you’ll notice is that organic traffic is broken down. This breakdown means you can see how people arrive at your store listing by searching or exploring (actions that aren’t search like browsing the homepage, visiting a category list, or viewing related apps).

This change has been of immediate benefit to developers, enabling their growth teams to optimize acquisition strategies. For example, Scopely found that:

“Isolating [explore] from search and then a deeper dive into search gives the whole organic picture. It allows us to focus on acquisition areas that really matter.” Dorothee Pinlet, VP Partnerships, Scopely


Click through for more insights

From the new search row, you can click-through to see the aggregate number of people using different search terms to find your store listing, and which of those lead to the most installs. This breakdown is a view into the Play Store that has not been available before.

Our pilot partners, who helped us refine the feature ahead of launch, were very happy with how this data has helped them make more informed decisions.

Evernote found that the breakdown:

“… offers surprising and actionable insights about the effectiveness of search terms in driving installs and retained users.”
May Allen, Product Manager, Evernote

Some partners changed their in-app onboarding experience to highlight features that reflected the search terms that were driving installs, to better meet user expectations. While others evaluated if their influencer marketing was having an impact by looking for their advocates’ names in the search results after adding them to descriptions.

Better coverage

The new organic data also includes information about when people visiting the Play Store saw previews of your listings, not just when they visited your full page. People see these previews when they make certain searches, such as searching directly for a brand or app name. As well as more generally in some markets. This new information gives you more visibility into where people see your assets. It helps you decide how to optimize these assets, for instance by ensuring that your screenshots are impactful. And when you come to do that, you’ve got Store Listing Experiments.

This change means that your total reported visits and installs are likely to increase as of July 30, 2018. This increase is because previews will be counted as listing views, previously they were included in the category “Installs without store listing visits”.

Putting the data to work

The developers who had the opportunity to test Organic breakdowns have given feedback that they loved them. They’ve also been kind enough to share some insights into how they plan to use the data. Perhaps these thoughts on how to use the data will spark some ideas for your business.

Some developers will be using this new data to evaluate their acquisition strategies by looking at the breakdown between explore and search. They will use this breakdown to evaluate the impact of exploring behaviors, especially around times when the app has been featured on the Play Store.

Using the information about popular search terms, several developers plan to change their app or game’s Google Play listing to reflect user interests better. This change involves adjusting the descriptions and screenshots to tie more directly into the top search terms.

Others plan to use the insight provided by search term information to optimize their in-app onboarding. Here they plan to make sure that the onboarding talks about the features related to the most popular searches people made when discovering their app or game, highlighting and reinforcing the benefits.

Final word

Our team is always thinking about the tools we can build to help you optimize the discovery and installation of your app or game from the Play Store. Organic breakdowns is just one of these tools, a new way to help drive your success. Ultimately, your success is what we work towards. Organic breakdowns give you a more comprehensive picture of how people discover you on the Play Store so you can optimize your store presence, turning more visits into installs, and more installs into engaged users.

How useful did you find this blog post?


Evolution of Android Security Updates


Posted by Dave Kleidermacher, VP, Head of Security – Android, Chrome OS, Play

At Google I/O 2018, in our What’s New in Android Security session, we shared a brief update on the Android security updates program. With the official release of Android 9 Pie, we wanted to share a more comprehensive update on the state of security updates, including best practice guidance for manufacturers, how we’re making Android easier to update, and how we’re ensuring compliance to Android security update releases.

Commercial Best Practices around Android Security Updates

As we noted in our 2017 Android Security Year-in-Review, Android’s anti-exploitation strength now leads the mobile industry and has made it exceedingly difficult and expensive to leverage operating system bugs into compromises. Nevertheless, an important defense-in-depth strategy is to ensure critical security updates are delivered in a timely manner. Monthly security updates are the recommended best practice for Android smartphones. We deliver monthly Android source code patches to smartphone manufacturers so they may incorporate those patches into firmware updates. We also deliver firmware updates over-the-air to Pixel devices on a reliable monthly cadence and offer the free use of Google’s firmware over-the-air (FOTA) servers to manufacturers. Monthly security updates are also required for devices covered under the Android One program.

While monthly security updates are best, at minimum, Android manufacturers should deliver regular security updates in advance of coordinated disclosure of high severity vulnerabilities, published in our Android bulletins. Since the common vulnerability disclosure window is 90 days, updates on a 90-day frequency represents a minimum security hygiene requirement.

Enterprise Best Practices

Product security factors into purchase decisions of enterprises, who often consider device security update cadence, flexibility of policy controls, and authentication features. Earlier this year, we introduced the Android Enterprise Recommended program to help businesses make these decisions. To be listed, Android devices must satisfy numerous requirements, including regular security updates: at least every 90 days, with monthly updates strongly recommended. In addition to businesses, consumers interested in understanding security update practices and commitment may also refer to the Enterprise Recommended list.

Making Android Easier to Update

We’ve also been working to make Android easier to update, overall. A key pillar of that strategy is to improve modularity and clarity of interfaces, enabling operating system subsystems to be updated without adversely impacting others. Project Treble is one example of this strategy in action and has enabled devices to update to Android P more easily and efficiently than was possible in previous releases. The modularity strategy applies equally well for security updates, as a framework security update can be performed independently of device specific components.

Another part of the strategy involves the extraction of operating system services into user-mode applications that can be updated independently, and sometimes more rapidly, than the base operating system. For example, Google Play services, including secure networking components, and the Chrome browser can be updated individually, just like other Google Play apps.

Partner programs are a third key pillar of the updateability strategy. One example is the GMS Express program, in which Google is working closely with system-on-chip (SoC) suppliers to provide monthly pre-integrated and pre-tested Android security updates for SoC reference designs, reducing cost and time to market for delivering them to users.

Security Patch Level Compliance

Recently, researchers reported a handful of missing security bug fixes across some Android devices. Initial reports had several inaccuracies, which have since been corrected. We have been developing security update testing systems that are now making compliance failures less likely to occur. In particular, we recently delivered a new testing infrastructure that enables manufacturers to develop and deploy automated tests across lower levels of the firmware stack that were previously relegated to manual testing. In addition, the Android build approval process now includes scanning of device images for specific patterns, reducing the risk of omission.

Looking Forward

In 2017, about a billion Android devices received security updates, representing approximately 30% growth over the preceding year. We continue to work hard devising thoughtful strategies to make Android easier to update by introducing improved processes and programs for the ecosystem. In addition, we are also working to drive increased and more expedient partner adoption of our security update and compliance requirements. As a result, over coming quarters, we expect the largest ever growth in the number of Android devices receiving regular security updates.

Bugs are inevitable in all complex software systems, but exploitability of those bugs is not. We’re working hard to ensure that the incidence of potentially harmful exploitation of bugs continues to decline, such that the frequency for security updates will reduce, not increase, over time. While monthly security updates represents today’s best practice, we see a future in which security updates becomes easier and rarer, while maintaining the same goal to protect all users across all devices.

Streamlining the developer experience for instant games


Posted by Vlad Zavidovych, Software Engineer; Artem Yudin, Software Engineer

Google Play Instant enables people to experience your game or app natively without having to go through a full installation process. Removing the friction of installing is a great way to increase engagement, conversions, and lifetime value of your users.

Today, we’ve made it easier to build instant games and apps by removing the URL requirement. Previously, in order to publish an instant game you had to create a web destination for it. The website also had to be connected to the instant game through intent filters and digital asset links verification.

Now, it is no longer required to add URL-based intent filters to your instant game. People will be able to access the instant experience through a ‘Try Now’ button in the Play Store or Play Games apps, via deep link API, and in the future through the app ads.

While being particularly helpful for games which often don’t have a corresponding website, the new URL-less functionality is available to both game and app developers.

How to develop and publish an instant game without adding URL support

Game developers using Unity or the latest Cocos Creator can take advantage of URL-less instant games by simply leaving the URL fields blank in the setup process.

However, if you have your own game engine or have built your game from scratch in C++, check the AndroidManifest to make sure it has the following intent filter declaration:

<intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

Starting with Android Studio 3.2, you can create a new instant game, or convert your existing game, without associating a URL with it. In fact, this is now the default behavior. Here is a run through the process:

  1. First, make sure you’re running Android Studio 3.2 or newer by either updating or downloading it here. Make sure to install Instant Apps Development SDK 1.3.0 or higher from Android SDK Manager.
  2. Then download a sample instant app from GitHub. In Android Studio, click File → New → Import Project… and import the downloaded “urlless” sample.
  3. Lastly, after gradle tasks are finished, click the green “Run” button with “instantapp” configuration.

You should see an instant game on your attached device. Instant runtime found and launched the entry point activity in your game with the ACTION_MAIN and CATEGORY_LAUNCHER intent filter.

Once you are ready to publish the sample instant game:

  1. Give your sample game a unique applicationId in app/build.gradle file by replacing existing applicationId – we don’t want different applications with the same id.
  2. Generate signed APKs for both installable and instant version of our sample game.
    • In Android Studio, Build → Generate Signed Bundle / APK…
    • Choose APK for both “app” and “instantapp” modules.
  3. In the Play Console, create a new application, upload APK under “App Releases” tab, and then upload “instantapp-release.zip” under “Android Instant Apps” tab.
    • The installable app must be rolled out before the instant one.
  4. The rollout process may be familiar to most Android developers, but here’s a step-by-step guide in case you run into any issues.

Once you publish your instant game, people can access it via a ‘Try Now’ button in Play Store within 24 hours or sooner. You can also send traffic to your instant game using the deep link API:

market://details?id=MY.PACKAGE.NAME&launch=true&referrer=myreferrer

MY.PACKAGE.NAME refers to applicationId that you have replaced in app/build.gradle file.

What’s next?

With the launch of Android App Bundle we are excited to further simplify the developer experience for Google Play Instant. In the coming months we are making it possible to deliver your app’s or game’s dynamic features instantly from the same bundle as your installable app or game. Stay tuned!

Check out more information on Google Play Instant, or feel free to ask a question on Stack Overflow, or report an issue to our public tracker.

How useful did you find this blogpost?

Alternative input methods for Android TV


Posted by Benjamin Baxter, Developer Advocate and Bacon Connoisseur

Hero image displaying phones and tvs communicating to each other

All TVs have the same problem with keyboard input: It is very cumbersome to hunt and peck for each letter using a D-pad with a remote. And if you make a mistake, trying to correct it compounds the problem.

APIs like Smart Lock and Autofill, can ease user’s frustrations, but for certain types of input, like login, you need to collect complex input that is difficult for users using the on-screen keyboard.

With the Nearby Connections API, you can use a second screen to gather input from the user with less friction.

How Nearby Connections works

From the documentation:

“Nearby Connections is an offline peer-to-peer socket model for communication based on advertising and discovering devices in proximity.

Usage of the API falls into two phases: pre-connection, and post-connection.

In the pre-connection phase, Advertisers advertise themselves, while Discoverers discover nearby Advertisers and send connection requests. A connection request from a Discoverer to an Advertiser initiates a symmetric authentication flow that results in both sides independently accepting (or rejecting) the connection request.

After a connection request is accepted by both sides, the connection is established and the devices enter the post-connection phase, during which both sides can exchange data.”

In most cases the TV is the advertiser and the phone is the discoverer. In the example below, the assumed second device is a phone. The API and patterns described in this article are not limited to a phone. For example, a tablet could also be the second screen device.

The TV is the Advertiser and the phone is the Discoverer.

Login Example

There are many times when keyboard input is required. Authenticating users and collecting billing information (like zip codes and name on card) are common cases. This example handles a login flow that uses a second screen to see how Nearby Connections can help reduce friction.

1. The user opens your app on her TV and needs to login. You can show a screen of options similar to the setup flow for a new TV.

Android TV setup with prompt to continue on the user's phone.

2. After the user chooses to login with their phone, the TV should start advertising and send the user to the associated login app on their phone, which should start discovering.

There are a variety of solutions to open the app on the phone. As an example, Android TV’s setup flow has the user open the corresponding app on their mobile device. Initiating the hand-off is a more a UX concern than a technology concern.

Animation showing setup hand off from TV to phone.

3. The phone app should display the advertising TV and prompt the user to initiate the connection. After the (encrypted — see Security Considerations below for more on this) connection is established the TV can stop advertising and the phone can stop discovering.

Advertising/Discovery using Nearby Connections for hours on end can affect a device’s battery. While this is not usually an issue for a plugged-in TV, it can be for mobile devices, so be conscious about stopping advertising and discovery once they’re no longer needed.”

4. Next, the phone can start collecting the user’s input. Once the user enters their login information, the phone should send it to the TV in a BYTES payload over the secure connection.

5. When the TV receives the message it should send an ACK (using a BYTES payload) back to the phone to confirm delivery.

6. When the phone receives the ACK, it can safely close the connection.

The following diagram summarizes the sequence of events:

Sequence diagram of order of events to setup a connect and send a message.

UX considerations

Nearby Connections needs location permissions to be able to discover nearby devices. Be transparent with your users. Tell them why they need to grant the location permission on their phone.

Since the TV is advertising, it does not need location permissions.

Start advertising: The TV code

After the user chooses to login on the phone, the TV should start advertising. This is a very simple process with the Nearby API.

override fun onGuidedActionClicked(action: GuidedAction?) { super.onGuidedActionClicked(action) if( action == loginAction ) { // Update the UI so the user knows to check their phone navigationFlowCallback.navigateToConnectionDialog() doStartAdvertising(requireContext()) { payload -> handlePayload(payload) } }
}

When the user clicks a button, update the UI to tell them to look at their phone to continue. Be sure to offer a way to cancel the remote login and try manually with the cumbersome onscreen keyboard.

This example uses a GuidedStepFragment but the same UX pattern applies to whatever design you choose.

Advertising is straightforward. You need to supply a name, a service id (typically the package name), and a `ConnectionLifeCycleCallback`.

You also need to choose a strategy that both the TV and the phone use. Since it is possible that the users has multiple TVs (living room, bedroom, etc) the best strategy to use is P2P_CLUSTER.

Then start advertising. The onSuccessListener and onFailureListener tell you whether or not the device was able to start advertising, they do not indicate a device has been discovered.

fun doStartAdvertising(context: Context) { Nearby.getConnectionsClient(context).startAdvertising( context.getString(R.string.tv_name), context.packageName, connectionLifecycleCallback, AdvertisingOptions.Builder().setStrategy(Strategy.P2P_CLUSTER).build() ) .addOnSuccessListener { Log.d(LoginStepFragment.TAG, "We are advertising!") } .addOnFailureListener { Log.d(LoginStepFragment.TAG, "We cannot start advertising.") Toast.makeText( context, "We cannot start advertising.", Toast.LENGTH_LONG) .show() }
} 

The real magic happens in the `connectionLifecycleCallback` that is triggered when devices start to initiate a connection. The TV should accept the handshake from the phone (after performing the necessary authentication — see Security Considerations below for more) and supply a payload listener.

val connectionLifecycleCallback = object : ConnectionLifecycleCallback() { override fun onConnectionInitiated( endpointId: String, connectionInfo: ConnectionInfo ) { Log.d(TAG, "Connection initialized to endpoint: $endpointId") // Make sure to authenticate using `connectionInfo.authenticationToken` // before accepting Nearby.getConnectionsClient(context) .acceptConnection(endpointId, payloadCallback) } override fun onConnectionResult( endpointId: String, connectionResolution: ConnectionResolution ) { Log.d(TAG, "Received result from connection: ${connectionResolution.status.statusCode}") doStopAdvertising() when (connectionResolution.status.statusCode) { ConnectionsStatusCodes.STATUS_OK -> { Log.d(TAG, "Connected to endpoint: $endpointId") otherDeviceEndpointId = endpointId } else -> { otherDeviceEndpointId = null } } } override fun onDisconnected(endpointId: String) { Log.d(TAG, "Disconnected from endpoint: $endpointId") otherDeviceEndpointId = null }
} 

The payloadCallback listens for the phone to send the login information needed. After receiving the login information, the connection is no longer needed. We go into more detail later in the Ending the Conversation section.

Discovering the big screen: The phone code

Nearby Connections does not require the user’s consent. However, the location permission must be granted in order for discovery with Nearby Connections to work its magic. (It uses BLE scanning under the covers.)

After opening the app on the phone, start by prompting the user for location permission if not already granted on devices running Marshmallow and higher.

Once the permission is granted, start discovering, confirm the connection, collect the credentials, and send a message to the TV app.

Discovering is as simple as advertising. You need a service id (typically the package name — this should be the same on the Discoverer and Advertiser for them to see each other), a name, and a `EndpointDiscoveryCallback`. Similar to the TV code, the flow is triggered by callbacks based on the connection status.

Nearby.getConnectionsClient(context).startDiscovery( context.packageName, mobileEndpointDiscoveryCallback, DiscoveryOptions.Builder().setStrategy(Strategy.P2P_CLUSTER).build() ) .addOnSuccessListener { // We're discovering! Log.d(TAG, "We are discovering!") } .addOnFailureListener { // We were unable to start discovering. Log.d(TAG, "We cannot start discovering!") } 

The Discoverer’s listeners are similar to the Advertiser’s success and failure listeners; they signal if the request to start discovery was successful or not.

Once you discover an advertiser, the `EndpointDiscoveryCallback` is triggered. You need to keep track of the other endpoint to know who to send the payload, e.g.: the user’s credentials, to later.

val mobileEndpointDiscoveryCallback = object : EndpointDiscoveryCallback() { override fun onEndpointFound( endpointId: String, discoveredEndpointInfo: DiscoveredEndpointInfo ) { // An endpoint was found! Log.d(TAG, "An endpoint was found, ${discoveredEndpointInfo.endpointName}") Nearby.getConnectionsClient(context) .requestConnection( context.getString(R.string.phone_name), endpointId, connectionLifecycleCallback) } override fun onEndpointLost(endpointId: String) { // A previously discovered endpoint has gone away. Log.d(TAG, "An endpoint was lost, $endpointId") }
}

One of the devices must initiate the connection. Since the Discoverer has a callback for endpoint discovery, it makes sense for the phone to request the connection to the TV.

The phone asks for a connection supplying a `connectionLifecycleCallback` which is symmetric to the callback in the TV code.

val connectionLifecycleCallback = object : ConnectionLifecycleCallback() { override fun onConnectionInitiated( endpointId: String, connectionInfo: ConnectionInfo ) { Log.d(TAG, "Connection initialized to endpoint: $endpointId") // Make sure to authenticate using `connectionInfo.authenticationToken` before accepting Nearby.getConnectionsClient(context) .acceptConnection(endpointId, payloadCallback) } override fun onConnectionResult( endpointId: String, connectionResolution: ConnectionResolution ) { Log.d(TAG, "Connection result from endpoint: $endpointId") when (connectionResolution.status.statusCode) { ConnectionsStatusCodes.STATUS_OK -> { Log.d(TAG, "Connected to endpoint: $endpointId") otherDeviceEndpointId = endpointId waitingIndicator.visibility = View.GONE emailInput.editText?.isEnabled = true passwordInput.editText?.isEnabled = true Nearby.getConnectionsClient(this).stopDiscovery() } else -> { otherDeviceEndpointId = null } } } override fun onDisconnected(endpointId: String) { Log.d(TAG, "Disconnected from endpoint: $endpointId") otherDeviceEndpointId = null }
} 

Once the connection is established, stop discovery to avoid keeping this battery-intensive operation running longer than needed. The example stops discovery after the connection is established, but it is possible for a user to leave the activity before that happens. Be sure to stop the discovery/advertising in onStop() on both the TV and phone.


override fun onStop() { super.onStop() Nearby.getConnectionsClient(this).stopDiscovery()
}


Just like a TV app, when you accept the connection you supply a payload callback. The callback listens for messages from the TV app such as the ACK described above to clean up the connection.

After the devices are connected, the user can use the keyboard and send their authentication information to the TV by calling `sendPayload()`.

fun sendCreditials() { val email = emailInput.editText?.text.toString() val password = passwordInput.editText?.text.toString() val creds = "$email:$password" val payload = Payload.fromBytes(creds.toByteArray()) Log.d(TAG, "sending payload: $creds") if (otherDeviceEndpointId != null) { Nearby.getConnectionsClient(this) .sendPayload(otherDeviceEndpointId, payload) }
}

Ending the conversation

After the phone sends the payload to the TV (and the login is successful), there is no reason for the devices to remain connected. The TV can initiate the disconnection with a simple shutdown protocol.

The TV should send an ACK to the phone after it receives the credential payload.

val payloadCallback = object : PayloadCallback() { override fun onPayloadReceived(endpointId: String, payload: Payload) { if (payload.type == Payload.Type.BYTES) { payload.asBytes()?.let { val body = String(it) Log.d(TAG, "A payload was received: $body") // Validate that this payload contains the login credentials, and process them. val ack = Payload.fromBytes(ACK_PAYLOAD.toByteArray()) Nearby.getConnectionsClient(context).sendPayload(endpointId, ack) } } } override fun onPayloadTransferUpdate( endpointId: String, update: PayloadTransferUpdate ) { }
} 

The phone should have a `PayloadCallback` that initiates a disconnection in response to the ACK. This is also a good time to reset the UI to show an authenticated state.

private val payloadCallback = object : PayloadCallback() { override fun onPayloadReceived(endpointId: String, payload: Payload) { if (payload.type == Payload.Type.BYTES) { payload.asBytes()?.let { val body = String(it) Log.d(TAG, "A payload was received: $body") if (body == ACK_PAYLOAD) { waitingIndicator.visibility = View.VISIBLE waitingIndicator.text = getString(R.string.login_successful) emailInput.editText?.isEnabled = false passwordInput.editText?.isEnabled = false loginButton.isEnabled = false Nearby.getConnectionsClient(this@MainActivity) .disconnectFromEndpoint(endpointId) } } } } override fun onPayloadTransferUpdate( endpointId: String, update: PayloadTransferUpdate ) { }
}

Security considerations

For security (especially since we’re sending over sensitive information like login credentials), it’s strongly recommended that you authenticate the connection by showing a code and having the user confirm that the two devices being connected are the intended ones — without this, the connection established by Nearby Connection is encrypted but not authenticated, and that’s susceptible to Man-In-The-Middle attacks. The documentation goes into greater detail on how to authenticate a connection.

Let the user accept the connection by displaying a confirmation code on both devices.

Does your app offer a second screen experience?

There are many times when a user needs to supply input to a TV app. The Nearby API provides a way to offload the hardships of an onscreen-dpad-driven keyboard to an easy and familiar phone keyboard.

What use cases do you have where a second screen would simplify your user’s life? Leave a comment or send me (@benjamintravels) or Varun (@varunkapoor, Team Lead for Nearby Connections) a tweet to continue the discussion.

Streaming support spec for hearing aids on Android


Posted by Seang Chau, Vice President, Engineering

According to the World Health Organization1, around 466 million people worldwide have disabling hearing loss. This number is expected to increase to 900 million people by the year 2050. Google is working with GN Hearing to create a new open specification for hearing aid streaming support on future versions of Android. Users with hearing loss will be able to connect, pair, and monitor their hearing aids so they can hear their phones loudly and clearly.

Hearing aid users expect a high quality, low latency experience with minimal impact on phone and hearing aid battery life. We’ve published a new hearing aid spec for Android smartphones: Audio Streaming for Hearing Aids (ASHA) on Bluetooth Low Energy Connection-Oriented Channels. ASHA is designed to have a minimal impact on battery life with low-latency while maintaining a high quality audio experience for users who rely on hearing aids. We look forward to continually evolving the spec to even better meet the needs of our users.

The spec details the pairing and connectivity, network topology, system architecture, and system requirements for implementing hearing aids using low energy connection-oriented channels. Any hearing aid manufacturer can now build native hearing aid support for Android.

The protocol specification is available here.

Updating Wear OS Google Play Store policy to increase app quality


Posted by Hoi Lam, Lead Developer Advocate, Wear OS by Google

Today we are announcing a new initiative to improve Wear app quality and their presentation in the Google Play Store. The Wear app review process, which has been in place since the launch of Android Wear 2.0, is currently optional. It will become mandatory for apps to be listed on the Wear OS by Google version of the Google Play Store from the following dates:

  • New Wear apps: 1 October 2018
  • Existing Wear apps: 4 March 2019.

The review process for mobile apps remains unchanged, and is independent of the Wear app review. Mobile app updates will not be blocked if they fail the Wear app review.

We hope this lightweight app review process will improve the quality of Wear app experiences across the wide range of devices available to your users. In addition, since screenshots are required for the Wear app review, this will improve the discovery and presentation of your Wear apps in the Google Play Store.

See a comprehensive list of review criteria here. The following are common issues we see during Wear app reviews:

  • Support for different screen types – Wear OS by Google is available in both round and square screens, and some round devices also have a chin. Developers are advised to test on all screen types. If a physical device is unavailable, please use the Wear OS by Google emulator.
  • Wear OS by Google app screenshot – To pass the review, the app needs to have at least one Wear OS app screenshot. To keep pre-release Wear apps private, the Google Play Store will not show the Wear screenshots unless the Wear App is in production or open testing. Currently, the Google Play Store only supports uploading one set of screenshots across all production and test versions. For existing Wear apps, we recommend developers keeping their production Wear app screenshots unchanged when uploading new open test or closed test Wear apps.

Opting out of app review for early prototypes

We understand that some developers need to experiment with their Wear apps in the early stages of app development, and a Wear app review at this stage might not be appropriate. In this case, developers have two options:

Please note that the open test and closed test channels will be subject to Wear app review to help front-load the quality assurance process and to avoid leaving reviews to the last minute.

Thank you for your continuing support of Wear OS by Google.

Google releases source for Google I/O 2018 for Android


Posted by Shailen Tuli, DPE

Today we’re releasing the source code for the official Google I/O 2018 for Android app.

The 2018 version constitutes a comprehensive rewrite of the app. For many years, the app has used a ContentProvider + SyncAdapter architecture. This year, we rewrote the app using Architecture Components and brought the code in sync with the Android team’s current recommendations for building modern apps.

Architecture

We followed the recommendations laid out in the Guide to App Architecture for writing modular, testable and maintainable code when deciding on the architecture for the app. We kept logic away from Activities and Fragments and moved it to ViewModels. We observed data using LiveData and used the Data Binding Library to bind UI components in layouts to the app’s data sources.

The overall architecture of the app can be summarized in this diagram:

We used a Repository layer for handling data operations. IOSched’s data comes from a few different sources — user data is stored in Cloud Firestore (either remotely or in a local cache for offline use), user preferences and settings are stored in SharedPreferences, conference data is stored remotely and is fetched and stored in memory for the app to use — and the repository modules are responsible for handling all data operations and abstracting the data sources from the rest of the app. If we ever wanted to swap out the Firestore backend for a different data source in the future, our architecture allows us to do so in a clean way.

We implemented a lightweight domain layer, which sits between the data layer and the presentation layer, and handles discrete pieces of business logic off the UI thread. Examples.

We used Dagger2 for dependency injection and we heavily relied on dagger-android to abstract away boilerplate code.

We used Espresso for basic instrumentation tests and JUnit and Mockito for unit testing.

Firebase

The use of Firebase technologies has grown in the app as the Firebase platform has matured. The 2018 version uses the following Firebase components:

  • Cloud Firestore is our source for all user data (events starred or reserved by a user). Firestore gave us automatic sync and also seamlessly managed offline functionality for us.
  • Firebase Cloud Functions allowed us to run backend code. The reservations feature heavily depended on Functions checking a user’s status (only attendees were allowed to make reservations), checking space availability and persisting reservation status in Firestore.
  • Firebase Cloud Messaging let us inform the app about changes to conference data on our server. Conference data is mostly static, but it does change from time to time, especially after the keynote. The app has traditionally used a ping-and-fetch model when working with conference data, and we retained that usage this year.
  • Remote Config helped us manage in-app constants. In previous years, we had found ourselves unable to inform users when data not directly related to the conference schedule — WiFi information, conference shuttle schedule, etc. — changed unexpectedly. Remote Config helped us update such values in a lightweight manner.

Kotlin

We made an early decision to rewrite the app from scratch to bring it in line with modern Android architecture. Using Kotlin for the rewrite was an easy choice: we loved Kotlin’s expressive, concise, and powerful syntax; we found that Kotlin’s support for safety features including nullability and immutability made our code more resilient; and we leveraged the enhanced functionality provided by Android Ktx extensions.

Material Design

At I/O 2018, the Material Design team announced Material Theming, giving apps much greater ability to customize Material Design to bring more of their product’s brand. As we launched the app before Material Theming, we couldn’t use all of the new components but we managed to sneak a couple in like the new Bottom App Bar with inset Floating Action Button and we were able to incorporate a lot of the conference’s branding elements.

Future plans

The rewrite of the app brings the code in sync with Android’s opinionated recommendations about building apps, and it resulted in a cleaner, more maintainable codebase. We’ll continue working on the app, incorporating JetPack components as they become available and finding opportunities to showcase platform features that are good fits for the app. Developers can follow changes to the code on GitHub.

Looking forward with Google Play

Posted by Purnima Kochikar, Director, Google Play, Apps & Games

On Monday we released Android 9 Pie. As we continue to push the Android platform forward, we’re always looking to provide new ways to distribute your apps efficiently, help people discover and engage with your work, and improve the overall security of our ecosystem. Google Play has had a busy year so far with some big milestones around helping you reach more users, including:

  • Shrinking download size: Android App Bundle & Dynamic Delivery has helped reduce app sizes by up to 65%, leading to increased downloads and fewer uninstalls.
  • Helping improve quality: New tools in the Play Console have helped you reduce crash rates by up to 70%.
  • Improving discovery: Improvements to the discovery experience have increased Google Play Store visits by 30% over the last 12 months.
  • Keeping users safe: Google Play Protect scans more than 50 billion apps a day and Android API level 26 adoption requirements improve app security and performance.

Google Play is dedicated to helping you build and grow quality app businesses, reach the more than 2 billion Android devices globally and provide your users with better experiences. Here are some of the important areas we’re prioritizing this year:

Innovative Distribution

We’ve added more testing tools to the popular Play Console to help developers de-risk app launches with internal and external test tracks and staged rollouts to get valuable early feedback. This year we’ve expanded the Start on Android program globally that provides developers new to Android additional guidance to optimize their apps before launch. Google Play Instant remains a huge bet to transform app discovery and improve conversions by letting users engage without the friction of installing. We’re seeing great results from early adopters and are working on new places to surface instant experience, including ads, and making them easier to build throughout the year.

Improving App Quality

Google Play plays an important role helping developers understand and fix quality and performance issues. At I/O, we showcased how we expanded the battery, stability and rendering of Android vitals reporting to include app start time & permission denials, enabling developers to cut application not responding errors by up to 95%. We also expanded the functionality of automated device testing with the pre-launch report to enable games testing. Recently, we increased the importance of app quality in our search and discovery recommendations that has resulted in higher engagement and satisfaction with downloaded games.

Richer Discovery

Over the last year we’ve rolled out more editorial content and improved our machine learning to deliver personalized recommendations for apps and games that engage users. Since most game downloads come from browsing (as opposed to searching or deep linking into) the store, we’ve put particular focus on games discovery, with a new games home page, special sections for premium and new games, immersive video trailers and screenshots, and the ability to try games instantly. We’ve also introduced new programs to help drive app downloads through richer discovery. For example, since launching our app pre-registration program in 2016, we’ve seen nearly 250 million app pre-registrations. Going forward, we’ll be expanding on these programs and others like LiveOps cards to help developers engage more deeply with their audience.

Expanding Commerce Platform

Google Play now collects payments in 150 markets via credit card, direct carrier billing (DCB), Paypal, and gift cards. Direct carrier billing is now enabled across 167 carriers in 64 markets. In 2018, we have focused on expanding our footprint in Africa and Latam with launches in Ghana, Kenya, Tanzania, Nigeria, Peru & Colombia. And users can now buy Google Play credit via gift cards or other means in more 800,000 retail locations around the world. This year, we also launched seller support in 18 new markets bringing the total markets with seller support to 98. Our subscription offering continues to improve with ML-powered fraud detection and even more control for subscribers and developers. Google Play’s risk modeling automatically helps detect fraudulent transactions and purchase APIs help you better analyze your refund data to identify suspicious activity.

Maintaining a Safe & Secure Ecosystem

Google Play Protect and our other systems scan and analyze more than 50 billion apps a day to keep our ecosystem safe for users and developers. In fact, people who only download apps from Google Play are nine times less likely to download a potentially harmful app than those who download from other sources. We’ve made significant improvements in our ability to detect abuse—such as impersonation, inappropriate content, fraud, or malware—through new machine learning models and techniques. The result is that 99% of apps with abusive content are identified and rejected before anyone can install them. We’re also continuing to run the Google Play Security Rewards Program through a collaboration with Hacker One to discover other vulnerabilities.

We are continually inspired by what developers build—check out #IMakeApps for incredible examples—and want every developer to have the tools needed to succeed. We can’t wait to see what you do next!