Posted by The Android Developers Team
Outdooractive, Europe’s largest outdoor platform, provides trail maps and information to a global community of more than 12 million nature enthusiasts. As a platform focused on helping users plan and navigate their outdoor adventures, Outdooractive has long viewed wearable devices like smart watches as essential to the growth of their app. Users value wearables as navigation tools and activity trackers, so when Google reached out with Android’s new UI toolkit, Compose for Wear OS, Outdooractive’s developers jumped on the opportunity to improve their app for this growing market.
The application overhaul quickly showed the benefits of Compose for Wear OS. It cut development time by an estimated 30% for Outdooractive’s developers, accelerating their ability to create streamlined user interfaces. “What would have taken us days now takes us hours,” said Liam Hargreaves, the Senior Project Manager of Outdooractive.
Having a modern code base and increasing the development speed helped make the UI code more intuitive for the developers to read and write, allowing for faster prototyping in the design phase and more fluid collaboration. This helped the developers create a more convenient experience for users.
Outdooractive’s app strives to deliver accurate information in real time to the users’ wearable devices, including turn-by-turn navigation, trail conditions, and weather updates.
“Our app has a relatively complex set of interactions,” said Liam. “Each of these needs to be kept simple, quick, easy to access, and clearly presented — all whilst our customer could be standing on a hillside or in a storm or wearing winter hiking gear and gloves!”
New features in Compose for Wear OS helped the Outdooractive developers create a higher quality app experience for users on the go. The Chip component significantly improved the process for creating lists and allowed developers to use pre-built design elements, saving the team days of work. ScalingLazyColumn also optimized the creation of scrolling screens without the need for RecyclerView or ScrollView.
The developers were also excited by how easy it was to use the AnimatedVisibility component because it allowed them to animate functions that they previously didn’t have time for. The team especially appreciated how Compose for Wear OS made it much easier to present different UI states to the user by communicating “loading” or “error” conditions more clearly.
"Compose makes the UI code more intuitive to write and read, allowing us to prototype faster in the design phase and also collaborate better on the code."
Since implementing Compose for Wear OS, Outdooractive’s users have spent more time on wearable devices doing things they normally would have done on their phones, such as navigating hiking routes — a key UI goal that Compose for Wear OS helped the developers to achieve.
“We see wearables as a critical part of our product and market strategy — and the reaction from our users is extremely positive,” Liam said.
Outdooractive’s developers used another Wear OS capability called Health Services to implement fitness tracking features such as heart rate monitoring into the app by leveraging on-device sensors to offer an experience unique to wearable devices. Health Services on Wear OS automates the configuration of all health- and fitness-related sensors; collects their data; and calculates metrics such as heart rate, distance traveled, and pace, making it easy for developers to implement sophisticated app features while also maximizing battery life. With Health Services and Compose for Wear OS, Outdooractive’s developers plan to further expand the app’s offerings that are made possible by body sensors.
Outdooractive’s streamlined process shows just how easy Compose for Wear OS makes application development because it gives developers the flexibility to experiment with different layouts without increasing development overhead.
Liam had clear advice for other developers considering using Compose for Wear OS: “Fully embrace it.”
Jetpack Compose for Wear OS helps build more engaging user experiences for wearable devices.
To get a first look, watch the Wear OS talk from Google I/O or try the Compose for Wear OS codelab to start learning now.
Posted by Rakesh Iyer, Staff Software Engineer and Leland Rechis, Group Product Manager
We are upgrading the Speech Services by Google speech engine in a big way, providing clearer, more natural voices. All 421 voices in 67 languages have been upgraded with a new voice model and synthesizer.
If you already use TTS and the Speech Services by Google engine, there is nothing to do – everything will happen behind the scenes as your users will have automatically downloaded the latest update. We’ve seen a significant side by side quality increase with this change, particularly in respects to clarity and naturalness.
With this upgrade we will also be changing the default voice in en-US to one that is built using fresher speaker data, which alongside our new stack, results in a drastic improvement. If your users have not selected a system voice, and you rely on system defaults, they will hear a slightly different speaker. You can hear the difference below
Speaker change and upgrade for EN-US
Sample Current Speaker
Sample Upgraded Speaker
Speaker upgrades in a few other languages
Current
Upgraded
HI-IN
PT-BR
ES-US
This update will be rolling out to all 64 bit Android devices via the Google Play Store over the next few weeks as a part of the Speech Services by Google apk. If you are concerned your users have not updated this yet, you can check for the minimum version code ,210390644 on the package com.google.android.tts.
If you haven't used TTS in your projects yet, or haven’t given your users the ability to choose a voice within your app, it's fairly straightforward, and easy to experiment with. We’ve included some sample code to get you started.
Here’s an example of how to set up voice synthesis, get a list of voices, and set a specific voice. We finally send a simple utterance to the synthesizer.
class MainActivity : AppCompatActivity() { companion object { private const val TAG = "TextToSpeechSample" } private lateinit var tts: TextToSpeech private val progressListener: UtteranceProgressListener = object : UtteranceProgressListener() { override fun onStart(utteranceId: String) { Log.d(TAG, "Started utterance $utteranceId") } override fun onDone(utteranceId: String) { Log.d(TAG, "Done with utterance $utteranceId") } override fun onError(utteranceId: String?) {} } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val onInitListener = TextToSpeech.OnInitListener { tts.setOnUtteranceProgressListener(progressListener) tts.voice = tts.voices.find { it.name == "en-us-x-iog-local" } ?: tts.defaultVoice tts.speak("1 2 3", TextToSpeech.QUEUE_ADD, Bundle(), "utteranceId") } tts = TextToSpeech(this, onInitListener) } override fun onDestroy() { tts.shutdown() super.onDestroy() }}
Posted by Niharika Arora, Developer Relations Engineer
Building for Android Go involves paying special attention to performance optimizations and resource usage.
In part-1 of this blog, we discussed why developers should consider building for Android Go, some tips on optimizing the app memory and identified the standard approach to follow while fixing performance issues. In this blog, we will talk about the other vitals to pay attention to while building apps for Android Go.
Improving app startup time requires a deep understanding of things that affect it.
Move the tasks from UI thread to background thread
If there are tasks which are taking longer and blocking the main thread, try to move them to a background thread or prefer using WorkManager.
Lazy load third party libraries. A lot of libraries do have on demand initialization or disabling auto init options.
Identify and measure these transactions to understand :
Users often avoid downloading apps that seem too large, particularly in emerging markets where devices connect to spotty 2G and 3G networks with low bandwidth speed or work on pay-by-the-byte plans.
a. Don’t translate internal-only UI strings. Mark them as translatable = “false”.
b. Remove unused alternative resources: You can use the Android Gradle plugin's resConfigs property to remove alternative resource files that your app does not need. if you are using a library that includes language resources (such as AppCompat or Google Play Services), then your app includes all translated language strings for the messages in those libraries whether the rest of your app is translated to the same languages or not. If you'd like to keep only the languages that your app officially supports, you can specify those languages using the resConfig property. Any resources for languages not specified are removed.
The following snippet shows how to limit your language resources to just English and French
android { defaultConfig { ... resConfigs "en", "fr" }}
You can read more here.c. Don’t translate what doesn’t need translation: If the string does not participate in a UI, it should not be translated. Strings for the purpose of debugging, exception messages, URLs and so on should be string literals in code, not resources. i. Don’t translate what’s not shown to the user anywayIt’s possible to have a String resource that’s practically never shown to the user, but is still strongly referenced. One example is in your <activity>, if you have an android:label set and referencing a String resource but the Activity’s label is never actually shown (e.g. it’s not a launcher Activity and it doesn’t have an app bar that shows its own label). d. Don’t translate URLs: Consider this example:
You can read more here.
c. Don’t translate what doesn’t need translation: If the string does not participate in a UI, it should not be translated. Strings for the purpose of debugging, exception messages, URLs and so on should be string literals in code, not resources.
i. Don’t translate what’s not shown to the user anyway
It’s possible to have a String resource that’s practically never shown to the user, but is still strongly referenced. One example is in your <activity>, if you have an android:label set and referencing a String resource but the Activity’s label is never actually shown (e.g. it’s not a launcher Activity and it doesn’t have an app bar that shows its own label).
d. Don’t translate URLs: Consider this example:
<string name="car_frx_device_incompatible_sol_message">This device doesn\'t support Android Auto.\n<a href="https://support.google.com/androidauto/answer/6395843">Learn more</a></string>
<string name="car_frx_device_incompatible_sol_message">
This device doesn\'t support Android Auto.\n
<a href="https://support.google.com/androidauto/answer/6395843">Learn more</a>
</string>
You may recognize < and > - these are escape characters for “<” and “>”. They’re needed here because if you were to put an <a> tag inside a <string> tag, then the Android resource compiler would just drop them (as it does with all tags it doesn’t recognize). However, this means that you’re translating the HTML tags and the URL to 78 languages. Totally unnecessary. Instead, remove the part with HTML:
You may recognize < and > - these are escape characters for “<” and “>”. They’re needed here because if you were to put an <a> tag inside a <string> tag, then the Android resource compiler would just drop them (as it does with all tags it doesn’t recognize).
However, this means that you’re translating the HTML tags and the URL to 78 languages. Totally unnecessary.
Instead, remove the part with HTML:
<string name="car_frx_device_incompatible_sol_message">This device doesn\'t support Android Auto.</string>
This device doesn\'t support Android Auto.
Note we don’t define a separate string for “Learn more”, because it’s a common string. To produce the HTML snippet for the link, we define "<a href="https://support.google.com/androidauto/answer/6395843>%s</a>" as a string literals in code, and then drop the value of “Learn more” from resources into the format specifier.
e. Inline untranslated strings: By specifying strings in strings.xml you can leverage the Android framework to automatically change the actual value used at runtime based on the current configuration (e.g. based on the current locale, show a localized value for the string).
f. Remove duplicate strings: If you have the same string multiple times as a literal in code (“Hello World”), it will be shared across all instances. But resources don’t work this way - if you have an identical string under a different name then unless both are translated identically across 78 languages (unlikely) you’ll end up with duplicates.
Don’t have duplicate strings!
g. Don’t have separate strings for ALL CAPS or Title Case: Android has built-in support for case mutations.
Use android:capitalize (since API level 1). If set, specifies that this TextView has a textual input method and should automatically capitalize what the user types. The default is "none".
Posted by Marcus Leal, Product Manager, Google Play
Over the years, Android has evolved to support more devices such as watches, tablets, TVs, and even cars. Apps and games are a critical part of this ecosystem as they power many of the unique digital experiences that we all enjoy and rely on. As a way to make it easier for users to find your great apps across all Android devices, we are making changes to the Google Play Store, enabling users to more easily discover and install apps on other devices directly from their phone.
We recently introduced three updates to the Play Store phone app that will help your users’ devices work better together: homepages for non-phone devices, a device search filter, and the ability to remotely install an app to another device.
Users with a Wear OS watch, Android TV OS, or car with Android Automotive can navigate to the Play Store “Other devices” page on their phone app to see app and game recommendations, and editorials tailored to their non-phone devices.
Users can use the device filters to easily find apps and games optimized for their Wear watch, Android TV, or Android Auto-enabled devices.
These changes were designed to give developers new opportunities to showcase their multi-device app experiences, driving more engagement across the Android ecosystem.
Posted by Patricia Correa, Director, Global Developer Marketing
Posted by Yuri Blaise, Product Manager, Android
Gradle Managed Virtual Devices also introduces a completely new type of device, called the Automated Test Device, which is optimized for automated tests, resulting in significant reduction in CPU and memory usage during test execution. Learn more.
@Preview
To recap, Android Studio Dolphin includes these new enhancements and features:
Development Tools
Download
Download the latest version of Android Studio Dolphin from the download page. If you are using a previous release of Android Studio, you can simply update to the latest version of Android Studio. If you want to maintain a stable version of Android Studio, you can run the stable release version and canary release versions of Android Studio at the same time. Learn more.
To use the mentioned Android Emulator features make sure you are running at least Android Emulator v31.3.0 downloaded via the Android Studio SDK Manager.
We appreciate any feedback on things you like, and issues or features you would like to see. If you find a bug or issue, feel free to file an issue. Follow us -- the Android Studio development team on Twitter and on Medium.