Android Wear 2.0 represents the the latest evolution of the Android Wear platform. It introduced the concept of standalone apps that can connect to the network directly and work independently of a smartphone. This is critical to providing apps not only to our Android users, but also iOS users - which is increasingly important as we continue to expand our diverse ecosystem of watches and users. In addition, Wear 2.0 brought multi-APK support to Wear apps, which reduces the APK size of your phone apps, and makes it possible for iOS users to experience your Wear apps.
Today, we are announcing that multi-APKs will also work for Android Wear 1.0 watches, so you can now reach all of your users without needing to bundle your Wear app within your phone app's APK. Additionally, the Google Play Store policy will change to promote the use of multi-APKs and standalone apps. This covers all types of apps that are designed to run on the watch, including watch faces, complication data providers as well as launchable apps.
The policy change will be effective from the 18th of January, 2018. At this time, the following apps will lose the "Enhanced for Android Wear" badge in the Google Play Store and will not be eligible to be listed in the top charts in the Play Store for Android Wear:
Since multi-APK is now supported by devices running Wear 1.0 and 2.0, developers embedding their Wear app APKs in phone APKs should unbundle their Wear APK and upload it to the Play Store as a multi-APK. This will allow them to continue to qualify for the "Enhanced for Android Wear" badge as well as be eligible to appear in the Android Wear top charts. The two APKs can continue to share the same package name.
In addition to providing top app charts, we periodically put together curated featured collections. To be eligible for selection for these collections, developers will need to make their Wear apps function independently from the phone, as a standalone app. These apps will need to work on watches that are paired with both iOS and Android phones.
Standalone apps are Wear apps that do not require a phone app to run. The app either does not require network access or can access the network directly without the phone app - something that is supported by Android Wear 2.0.
To mark your app as standalone, put the following meta-data tag in the AndroidManifest.xml:
AndroidManifest.xml:
<application> ... <meta-data android:name="com.google.android.wearable.standalone" android:value="true" /> ... </application>
In some rare cases, the user experience may be enhanced by the syncing of data between the phone and watch. For example, a cycling app can use the watch to display the current pace, and measure the user's heart rate, while displaying a map on the phone. In this scenario, we recommend that developers ensure that their Wear apps function without a phone and treat the phone experience as optional as far as the Wear apps are concerned. In these cases, a Wear app is still considered standalone and should be marked as such in its AndroidManifest.xml file.
AndroidManifest.xml
From the beginning, Android Wear has been about wear what you want -- the styles, watches, and apps you want to wear. This latest policy change lets you highlight your Android Wear apps, giving users even more choice about what apps they want on their watches.
Posted by Sami Tolvanen, Senior Software Engineer, Android Security
The hardening of Android's userspace has increasingly made the underlying Linux kernel a more attractive target to attackers. As a result, more than a third of Android security bugs were found in the kernel last year. In Android 8.0 (Oreo), significant effort has gone into hardening the kernel to reduce the number and impact of security bugs.
Android Nougat worked to protect the kernel by isolating it from userspace processes with the addition of SELinux ioctl filtering and requiring seccomp-bpf support, which allows apps to filter access to available system calls when processing untrusted input. Android 8.0 focuses on kernel self-protection with four security-hardening features backported from upstream Linux to all Android kernels supported in devices that first ship with this release.
Usercopy functions are used by the kernel to transfer data from user space to kernel space memory and back again. Since 2014, missing or invalid bounds checking has caused about 45% of Android's kernel vulnerabilities. Hardened usercopy adds bounds checking to usercopy functions, which helps developers spot misuse and fix bugs in their code. Also, if obscure driver bugs slip through, hardening these functions prevents the exploitation of such bugs.
This feature was introduced in the upstream kernel version 4.8, and we have backported it to Android kernels 3.18 and above.
int buggy_driver_function(void __user *src, size_t size) { /* potential size_t overflow (don’t do this) */ u8 *buf = kmalloc(size * N, GPF_KERNEL); … /* results in buf smaller than size, and a heap overflow */ if (copy_from_user(buf, src, size)) return -EFAULT; /* never reached with CONFIG_HARDENED_USERCOPY=y */ }
An example of a security issue that hardened usercopy prevents.
While hardened usercopy functions help find and mitigate security issues, they can only help if developers actually use them. Currently, all kernel code, including drivers, can access user space memory directly, which can lead to various security issues.
To mitigate this, CPU vendors have introduced features such as Supervisor Mode Access Prevention (SMAP) in x86 and Privileged Access Never (PAN) in ARM v8.1. These features prevent the kernel from accessing user space directly and ensure developers go through usercopy functions. Unfortunately, these hardware features are not yet widely available in devices that most Android users have today.
Upstream Linux introduced software emulation for PAN in kernel version 4.3 for ARM and 4.10 in ARM64. We have backported both features to Android kernels starting from 3.18.
Together with hardened usercopy, PAN emulation has helped find and fix bugs in four kernel drivers in Pixel devices.
int buggy_driver_copy_data(struct mydata *src, void __user *ptr) { /* failure to keep track of user space pointers */ struct mydata *dst = (struct mydata *)ptr; … /* read/write from/to an arbitrary user space memory location */ dst->field = … ; /* use copy_(from|to)_user instead! */ … /* never reached with PAN (emulation) or SMAP */ }
An example of a security issue that PAN emulation mitigates.
Android has included support for Address Space Layout Randomization (ASLR) for years. Randomizing memory layout makes code reuse attacks probabilistic and therefore more difficult for an attacker to exploit, especially remotely. Android 8.0 brings this feature to the kernel. While Linux has supported KASLR on x86 since version 3.14, KASLR for ARM64 has only been available upstream since Linux 4.6. Android 8.0 makes KASLR available in Android kernels 4.4 and newer.
KASLR helps mitigate kernel vulnerabilities by randomizing the location where kernel code is loaded on each boot. On ARM64, for example, it adds 13–25 bits of entropy depending on the memory configuration of the device, which makes code reuse attacks more difficult.
The final hardening feature extends existing memory protections in the kernel by creating a memory region that's marked read-only after the kernel has been initialized. This makes it possible for developers to improve protection on data that needs to be writable during initialization, but shouldn't be modified after that. Having less writable memory reduces the internal attack surface of the kernel, making exploitation harder.
Post-init read-only memory was introduced in upstream kernel version 4.6 and we have backported it to Android kernels 3.18 and newer. While we have applied these protections to some data structures in the core kernel, this feature is extremely useful for developers working on kernel drivers.
Android Oreo includes mitigations for the most common source of security bugs in the kernel. This is especially relevant because 85% of kernel security bugs in Android have been in vendor drivers that tend to get much less scrutiny. These updates make it easier for driver developers to discover common bugs during development, stopping them before they can reach end user devices.
With more than two billion active devices, Android is the largest mobile platform in the world. And for the past nine years, we've worked to create a rich set of tools, frameworks and APIs that deliver developers' creations to people everywhere. Today, we're releasing a preview of a new software development kit (SDK) called ARCore. It brings augmented reality capabilities to existing and future Android phones. Developers can start experimenting with it right now.
We've been developing the fundamental technologies that power mobile AR over the last three years with Tango, and ARCore is built on that work. But, it works without any additional hardware, which means it can scale across the Android ecosystem. ARCore will run on millions of devices, starting today with the Pixel and Samsung's S8, running 7.0 Nougat and above. We're targeting 100 million devices at the end of the preview. We're working with manufacturers like Samsung, Huawei, LG, ASUS and others to make this possible with a consistent bar for quality and high performance.
ARCore works with Java/OpenGL, Unity and Unreal and focuses on three things:
Alongside ARCore, we've been investing in apps and services which will further support developers in creating great AR experiences. We built Blocks and Tilt Brush to make it easy for anyone to quickly create great 3D content for use in AR apps. As we mentioned at I/O, we're also working on Visual Positioning Service (VPS), a service which will enable world scale AR experiences well beyond a tabletop. And we think the Web will be a critical component of the future of AR, so we're also releasing prototype browsers for web developers so they can start experimenting with AR, too. These custom browsers allow developers to create AR-enhanced websites and run them on both Android/ARCore and iOS/ARKit.
ARCore is our next step in bringing AR to everyone, and we'll have more to share later this year. Let us know what you think through GitHub, and check out our new AR Experiments showcase where you can find some fun examples of what's possible. Show us what you build on social media with #ARCore; we'll be resharing some of our favorites.
With so many great mobile games launching this year, we saw a huge amount of interest from indie developers to showcase their art at the Google Play Indie Games Festival in San Francisco next month. While it was a tough selection process, we're excited to announce the 20 finalists, as well as our esteemed judging panel. Fans will be able to play the new and un-released indie games in a fun festival atmosphere where they can also meet the creators themselves. To attend and learn more about the event, register now for free at g.co/play/sfindiegamesfest2017.
So how did we choose the 20 finalists? We powered up our phones, put our game-faces on, and looked for games that not only met the festival requirements, but also stood out with their overall design, fun, and quality. These are the 20 finalists who will be joining us at the festival to demo their games.
In addition to playing these games and meeting the developers who made them, fans will have a chance to vote for their favorites throughout the festival. The Top 10 will then move on to present a short pitch in pursuit of going home as one of the three overall festival winners. The winners will be chosen by this year's panel of judges representing a diverse lineup of gaming expertise.
Emceeing this year's event is J.D. Witherspoon, aka runJDrun. No stranger to gaming, YouTuber/actor/comedian, J.D. plays a wide array of games and frequently uploads gaming, vlog, and comedy content to his channels.
If you want to try out these games and celebrate the indie community, learn more about the event and register at g.co/play/sfindiegamesfest2017.
Wear 2.0 launched back in February with added support for new hardware features in addition to adopting new Material Design themes, guidelines, and a simpler vertical UI pattern. It also introduces a complications API, making it easier for apps to provide data to watch faces, and watch faces to incorporate external data. The final big update was that, apps targeting Wear 2.0 now have the ability to operate in a standalone mode, without needing a connection to a companion app on the phone.
There are a few design considerations in relation to navigation, notifications, the complications API, and the standalone functionality to help you better optimize for Wear 2.0 devices:
Ensure that for devices using Wear 2.0, your app takes advantage of these new UI patterns to provide a consistent user experience. Check out more training resources for Wear Navigation and Actions and the Material Design specifications for Navigation and Action Drawers.
Wear 2.0 uses a simpler vertical navigation pattern, removing the horizontal swiping gesture to present actions for a notification. Notification actions are now presented as a single primary action (if applicable) at the bottom of a notification. If there is no primary action, expanding the notification will present options in a single, vertically scrollable view.
Notifications will work without needing many changes on both 1.x and 2.0 devices, but appear quite different:
When creating apps for Wear 2.0 devices, improve the user experience with notifications by applying the following best practices:
To learn more about adding wearable features to notifications.
The complications API in Wear 2.0 makes it much easier for watch face developers and third-party data providers to surface important information users want, at a glance. Watch faces that support the API can be configured to use any of the data providers that have been installed on the watch while maintaining complete control over their appearance. Apps supporting the complication API allow the app's data to be accessible on any watch faces that support complications. These complications can be displayed in a variety of forms (short text, icon, ranged value, long text, small image, and large image) depending on what the data provider has configured and how much space has been allocated on the watch face.
To ensure that complications fit the overall design of the watch face and properly handle their data type, when adding complication support we recommend watch face makers should:
TextRenderer
ComplicationDrawable
ComplicationProviderService
ComplicationData
Though a lot was covered here, there are additional resources you can use to ensure that your apps or games are optimized and use the latest patterns and functionality on Wear. Be sure to review the quality guidelines and check out the developer training documentation to learn more best practices for wearable app development and wearable app design in order to build quality apps for Wear.
Since announcing ConstraintLayout at Google I/O last year, we've continued to improve the layout's stability and layout editor support. We've also added new features specific to ConstraintLayout that help you build various type of layouts, such as introducing chains and setting size as a ratio. In addition to these features, there is a notable performance benefit by using ConstraintLayout. In this post, we'll walk through how you can benefit from these performance improvements.
ConstraintLayout
To better understand the performance of ConstraintLayout, let's take a step back and see how Android draws views.
When a user brings an Android view into focus, the Android framework directs the view to draw itself. This drawing process comprises 3 phases:
The system completes a top-down traversal of the view tree to determine how large each ViewGroup and View element should be. When a ViewGroup is measured, it also measures its children.
ViewGroup
Another top-down traversal occurs, with each ViewGroup determining the positions of its children using the sizes determined in the measure phase.
The system performs yet another top-down traversal. For each object in the view tree, a Canvas object is created to send a list of drawing commands to the GPU. These commands include the ViewGroup and View objects' sizes and positions, which the system determined during the previous 2 phases.
Canvas
View
Each phase within the drawing process requires a top-down traversal of the view tree. Therefore, the more views you embed within each other (or nest) into the view hierarchy, the more time and computation power it takes for the device to draw the views. By keeping a flat hierarchy in your Android app layouts, you can create a fast and responsive user interface for your app.
With that explanation in mind, let's create a traditional layout hierarchy that uses LinearLayout and RelativeLayout objects.
LinearLayout
RelativeLayout
Let's say we want to build a layout like the image above. If you build it with traditional layouts, the XML file contains an element hierarchy similar to the following (for this example, we've omitted the attributes):
<RelativeLayout> <ImageView /> <ImageView /> <RelativeLayout> <TextView /> <LinearLayout> <TextView /> <RelativeLayout> <EditText /> </RelativeLayout> </LinearLayout> <LinearLayout> <TextView /> <RelativeLayout> <EditText /> </RelativeLayout> </LinearLayout> <TextView /> </RelativeLayout> <LinearLayout > <Button /> <Button /> </LinearLayout> </RelativeLayout>
Although there's usually room for improvement in this type of view hierarchy, you'll almost certainly still need to create a hierarchy with some nested views.
As discussed before, nested hierarchies can adversely affect performance. Let's take a look at how the nested views actually affect the UI performance using Android Studio's Systrace tool. We called the measure and layout phases for each ViewGroup (ConstraintLayout and RelativeLayout) programmatically and triggered Systrace while the measure and layout calls are executing. The following command generates an overview file that contains key events, such as expensive measure/layout passes, that occur during a 20-second interval:
python $ANDROID_HOME/platform-tools/systrace/systrace.py --time=20 -o ~/trace.html gfx view res
For more details about how you can use Systrace, see the Analyzing UI Performance with Systrace guide.
Systrace automatically highlights the (numerous) performance problems with this layout, as well as suggestions for fixing them. By clicking the "Alerts" tab, you will find that drawing this view hierarchy requires 80 expensive passes through the measure and layout phases!
Triggering that many expensive measure and layout phases is far from ideal; such a large amount of drawing activity could result in skipped frames that users notice. We can conclude that the layout has poor performance due to the nested hierarchy as well as the characteristic of RelativeLayout, which measures each of its children twice.
You can check the entire code on how we performed these measurements in our GitHub repository.
If you create the same layout using ConstraintLayout, the XML file contains an element hierarchy similar to the following (attributes again omitted):
<android.support.constraint.ConstraintLayout> <ImageView /> <ImageView /> <TextView /> <EditText /> <TextView /> <TextView /> <EditText /> <Button /> <Button /> <TextView /> </android.support.constraint.ConstraintLayout>
As this example shows, the layout now has a completely flat hierarchy. This is because ConstraintLayout allows you to build complex layouts without having to nest View and ViewGroup elements.
For example, let's look at the TextView and EditText in the middle of the layout:
TextView
EditText
<LinearLayout android:id="@+id/camera_area" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_below="@id/title" > <TextView android:text="@string/camera" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:id="@+id/cameraLabel" android:labelFor="@+id/cameraType" android:layout_marginStart="16dp" /> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <EditText android:id="@+id/cameraType" android:ems="10" android:inputType="textPersonName" android:text="@string/camera_value" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginTop="8dp" android:layout_marginStart="8dp" android:layout_marginEnd="8dp" /> </RelativeLayout> </LinearLayout>
By using ConstraintLayout instead, you can achieve the same effect just by adding a constraint from the baseline of the TextView to the baseline of the EditText without creating another ViewGroup:
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintLeft_creator="1" app:layout_constraintBaseline_creator="1" app:layout_constraintLeft_toLeftOf="@+id/activity_main_done" app:layout_constraintBaseline_toBaselineOf="@+id/cameraType" />
When running the Systrace tool for the version of our layout that uses ConstraintLayout, you see far fewer expensive measure/layout passes during the same 20-second interval. This improvement in performance makes sense, now that we're keeping the view hierarchy flat!
On a related note, we built the ConstraintLayout variant of our layout using just the layout editor instead of editing the XML by hand. To achieve the same visual effect using RelativeLayout, we probably would have needed to edit the XML by hand.
We analyzed how long every measure and layout pass took for two type of layouts, ConstraintLayout and RelativeLayout, by using OnFrameMetricsAvailableListener, which was introduced in Android 7.0 (API level 24). This class allows you to collect frame-by-frame timing information about your app's UI rendering.
OnFrameMetricsAvailableListener
By calling the following code, you can start recording per-frame UI actions:
window.addOnFrameMetricsAvailableListener( frameMetricsAvailableListener, frameMetricsHandler);
After timing information becomes available, the app triggers the frameMetricsAvailableListener() callback. We are interested in the measure/layout performance, so we call FrameMetrics.LAYOUT_MEASURE_DURATION when retrieving the actual frame duration.
frameMetricsAvailableListener()
FrameMetrics.LAYOUT_MEASURE_DURATION
Window.OnFrameMetricsAvailableListener { _, frameMetrics, _ -> val frameMetricsCopy = FrameMetrics(frameMetrics); // Layout measure duration in nanoseconds val layoutMeasureDurationNs = frameMetricsCopy.getMetric(FrameMetrics.LAYOUT_MEASURE_DURATION);
To learn more about the other types of duration information that FrameMetrics can receive, see the FrameMetrics API reference.
FrameMetrics
Our performance comparison shows that ConstraintLayout performs about 40% better in the measure/layout phase than RelativeLayout:
As these results show, ConstraintLayout is likely to be more performant than traditional layouts. Moreover, ConstraintLayout has other features that help you build complex and performant layouts, as discussed in the benefits of a ConstraintLayout object section. For details, see the Build a Responsive UI with ConstraintLayout guide. We recommend that you use ConstraintLayout when designing your app's layouts. In almost all cases when you would have previously need a deeply-nested layout, ConstraintLayout should be your go-to layout for optimal performance and ease of use.
All the measurements above were performed in the following environment.
Check out the developer guide, the API reference documentation, and the article on Medium to fully understand what ConstraintLayout can provide for you. And once again, thank you to all who submitted feedback and issues over the months since our alpha release of ConstraintLayout. We're truly grateful that we were able to release the production-ready 1.0 version of ConstraintLayout earlier this year. As we continue to improve ConstraintLayout, please continue to send us feedback using the Android issue tracker.
Early Access was launched at Google I/O 2016 as a destination on Google Play for beta app and game titles still in development, and to attract early adopters willing to test those titles. The results speak for themselves. The program has helped over 350 developers launch their titles and generated over 40M beta installs for their apps and games during just the short window before their public availability on the Play Store. More importantly, the average rating for titles that have been through Early Access is 4.3☆ once in production, putting them in a strong position to be favored in search and discovery on Google Play.
Early Access also generates positive awareness for new titles. Alumni like Simple Habit and Digit were chosen as finalists in the "Standout Startup" category at the Google Play Awards this year. Omnidrone's game Titan Brawl became the first game to reach 1M testers. Hear more about their experience in the video below.
Early Access and our work with the venture capital community has taught us a lot about successful startups. We know you seek rapid iteration towards product-market fit and are thirsty for the same kind of powerful testing, analytics, and user feedback that Google's own product teams depend on to launch successful products. When we know about your startup's plans well in advance of your launch date, we can impact your trajectory by supporting you through this understood process of iterative improvement.
Earlier this year we launched Start on Android to identify the highest potential Android startups earlier in their lifecycle and provide tools, perks, and guidance for those who qualify. We've developed five components that have proven to be most impactful:
We've already seen a lot of developer interest and received hundreds of public applications and referrals from venture capitalists and other startup influencers. Below are a few accepted startups:
We are incredibly proud of every developer we work with and grateful to our friends within VC firms and the wider community who bring exciting new startups to our attention.
If you would like to be part of Start on Android, complete the form at StartonAndroid.com. We're looking for developers who are planning to launch on Android soon, or have done so in the past 6 months.
How useful did you find this blogpost?
Eagle-eyed users of Android O will have noticed the absence of the 'Allow unknown sources' setting, which has existed since the earliest days of Android to facilitate the installation of apps from outside of Google Play and other preloaded stores. In this post we'll talk about the new Install unknown apps permission and the security benefits it brings for both Android users and developers.
Earlier this year we introduced Google Play Protect - comprehensive security services that are always at work to protect your device from harm. Google Play continues to be one of the safest places for Android users to download their apps, with the majority of Potentially Harmful Apps (PHAs) originating from third-party sources.
A common strategy employed by PHA authors is to deliver their apps via a hostile downloader. For example, a gaming app might not contain malicious code but instead might notify the user to install a PHA that masquerades as an important security update. (You can read more about hostile downloaders in the Android Security 2016 Year in Review). Users who have enabled the installation of apps from unknown sources leave themselves vulnerable to this deceptive behavior.
In Android O, the Install unknown apps permission makes it safer to install apps from unknown sources. This permission is tied to the app that prompts the install— just like other runtime permissions—and ensures that the user grants permission to use the install source before it can prompt the user to install an app. When used on a device running Android O and higher, hostile downloaders cannot trick the user into installing an app without having first been given the go-ahead.
This new permission provides users with transparency, control, and a streamlined process to enable installs from trusted sources. The Settings app shows the list of apps that the user has approved for installing unknown apps. Users can revoke the permission for a particular app at any time.
To take advantage of this new behavior, developers of apps that require the ability to download and install other apps via the Package Installer may need to make some changes. If an app uses a targetSdkLevel of 26 or above and prompts the user to install other apps, the manifest file needs to include the REQUEST_INSTALL_PACKAGES permission:
targetSdkLevel
REQUEST_INSTALL_PACKAGES
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
Apps that haven't declared this permission cannot install other apps, a handy security protection for apps that have no intention of doing so. You can choose to pre-emptively direct your users to the Install unknown apps permission screen using the ACTION_MANAGE_UNKNOWN_APP_SOURCES Intent action. You can also query the state of this permission using the PackageManager canRequestPackageInstalls() API.
ACTION_MANAGE_UNKNOWN_APP_SOURCES
canRequestPackageInstalls()
Remember that Play policies still apply to apps distributed on Google Play if those apps can install and update other apps. In the majority of cases, such behavior is inappropriate; you should instead provide a deep link to the app's listing on the Play Store.
Be sure to check out the updated publishing guide that provides more information about installing unknown apps, and stay tuned for more posts on security hardening in Android O.
After more than a year of development and months of testing by developers and early adopters (thank you!), we're now ready to officially launch Android 8.0 Oreo to the world. Android 8.0 brings a ton of great features such as picture-in-picture, autofill, integrated Instant Apps, Google Play Protect, faster boot time, and much more.
We're pushing the sources to Android Open Source Project (AOSP) for everyone to access today. Pixel and Nexus 5X/6P builds have entered carrier testing and we expect to start rolling out in phases over the next several weeks, alongside Pixel C and Nexus Player. Android Beta users will receive the update to the final version today and images are available to download and flash manually. We've been working closely with our partners over the last many months, and by the end of this year, hardware makers like Essential, General Mobile, HMD Global Home of Nokia Phones, Huawei, HTC, Kyocera, LG, Motorola, OnePlus, Samsung, Sharp and Sony are scheduled to be launching or upgrading new devices to Android 8.0 Oreo.
In Android 8.0 Oreo we focused on creating fluid experiences that make Android even more powerful and easy to use, such as:
We also invested in Android Vitals, a project focused on optimizing battery life, startup time, graphics rendering, and stability, while giving developers better visibility over the health of their apps:
For developers, Android Oreo includes many new capabilities to help you build better, more efficient apps. Here are just a few:
Learn more about these and other new features by visiting the Android 8.0 Oreo site on developer.android.com. Also check out the What's New in Android Oreo? video for an overview of new features for developers.
If haven't already, take a few moments today to test your apps and make sure they offer the experience you want for users upgrading to Android Oreo.
Just install your current app from Google Play onto a device or emulator running Android Oreo and test the user flows. The app should run and look great, and handle the Android Oreo behavior changes properly. In particular, pay attention to background location limits, notification channels, and changes in networking, security, and identifiers.
Once you've resolved any issues, publish your app updates to Google Play in your alpha, beta, or production channels so that they're available as users start to receive Android 8.0 Oreo.
When you're ready to build with new APIs in Android Oreo, we recommend updating to the latest version of Android Studio 3.0, available for download from the beta channel. Aside from improved app performance profiling tools, support for the Kotlin programming language, and Gradle build optimizations, Android Studio 3.0 makes it easier to develop with Instant Apps, XML Fonts, downloadable fonts, and adaptive icons.
We also recommend updating to the Android Support Library 26.0.2, available now from Google's Maven repository, and to the latest SDK, tools, and emulator system images, available in the SDK Manager.
If you're just getting started building for Android Oreo, read the migration guide first. It gives you an overview of the process and the configuration changes you'll need to make.
To compile against the official Android 8.0 APIs, update your project's compileSdkVersion to API 26. We also recommend updating your app's targetSdkVersion to API 26 to opt-in and test your app with Android Oreo specific behavior changes. See the migration guide for details on how to set up your environment to build with Android Oreo.
compileSdkVersion
targetSdkVersion
Google Play is open for apps compiled against or targeting API 26. When you're ready, you can publish your APK updates in your alpha, beta, or production channels.
Make sure that your updated app runs well on Android Oreo as well as older versions. We recommend using Google Play's beta testing feature to get early feedback from a small group of users, then do a staged rollout. We're looking forward to seeing your app updates!
We'll soon be closing the Developer Preview issue tracker, but please keep the feedback coming! You can file a new issue against Android 8.0 in the AOSP issue tracker.
Thanks again to the many developers and early adopters who participated in the Android O Developer Preview and public beta. You gave us great feedback, and filed hundreds of issues that helped us to make the Android Oreo platform great for consumers and developers.
Today we're releasing the source code for the official Google I/O 2017 for Android app.
This year's app substantially modifies existing functionality and adds several new features. It also expands the tech stack to use Firebase. In this post, we'll highlight several notable changes to the app as well as their design considerations.
The most prominent new feature for 2017 is the event reservation system, designed to help save in-person attendees' time and provide a streamlined conference experience. Registered attendees could reserve sessions and join waitlists prior to and during the conference; a reservation provided expedited entry to sessions without having to wait in long lines. Reservation data was synced with attendees' conference badges, allowing event staff to verify reservations using NFC-enabled phones. Not only was the reservation feature incredibly popular, but the reservation data helped event staff change the size of session rooms both before and during I/O to adjust for actual demand for seats.
The reservation feature was implemented using Firebase Realtime Database (RTDB) and Cloud Functions for Firebase. RTDB provided easy sync across user devices — we just had to implement a listener in our code to receive database updates. RTDB also provided out-of-the-box offline support, allowing conference data to be available even in the face of intermittent network connectivity while traveling. A Cloud Function processed reservation requests in the background for the user, using transactions to ensure correctness of state (preventing mischievous users from grabbing too many seats!) and communicating with the event badging system.
As in previous years, we used a ContentProvider as an abstraction layer over all app data, which meant we had to figure out how to integrate RTDB data with the ContentProvider. We needed to negotiate between having two local caches for data: 1) the extant local SQLite database accessed via the ContentProvider, and 2) the local cache created by RTDB to facilitate offline access. We decided to integrate all app data under the ContentProvider: whenever reservation data for the user changed in RTDB, we updated the ContentProvider, making it the single source of truth for app data at all times. This meant that we needed to keep open connections to RTDB only on a single screen, the Session Detail Activity, where users might be actively managing their reservations. Reservation data displayed in other parts of the app was backed by the ContentProvider. In offline mode, or in case of a flaky or delayed connection to RTDB, we could just get the last known state of the user's reservations from the ContentProvider.
We also had to figure out good patterns for integrating RTDB into the overall sync logic of IOSched, especially since RTDB comes with a very different sync model than the ping-and-fetch approach we were using in the app. We decided to continue using Cloud Endpoints to synchronize user data across devices and with the web and iOS clients (the data itself was stored in Datastore). While RTDB provides out-of-the-box data syncing, we wanted to make sure that a user's reservation data was current across all devices, even when the app was not in the foreground. We used a Cloud Function to integrate RTDB reservation data into the sync flow: once reservation data for a user changed in RTDB, the function updated the endpoint, which triggered a Firebase Cloud Messaging downstream message to all the user's devices, which then scheduled data syncs.
This year's app also featured a Feed to apprise users about hour-by-hour developments at I/O (most of the app's users were remote, and the Feed was a window into the conference for them). The Feed was also powered by RTDB, with data pushed to the server using a simple CMS. We used a Cloud Function to monitor RTDB feed data; when feed data was updated on the server, the Function sent a Cloud Messaging downstream message to clients, which visually surfaced the presence of new feed items to the user.
In 2015 and 2016, we had adopted an MVP architecture for IOSched, and we continued using that this year. This architecture provides us with good separation of concerns, facilitates testing, and in general makes our code cleaner and easier to maintain. For the Feed feature, we decided to experiment with a more lightweight MVP implementation inspired by Android Architecture Blueprints, which provided the necessary modularity while being very easy to conceptualize. The goal here was both pedagogical and practical: we wanted to showcase an alternate MVP pattern for developers; we also wanted to showcase an architecture that was an appropriate fit for our needs for this feature.
For the first time, IOSched made heavy use of Firebase Remote Config. In the past, we had found ourselves unable to inform users when non-session data - wifi information, shuttle schedule, discount codes for ridesharing, etc. - changed just before or during the conference. Forcing an app update was not feasible; we just wanted in-app default values to be updatable. Using remote config easily solved this problem for us.
In the end, we ended up with a three-tier system of informing users about changes:
Even though we're releasing the 2017 code, we still have work ahead of us for the coming months. We'll be updating the code to follow modern patterns for background processing (and making our app "O" compliant), and in the future we'll be adopting Android's Architecture Components to simplify the overall design of the app. Developers can follow changes to the code on GitHub.