social media

New ways to reach more drivers on Android for cars

<img src="https://4.bp.blogspot.com/-vKb1-7G-Hhc/XzGjZ55QbCI/AAAAAAAAPcs/o6EntDHnGbcodAILNSb6RwYYA_9sNrhvwCLcBGAsYHQ/s1600/Image%2B1_%2BEAP%2BAndroid%2BAuto%2Bapp%2Bexpansion.png"><p><em>Posted by Mickey Kataria, Director of Product Management, Android for cars</em></p><p> </p><p> <em>This blog post is part of a weekly series for <a href="https://twitter.com/search?q=%2311WeeksOfAndroid&src=typed_query">#11WeeksOfAndroid</a>. For each week, we’re diving into a key area and this week we’re focusing on Android Beyond Phones. Today, we’ll be talking about cars.</em> </p> <p> Since 2014, Google has been committed to bringing the familiarity of apps and services from Android phones into the car in a safe and seamless way. We’re continuing to see strong momentum and adoption of both <a href="https://www.android.com/auto/">Android Auto</a> and <a href="https://source.android.com/devices/automotive/start/what_automotive">Android Automotive OS</a>, and are excited to share new improvements that provide app developers the opportunity to reach more users in the car. </p> <p> <strong>Android Auto momentum</strong> </p> <p> We launched <a href="https://www.android.com/auto/">Android Auto</a> for users to stay connected on-the-go and more easily access their Android phones on their car displays— while staying focused on the road. Android Auto is currently available with nearly every major car manufacturer and is on track to be in more than 100 million cars in the coming months. Many car manufacturers, including General Motors, BMW and Kia, have also added support for wireless connections, making it easier for drivers to use Android Auto as soon as they get into their car. We’re continuing to add <a href="https://blog.google/products/android/five-new-android-features">new features</a> to make the experience more seamless for users and help developers reach more drivers with in-car apps. </p> <p> <strong>Expanding Android Auto’s app ecosystem</strong> </p> <p> One of our most common requests for Android Auto continues to be support for more apps in the car. We currently have over 3,000 apps in Google Play whose in-car experiences have been purpose-built for driving. </p> <p> Today, we’re showcasing our work with early access partners to build apps in new categories for Android Auto, including navigation, parking and electric vehicle charging. Using our new Android for Cars App Library, we’re able to ensure that all tasks within an app can be achieved with minimal glances or taps. </p> <a href="https://4.bp.blogspot.com/-vKb1-7G-Hhc/XzGjZ55QbCI/AAAAAAAAPcs/o6EntDHnGbcodAILNSb6RwYYA_9sNrhvwCLcBGAsYHQ/s1600/Image%2B1_%2BEAP%2BAndroid%2BAuto%2Bapp%2Bexpansion.png"><img border="0" src="https://4.bp.blogspot.com/-vKb1-7G-Hhc/XzGjZ55QbCI/AAAAAAAAPcs/o6EntDHnGbcodAILNSb6RwYYA_9sNrhvwCLcBGAsYHQ/s1600/Image%2B1_%2BEAP%2BAndroid%2BAuto%2Bapp%2Bexpansion.png" data-original-width="1600" data-original-height="835" alt="image"></a> <p> Early access partners for new apps on Android Auto </p> <p> To mitigate driver distraction, we collaborated with government, industry and academic institutions to develop our own <a href="https://www.youtube.com/watch?v=OFHjmDrUF9A">best practice guidelines</a> that we apply to every aspect of our product development process. With our standard templates and guidelines, developers have the tools to easily optimize their apps for cars, without needing to become an expert in driver distraction. </p> <p> Our early access partners will be releasing new apps to their beta testers by the end of this year. Pending additional testing and feedback, we then plan to make these APIs publicly available for all developers to build Android Auto apps in these categories. </p> <p> </p> <a href="https://3.bp.blogspot.com/-q1PE31sWfXk/XzHU2kf2eJI/AAAAAAAAPdw/6DQF9Q3JFpMZP8mMTbB8HEMOQeyK74ljACLcBGAsYHQ/s1600/final_5f31ce27e5bc060015ae78e4_186813%2B%25282%2529%2B%25281%2529.gif"><img border="0" src="https://3.bp.blogspot.com/-q1PE31sWfXk/XzHU2kf2eJI/AAAAAAAAPdw/6DQF9Q3JFpMZP8mMTbB8HEMOQeyK74ljACLcBGAsYHQ/s1600/final_5f31ce27e5bc060015ae78e4_186813%2B%25282%2529%2B%25281%2529.gif" data-original-width="1280" data-original-height="762" alt="Android"></a> <p> We're partnering with some of the leading navigation, parking and electric vehicle charging apps around the world including ChargePoint, SpotHero and Sygic. </p> <p> <strong>Android Automotive OS adoption</strong> </p> <p> More recently, we introduced <a href="https://source.android.com/devices/automotive/start/what_automotive">Android Automotive OS</a> as a full-stack, open source and highly customizable platform powering vehicle infotainment systems. With Android Automotive OS, car manufacturers are able to have apps and services like Google Assistant, Google Maps and Google Play built into vehicles so that a mobile device is not required for common activities like navigation, downloading third-party apps and listening to media. <a href="https://www.polestar.com/us/polestar-2/">Polestar 2</a>, the first car running Android Automotive OS with Google built in, is now on the road and available for customers globally. In addition, Volvo Cars, Renault, General Motors and more have announced plans for infotainment systems powered by Android Automotive OS with Google apps and services built-in. </p> <p> <strong>Extending the reach of media apps in cars</strong> </p> <p> As more manufacturers begin to ship cars with infotainment systems powered by Android Automotive OS, developers have the opportunity to deliver a seamless media experience using Google Play in the car. If you already have a media app for Android Auto, you can extend the reach by adding support for Android Automotive OS. The process for porting over your apps is simple with most of the work already done, just <a href="https://developer.android.com/training/cars/media/automotive-os">follow these steps</a>. </p> <p> <strong>Making it easier to develop media apps for Android Automotive OS </strong> </p> <p> For the past year, we have been on a journey to allow app developers to design, develop, test and publish media apps directly on Google Play in the car. We are happy to share that this is now possible. </p> <div> <a href="https://1.bp.blogspot.com/-sZ0_6GQV6zY/XzGmSw3Q2-I/AAAAAAAAPdE/6wa8TYfWFQM-krqiwqS4EvoQugyy7UMswCLcBGAsYHQ/s1600/Image%2B3_%2BPolestar%2B2%2BEmulator.png"><img border="0" src="https://1.bp.blogspot.com/-sZ0_6GQV6zY/XzGmSw3Q2-I/AAAAAAAAPdE/6wa8TYfWFQM-krqiwqS4EvoQugyy7UMswCLcBGAsYHQ/s1600/Image%2B3_%2BPolestar%2B2%2BEmulator.png" alt="Android Auto image"></a> <a href="https://2.bp.blogspot.com/-lSjoQ291WB0/XzGmvaJXcnI/AAAAAAAAPdM/jzYb7GuOkecrwqj5JajFsw-y0tFiUXBrwCLcBGAsYHQ/s1600/Image%2B4_%2BGoogle%2BGeneric%2BEmulator.png"><img border="0" src="https://2.bp.blogspot.com/-lSjoQ291WB0/XzGmvaJXcnI/AAAAAAAAPdM/jzYb7GuOkecrwqj5JajFsw-y0tFiUXBrwCLcBGAsYHQ/s1600/Image%2B4_%2BGoogle%2BGeneric%2BEmulator.png" alt="Image of Polestar 2 and Google Generic Automative system"></a> </div> <p> Polestar 2 and Google Generic Automotive system images for Android emulator </p> <p> We have made updates to the Android Automotive OS <a href="https://designguidelines.withgoogle.com/automotive-os-apps/">design guidelines</a> and <a href="https://developer.android.com/training/cars/media/automotive-os">development documentation</a> for you to add support for your media apps. We also launched updates to the <a href="https://developer.android.com/training/cars/testing#system-images">emulator</a> to include Google Assistant, Google Maps and Google Play, so you can develop and test your apps in an environment that more closely mirrors the software in the car. The <a href="https://developer.android.com/training/cars/testing#system-images">Polestar 2 system image</a> enables you to test your app on similar software that is available on the road today. Lastly, the <a href="http://play.google.com/console">Play Console</a> now accepts Android Automotive OS APKs, enabling you to simply upload your app for quality review and publishing. These changes allow developers to seamlessly complete the end-to-end development process for Android Automotive OS. </p> <a href="https://2.bp.blogspot.com/-Akp0li2-5-k/XzGnzCQCR1I/AAAAAAAAPdY/SDywcW3wJ84MbuJOjyqKAg_fQI4sjhvoACLcBGAsYHQ/s1600/Image%2B5_%2BGoogle%2BPlay%2Bon%2BAndroid%2BAutomotive%2BOS.gif"><img border="0" src="https://2.bp.blogspot.com/-Akp0li2-5-k/XzGnzCQCR1I/AAAAAAAAPdY/SDywcW3wJ84MbuJOjyqKAg_fQI4sjhvoACLcBGAsYHQ/s1600/Image%2B5_%2BGoogle%2BPlay%2Bon%2BAndroid%2BAutomotive%2BOS.gif" data-original-width="1152" data-original-height="1536" alt="Image of Google Play features"></a> <p> Google Play features many media apps today, including Spotify, iHeartRadio, NPR One and more. </p> <p> To learn more about how to create an app for Android Automotive OS, look out for updates or post on the <a href="https://groups.google.com/a/android.com/forum/#!forum/automotive-developers">automotive-developers</a> Google Group or Stack Overflow using <a href="https://stackoverflow.com/questions/tagged/android-automotive">android-automotive</a> tags. </p> <p> With new app expansion on Android Auto and improved development tools for Android Automotive OS, developers have more opportunity than ever to reach users with app experiences optimized for the car. Head over to <a href="http://developer.android.com/cars">developer.android.com/cars</a> to get started! </p> <p> <strong>Resources</strong> </p> <p> <em>You can find the entire playlist of #11WeeksOfAndroid video content <a href="https://www.youtube.com/user/androiddevelopers">here</a>, and learn more about each week <a href="http://d.android.com/android11">here</a>. We’ll continue to spotlight new areas each week, so <a href="https://android-developers.googleblog.com/">keep an eye out</a> and follow us on <a href="https://twitter.com/androiddev">Twitter</a> and <a href="https://www.youtube.com/user/androiddevelopers">YouTube</a>. Thanks so much for letting us be a part of this experience with you! </em> </p><div> <a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=a5lcR463iT8:rnmsUAfkTCs:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?d=yIl2AUoC8zA" border="0"></a> <a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=a5lcR463iT8:rnmsUAfkTCs:-BTjWOF_DHI"><img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?i=a5lcR463iT8:rnmsUAfkTCs:-BTjWOF_DHI" border="0"></a> </div><img src="http://feeds.feedburner.com/~r/blogspot/hsDu/~4/a5lcR463iT8" height="1" width="1" alt="">

6 New ways to engage with users on Android TV

Posted by Dan Aharon, Product Manager, Android TV This blog post is part of a weekly series for #11WeeksOfAndroid. This week we’re focusing on Android Beyond Phones. So what’s new on Android TV?. With users asking for more TV shows, movies, ...

11 Weeks of Android: Android Developer Tools

Posted by Jamal Eason, Product Manager, Android This blog post is part of a weekly series for #11WeeksOfAndroid. For each of the #11WeeksOfAndroid, we’re diving into a key area so you don’t miss anything. This week, we spotlighted Android Develo...

Introducing the Motion Editor

Posted by Scott Swarthout, Product Manager We spoke with the Android developer community and learned that animations are important for making UIs more intuitive and memorable. However, we also heard that adding complex animation to Android apps ha...

11 Weeks of Android: Jetpack

Posted by Diana Wong, Product Manager, Android Jetpack This blog post is part of a weekly series for #11WeeksOfAndroid. For each of the #11WeeksOfAndroid, we’re diving into a key area so you don’t miss anything.This week, we spotlighted Jetpack; h...

Decrease startup time with Jetpack App Startup

<img src="https://3.bp.blogspot.com/-nQZnpkNzvHg/Xxiu-grxEuI/AAAAAAAAPTY/SaDDpJtTY-ovG6kQqKRHEMJDJ3ivhVJRgCLcBGAsYHQ/s1600/Jetpack_Decrease_Starup_Time.png"><p><em>Posted by <a href="https://twitter.com/yrezgui">Yacine Rezgui</a>, Developer Advocate and <a href="https://twitter.com/tikurahul">Rahul Ravikumar</a>, Software Engineer</em></p><p> </p> <a href="https://3.bp.blogspot.com/-nQZnpkNzvHg/Xxiu-grxEuI/AAAAAAAAPTY/SaDDpJtTY-ovG6kQqKRHEMJDJ3ivhVJRgCLcBGAsYHQ/s1600/Jetpack_Decrease_Starup_Time.png"><img border="0" src="https://3.bp.blogspot.com/-nQZnpkNzvHg/Xxiu-grxEuI/AAAAAAAAPTY/SaDDpJtTY-ovG6kQqKRHEMJDJ3ivhVJRgCLcBGAsYHQ/s1600/Jetpack_Decrease_Starup_Time.png" data-original-width="1600" data-original-height="476" alt="Jetpack image"></a> <p> Application startup time is a critical metric for any application. Users expect apps to be responsive and fast to load. When an application does not meet this expectation, it can be disappointing to users. This poor experience may cause a user to rate your app badly on the Play store, or even abandon your app altogether. </p> <p> <a href="https://developer.android.com/topic/libraries/app-startup">Jetpack App Startup</a> is a library that provides a straightforward, performant way to initialize components at application startup. Both library developers and app developers can use App Startup to streamline startup sequences and explicitly set the order of initialization. </p> <p> Apps and libraries often rely on having components (<code>WorkManager</code>, <code>ProcessLifecycleObserver</code>, <code>FirebaseApp</code> etc.) initialized before <code>Application.onCreate()</code>. This is usually achieved by using content providers to initialize each dependency. Instead of defining separate content providers for each component that needs to be initialized, App Startup lets you define initializers that share a single content provider. This significantly improves app startup time, usually by ~2ms per content provider. App Startup also helps you <strong>further improve startup performance</strong> by making it really easy to <a href="https://developer.android.com/topic/libraries/app-startup#disable-individual">initialize components lazily</a>. When App Startup goes stable, we will be updating our libraries like `WorkManager` and `ProcessLifecycle` to benefit from this as well. </p> <p> App Startup supports API level 14 and above. </p> <h2>How to use it</h2> <b>Gradle setup</b> <p> To use App Startup in your library or app, add the following dependency to your gradle file: </p> <pre>repositories { google() maven() } dependencies { implementation "androidx.startup:startup-runtime:1.0.0-alpha02" } </pre> <b>Define an Initializer</b> <p> To be able to use App Startup in your application, you need to define an<a href="https://developer.android.com/topic/libraries/app-startup#implement-initializers"> Initializer</a>. This is where you define how to initialize and specify your dependencies. Here’s the interface you need to implement: </p> <pre>interface Initializer<out T: Any> { fun create(context: Context): T fun dependencies(): List<Class<out Initializer<*>>> }</pre> <p> As a practical example, here’s what an <code>Initializer</code> that initializes <strong>WorkManager</strong> might look like: </p> <pre>class WorkManagerInitializer : Initializer<WorkManager> { override fun create(context: Context): WorkManager { val configuration = Configuration.Builder() .setMinimumLoggingLevel(Log.DEBUG) .build() WorkManager.initialize(context, configuration) return WorkManager.getInstance(context) } // This component does not have any dependencies override fun dependencies() = emptyList<Class<out Initializer<*>>>() }</pre> <p> <b>Note: </b> <i>This example is purely illustrative. This <code>Initializer</code> should actually be defined by the WorkManager library.</i> </p> <p> Lastly, we need to add an entry for <code>WorkManagerInitializer</code> in the <code>AndroidManifest.xml</code>: </p> <pre><provider android:name="androidx.startup.InitializationProvider" android:authorities="${applicationId}.androidx-startup" android:exported="false" tools:node="merge"> <!-- This entry makes WorkManagerInitializer discoverable. --> <meta-data android:name="com.example.WorkManagerInitializer" android:value="androidx.startup" /> </provider></pre> <h2>How it works</h2> <p> App Startup uses a single content provider called <code>InitializationProvider</code>. This content provider discovers initializers by introspecting the <code><meta-data></code> entries in the merged <code>AndroidManifest.xml</code> file. This happens before <code>Application.onCreate()</code>. </p> <p> After the discovery phase, it subsequently initializes a component after having initialized all its dependencies. Therefore, a component is <strong>only initialized after</strong> all its dependencies have been initialized. </p> <h2>Lazy initialization</h2> <p> We highly recommend using lazy initialization to further improve startup performance. To make initialization of a component lazy, you need to do the following: </p> <p> Add a <code>tools:node="remove"</code> attribute to the <code><meta-data></code> entry for the <code>Initializer</code>. This disables eager initialization. </p> <pre><provider android:name="androidx.startup.InitializationProvider" android:authorities="${applicationId}.androidx-startup" android:exported="false" tools:node="merge"> <!-- disables eager initialization --> <meta-data android:name="com.example.WorkManagerInitializer" tools:node="remove" /> </provider></pre> <p> To lazily initialize <code>WorkManagerInitializer</code> you can then use: </p> <pre>// This returns an instance of WorkManager AppInitializer.getInstance(context) .initializeComponent(WorkManagerInitializer.class);</pre> <p> Your app now initializes the component lazily. For more information, please read our detailed documentation <a href="https://developer.android.com/topic/libraries/app-startup#disable-individual">here</a>. </p> <h2>Final thoughts</h2> <p> App Startup is currently in <code>alpha-02</code>. Find out more about how to use it from our <a href="https://developer.android.com/topic/libraries/app-startup">documentation</a>. Once you try it out, help us make it better by giving us feedback on the <a href="https://issuetracker.google.com/components/823348#basic">issue tracker</a>. </p><div> <a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=C42xoR2gU4c:WDE0jF_quU8:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?d=yIl2AUoC8zA" border="0"></a> <a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=C42xoR2gU4c:WDE0jF_quU8:-BTjWOF_DHI"><img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?i=C42xoR2gU4c:WDE0jF_quU8:-BTjWOF_DHI" border="0"></a> </div><img src="http://feeds.feedburner.com/~r/blogspot/hsDu/~4/C42xoR2gU4c" height="1" width="1" alt="">

What’s New in Navigation 2020

<img src="http://android-developers.googleblog.com/"><p><em>Posted by Jeremy Woods, Software Engineer, Android UI Toolkit </em></p><p> </p> <a href="https://4.bp.blogspot.com/-igLPrJ5bA8M/Xxi0yzegEAI/AAAAAAAAPTk/si7V5QsW_18fr_RGOr3SH-xrPdWqTYc-wCLcBGAsYHQ/s1600/What%25E2%2580%2599s%2BNew%2Bin%2BNavigation%2B2020%2Bv02.png"><img border="0" src="https://4.bp.blogspot.com/-igLPrJ5bA8M/Xxi0yzegEAI/AAAAAAAAPTk/si7V5QsW_18fr_RGOr3SH-xrPdWqTYc-wCLcBGAsYHQ/s1600/What%25E2%2580%2599s%2BNew%2Bin%2BNavigation%2B2020%2Bv02.png" data-original-width="1024" data-original-height="512" alt="Navigation image"></a> <p> The latest versions of the Jetpack Navigation library (2.2.0 and 2.3.0) added a lot of requested features and functionality, including <a href="https://developer.android.com/guide/navigation/navigation-dynamic">dynamic navigation</a>, <a href="https://developer.android.com/reference/androidx/navigation/NavBackStackEntry">navigation back stack entries</a>, a library for <a href="https://developer.android.com/reference/kotlin/androidx/navigation/testing/TestNavHostController">navigation testing</a>, additional features for <a href="https://developer.android.com/guide/navigation/navigation-navigate#uri">deep linking</a>, and more. Let’s go over the most important changes, see what problems they solve, and learn how to use them! </p> <h2>Dynamic Navigation</h2> <p> We’ve updated Navigation to simplify adding dynamic feature modules for your application. </p> <p> Previously, implementing navigation between destinations defined in dynamic feature modules required a lot of work. Before you could navigate to the first dynamic destination, you needed to add the Play Core library and the Split Install API to your app. You also needed to check for and download the dynamic module. Once downloaded, you could then finally navigate to the destination. On top of this, if you wanted to have an on-screen progress bar for the module being downloaded, you needed to implement a <code>SplitInstallManager</code> listener. </p> <p> To address this complexity, we created the Dynamic Navigator library. This library extends the functionality of the Jetpack Navigation library to provide seamless installation of on-demand dynamic feature modules when navigating. The library handles all Play Store interaction for you, and it even includes a progress screen that provides the download status of your dynamic module. </p> <a href="https://3.bp.blogspot.com/-oO5hDxQNAJc/XxiUD9LVzhI/AAAAAAAAPSg/PiUNldhIeL0FipRFA2qsG76nHXqhKKF_ACLcBGAsYHQ/s1600/On%2BDemand%2BSample.png"><img border="0" src="https://3.bp.blogspot.com/-oO5hDxQNAJc/XxiUD9LVzhI/AAAAAAAAPSg/PiUNldhIeL0FipRFA2qsG76nHXqhKKF_ACLcBGAsYHQ/s1600/On%2BDemand%2BSample.png" data-original-width="1600" data-original-height="1487" alt="The default UI for showing a progress bar when a user navigates to a dynamic feature for the first time."></a> <p> The default UI for showing a progress bar when a user navigates to a dynamic feature for the first time. The app displays this screen as the corresponding module downloads </p>id="imgCaption"> <p> To use dynamic navigation, all you need to do is: </p> <ol><li>Change instances of <code><a href="https://developer.android.com/reference/kotlin/androidx/navigation/fragment/NavHostFragment.html">NavHostFragment</a></code> to <code><a href="https://developer.android.com/reference/kotlin/androidx/navigation/dynamicfeatures/fragment/DynamicNavHostFragment">DynamicNavHostFragment</a></code> </li><li>Add an <code>app:moduleName</code> attribute to the destinations associated with a <code><a href="https://developer.android.com/reference/kotlin/androidx/navigation/dynamicfeatures/fragment/DynamicNavHostFragment">DynamicNavHostFragment</a></code> </li> </ol><p> For more information on dynamic navigation, see <a href="https://developer.android.com/guide/navigation/navigation-dynamic">Navigate with dynamic feature modules</a> and <a href="https://github.com/android/app-bundle-samples/tree/master/DynamicFeatureNavigation">check out the samples</a>. </p> <h2>NavBackStackEntry: Unlocked</h2> <p> When you navigate from one destination to the next, the previous destination and its latest state is placed on the Navigation back stack. If you return to the previous destination by using <code><a href="https://developer.android.com/reference/kotlin/androidx/navigation/NavController#popBackStack(kotlin.Int,%20kotlin.Boolean)">navController.popBackBack()</a></code>, the top back stack entry is removed from the back stack with its state still intact and the <code><a href="https://developer.android.com/reference/kotlin/androidx/navigation/NavDestination">NavDestination</a></code> is restored. The Navigation back stack contains all of the previous destinations that were needed to arrive at the current <code><a href="https://developer.android.com/reference/kotlin/androidx/navigation/NavDestination">NavDestination</a></code>. </p><p> We manage the destinations on the Navigation back stack by encapsulating them into the <code><a href="https://developer.android.com/reference/androidx/navigation/NavBackStackEntry">NavBackStackEntry</a></code> class. <code>NavBackStackEntry</code> is now public. This means that users can go a level deeper than just <code>NavDestinations</code> and gain access to navigation-specific <code><a href="https://developer.android.com/reference/kotlin/androidx/lifecycle/ViewModel">ViewModel</a></code>s, <code><a href="https://developer.android.com/reference/kotlin/androidx/lifecycle/Lifecycle">Lifecycle</a></code>s, and <a href="https://developer.android.com/reference/kotlin/androidx/savedstate/SavedStateRegistry">SavedStateRegistries</a>. You can now properly scope data sharing or ensure it is destroyed at the appropriate time. </p><p> See <a href="https://developer.android.com/guide/navigation/navigation-navigate#back-stack">Navigation and the back stack</a> for more information. </p> <h2>NavGraph ViewModels</h2> <p> Since a <code><a href="https://developer.android.com/reference/androidx/navigation/NavBackStackEntry">NavBackStackEntry</a></code> is a <code><a href="https://developer.android.com/reference/kotlin/androidx/lifecycle/ViewModelProvider">ViewModelProvider</a></code>, you can create a <code><a href="https://developer.android.com/reference/kotlin/androidx/lifecycle/ViewModel">ViewModel</a></code> to share data between destinations at the <code><a href="https://developer.android.com/reference/kotlin/androidx/navigation/NavGraph">NavGraph</a></code> level. Each parent navigation graph of all <code><a href="https://developer.android.com/reference/kotlin/androidx/navigation/NavDestination">NavDestinations</a></code> are on the back stack, so your view model can be scoped appropriately: </p><pre>val viewModel: MyViewModel by navGraphViewModels(R.id.my_graph) </pre> <p> For more information on navGraph scoped view models, see <a href="https://developer.android.com/guide/navigation/navigation-programmatic#share_ui-related_data_between_destinations_with_viewmodel">Share UI-related data between destinations with ViewModel</a> </p> <h2>Returning a Result from a destination</h2> <p> By combining <code><a href="https://developer.android.com/reference/kotlin/androidx/lifecycle/ViewModel">ViewModel</a></code> and <code><a href="https://developer.android.com/reference/kotlin/androidx/lifecycle/Lifecycle">Lifecycle</a></code>, you can share data between two specific destinations. To do this, <code><a href="https://developer.android.com/reference/androidx/navigation/NavBackStackEntry">NavBackStackEntry</a></code> provides a <code><a href="https://developer.android.com/reference/kotlin/androidx/lifecycle/SavedStateHandle">SavedStateHandle</a></code>, a key-value map that can be used to store and retrieve data, even across configuration changes. By using the given <code><a href="https://developer.android.com/reference/kotlin/androidx/lifecycle/SavedStateHandle">SavedStateHandle</a></code>, you can access and pass data between destinations. For example to pass data from destination A to destination B: </p><p> In destination A: </p> <pre>override fun onViewCreated(view: View, savedInstanceState: Bundle?) { val navController = findNavController(); // We use a String here, but any type that can be put in a Bundle is supported navController.currentBackStackEntry?.savedStateHandle?.getLiveData<String>("key")?.observe( viewLifecycleOwner) { result -> // Do something with the result. } } </pre> <p> And in destination B: </p> <pre>navController.previousBackStackEntry?.savedStateHandle?.set("key", result) </pre> <p> See <a href="https://developer.android.com/guide/navigation/navigation-programmatic#returning_a_result">Returning a result to the previous Destination</a> for more details. </p> <h2>Testing your Navigation Flow</h2> <p> Previously, the recommended testing solution for Navigation was Mockito. You would create a mock <code><a href="https://developer.android.com/reference/kotlin/androidx/navigation/NavController">NavController</a></code> and verify that <code><a href="https://developer.android.com/reference/kotlin/androidx/navigation/NavController#navigate(kotlin.Int)">navigate()</a></code> was called at the appropriate time with the correct parameters. Unfortunately, this solution was not enough to test certain areas of Navigation flow, such as <code><span>ViewModel</span></code> interaction or the Navigation back stack. The Navigation Library now offers a well-integrated solution for these areas with the Navigation Testing library. </p><p> The Navigation Testing library adds <code><a href="https://developer.android.com/reference/kotlin/androidx/navigation/testing/TestNavHostController">TestNavHostController</a></code>, which gives access to the Navigation back stack in a test environment. This means that you can now verify the state of the entire back stack. When using the <code><a href="https://developer.android.com/reference/kotlin/androidx/navigation/testing/TestNavHostController">TestNavHostController</a></code>, you can set your own <code><a href="https://developer.android.com/reference/kotlin/androidx/lifecycle/LifecycleOwner">LifecycleOwner</a></code>, <code><a href="https://developer.android.com/reference/kotlin/androidx/lifecycle/LifecycleOwner">ViewModelStoreOwner</a></code>, and <code><a href="https://developer.android.com/reference/kotlin/androidx/activity/OnBackPressedDispatcher">OnBackPressDispatcher</a></code> by using the APIs given by <code><a href="https://developer.android.com/reference/kotlin/androidx/navigation/NavHostController.html">NavHostController</a></code>. By setting these components, you can test them in the context of navigation. </p><p> For example, here's how to test a destination that uses a nav graph-scoped <code>ViewModel</code>: </p> <pre>val navController = TestNavHostController(ApplicationProvider.getApplicationContext()) // This allows fragments to use by navGraphViewModels() navController.setViewModelStore(ViewModelStore()) navController.setGraph(R.navigation.main_nav) </pre> <p> The <code>TestNavHostController</code> also lets you set the current destination. You can move the test directly to the use case being tested without the need to set it up using <code>navigate()</code> calls. This is extremely convenient for writing tests for different navigation scenarios. </p> <p> When setting the current destination, you might do something like the following: </p> <pre>val navController = TestNavHostController(ApplicationProvider.getApplicationContext()) navController.setGraph(R.navigation.main_nav) navController.setCurrentDestination(R.id.destination_1) </pre> <p> Remember that when setting the current destination, that destination must be part of your nav graph. </p> <p> For more information about <code>TestNavHostController</code>, see the <a href="https://developer.android.com/guide/navigation/navigation-testing">Test Navigation docs</a>. </p> <h2>Nav Deep Linking</h2> <p> Deep linking allows you to navigate directly to any destination no matter where you currently are in the <code><a href="https://developer.android.com/reference/kotlin/androidx/navigation/NavGraph">NavGraph</a></code>. This can be very useful for launching your app to a specific destination or jumping between destinations that would otherwise be inaccessible to one another. </p><p> When navigating using a deep link, you can now provide deep link query parameters in any order and even leave them out altogether if they have been given a default value or have been made nullable. This means that if you have provided default values for all of the query parameters on a deep link, the deep link can match a URL pattern without including any query parameters. </p> <p> For example,<code> <strong>www.example.com?arg1={arg1}&arg2={arg2}</strong></code> will now match with <strong><code>www.example.com</code></strong> as long as <code>arg1</code> and <code>arg2</code> have default values and/or are nullable. </p><p> Deep links can also be matched using intent actions and MIME types. Instead of requiring destinations to match by URI, you can provide the deep link with an action or MIME type and match with that instead. You can specify multiple match types for a single deep link, but note that <code><a href="https://developer.android.com/reference/java/net/URI?hl=en">URI</a></code> argument matching is prioritized first, followed by <code>action</code>, and then <code>mimeType</code>. </p><p> You create a deep link by adding it to a destination in XML, using the <a href="https://developer.android.com/guide/navigation/navigation-kotlin-dsl#deep">Kotlin DSL</a>, or by using the Navigation Editor in Android Studio. </p> <p> Here's how to add a deep link to a destination using XML: </p> <pre><fragment android:id="@+id/a" android:name="com.example.myapplication.FragmentA" tools:layout="@layout/a"> <deeplink app:url="www.example.com" app:action="android.intent.action.MY_ACTION" app:mimeType="type/subtype"/> </fragment> </pre> <p> Here's how to add the same deep link using the Kotlin DSL: </p> <pre>val baseUri = "http://www.example.com/" fragment<MyFragment>(nav_graph.dest.a) { deepLink(navDeepLink { uriPattern = "${baseUri}" action = "android.intent.action.MY_ACTION" mimeType = "type/subtype" }) } </pre> <p> You can also add the same deep link using the Navigation Editor in Android Studio versions 4.1 and higher. Note that you must also be using the Navigation 2.3.0-alpha06 dependency or later. </p> <a href="https://1.bp.blogspot.com/-pdWiqpW1gXw/XxiWRV0uTDI/AAAAAAAAPSs/yXRuANB1Jv4ylvxb3sez-dt44FXQRiVQACLcBGAsYHQ/s1600/Navigation%2B2020.png"><img border="0" src="https://1.bp.blogspot.com/-pdWiqpW1gXw/XxiWRV0uTDI/AAAAAAAAPSs/yXRuANB1Jv4ylvxb3sez-dt44FXQRiVQACLcBGAsYHQ/s1600/Navigation%2B2020.png" data-original-width="512" data-original-height="285" alt="An open dialog in the Navigation Editor for adding a deep link to a destination. There are options to add an URI, a MIME type, and an action, along with a checkBox to Auto Verify"></a> <p> Adding a deep link to a destination in the Navigation Editor </p>id="imgCaption"><p> </p><p> To navigate to a destination using a deep link, you must first build a <code><span>NavDeepLinkRequest</span></code> and then pass that deep link request into the Navigation controller's call to <code><span>navigate()</span></code>: </p><pre>val deepLinkRequest = NavDeepLinkRequest.Builder .fromUri(Uri.parse("http://www.example.com")) .setAction("android.intent.action.MY_ACTION") .setMimeType("type/subtype") .build() navController.navigate(deeplinkRequest) </pre> <p> For more information on deep links, visit <a href="https://developer.android.com/guide/navigation/navigation-deep-link">Create a deep link for a destination</a>, as well as the deep linking sections in <a href="https://developer.android.com/guide/navigation/navigation-navigate#uri">Navigate to a destination</a> and <a href="https://developer.android.com/guide/navigation/navigation-kotlin-dsl#deep">Kotlin DSL</a>. </p> <h2>Navigation Editor</h2> <p> Android Studio 4.0 includes new features for the Navigation Editor. You can now edit your destinations using a split pane view. This means you can edit the XML or design and see the changes in real time. </p> <a href="https://3.bp.blogspot.com/-OrKSwU1pDp4/XxiW3r7JExI/AAAAAAAAPS0/X6ilvTUqRvMhqJKKqI-DHyEMeKEZy6BMgCLcBGAsYHQ/s1600/split-mode-screenshot.png"><img border="0" src="https://3.bp.blogspot.com/-OrKSwU1pDp4/XxiW3r7JExI/AAAAAAAAPS0/X6ilvTUqRvMhqJKKqI-DHyEMeKEZy6BMgCLcBGAsYHQ/s1600/split-mode-screenshot.png" data-original-width="1600" data-original-height="890" alt="The Navigation Editor opened in split pane mode with the navigation.xml file on the left and the corresponding nav graph on the right. The nav graph has 6 destination, and a nested graph"></a> <p> Viewing a navigation.xml file in split view mode </p>id="imgCaption"><p> </p><p> In Android Studio 4.1, the Navigation Editor introduced the component tree. This allows you to traverse the entire nav graph, freely going in and out of nested graphs. </p> <a href="https://4.bp.blogspot.com/-Vi4AOZ9oiGQ/XxiYmmZMvVI/AAAAAAAAPTA/9eJM-PBEoQ0PcKuY8337m9LXvmUJmcK9ACLcBGAsYHQ/s1600/new-component-tree.gif"><img border="0" src="https://4.bp.blogspot.com/-Vi4AOZ9oiGQ/XxiYmmZMvVI/AAAAAAAAPTA/9eJM-PBEoQ0PcKuY8337m9LXvmUJmcK9ACLcBGAsYHQ/s1600/new-component-tree.gif" data-original-width="1600" data-original-height="889" alt="An open component tree of a nav graph in the Navigation Editor. It starts viewing the entire graph, then moves to the title screen before going into the nested profiles graph. After cycling through the destinations in the profiles graph, it goes back to fragments in the original graph"></a> <p> </p> <p> Navigating through a graph in the Navigation Editor </p>id="imgCaption"><p> </p><h2>Additional Changes</h2> <p> <code><a href="https://developer.android.com/reference/androidx/navigation/ui/NavigationUI?hl=en">NavigationUI</a></code> can now use any layout that uses the <code><a href="https://developer.android.com/reference/kotlin/androidx/customview/widget/Openable?hl=en">Openable</a></code> interface. This means that it is no longer limited to <code><a href="https://developer.android.com/reference/kotlin/androidx/drawerlayout/widget/DrawerLayout?hl=en">DrawerLayout</a></code> and allows for customization of the <code><a href="https://developer.android.com/reference/androidx/navigation/ui/AppBarConfiguration?hl=en">AppBarConfiguration</a></code>. You can provide your <code><a href="https://developer.android.com/reference/kotlin/androidx/customview/widget/Openable?hl=en">Openable</a></code> and use it as the layout instead. </p><p> Navigation also provides support for Kotlin DSL. Kotlin DSL can be used to create different destinations, actions, or deep links. For more information see the <a href="https://developer.android.com/guide/navigation/navigation-kotlin-dsl">documentation for Kotlin DSL</a>. </p> <h2>Wrap up</h2> <p> Navigation added lots of useful features over the past year. You can simplify your dynamic feature modules by taking advantage of the Dynamic Navigator library, use a <code>NavBackStackEntry</code> to help correctly scope your data, easily test your navigation flow using the <code>TestNavHostController</code>, or even match your deep link using intent actions and/or MIME types. </p> <p> For more information about the Jetpack Navigation library, check out the documentation at <a href="https://developer.android.com/guide/navigation">https://developer.android.com/guide/navigation</a> </p> <p> Please provide feedback (or file bugs) using the <a href="http://www.issuetracker.google.com/issues?q=componentid:409828">Navigation issuetracker component</a>. </p><div> <a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=FX5yH2GrOfU:EPlb0nJfe-s:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?d=yIl2AUoC8zA" border="0"></a> <a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=FX5yH2GrOfU:EPlb0nJfe-s:-BTjWOF_DHI"><img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?i=FX5yH2GrOfU:EPlb0nJfe-s:-BTjWOF_DHI" border="0"></a> </div><img src="http://feeds.feedburner.com/~r/blogspot/hsDu/~4/FX5yH2GrOfU" height="1" width="1" alt="">

Getting on the same page with Paging 3

<img src="https://3.bp.blogspot.com/-eGu7cn6d12k/XxIE85ezRwI/AAAAAAAAPQk/Pej7vTRjtRw-fAv6U-KwupNSV9FV92kTgCLcBGAsYHQ/s1600/Paging%2Bdata%2Bwith%2Bpaging%2B3.0%2Bv03.png"><p><em>Posted by <a href="https://twitter.com/FMuntenescu">Florina Muntenescu</a>, Android Developer Advocate</em></p><p> <a href="https://3.bp.blogspot.com/-eGu7cn6d12k/XxIE85ezRwI/AAAAAAAAPQk/Pej7vTRjtRw-fAv6U-KwupNSV9FV92kTgCLcBGAsYHQ/s1600/Paging%2Bdata%2Bwith%2Bpaging%2B3.0%2Bv03.png"><img border="0" src="https://3.bp.blogspot.com/-eGu7cn6d12k/XxIE85ezRwI/AAAAAAAAPQk/Pej7vTRjtRw-fAv6U-KwupNSV9FV92kTgCLcBGAsYHQ/s1600/Paging%2Bdata%2Bwith%2Bpaging%2B3.0%2Bv03.png" data-original-width="1024" data-original-height="512" alt="Android graphic"></a> </p><h1>Getting on the same page with Paging 3</h1> <p> The Paging library enables you to load large sets of data gradually and gracefully, reducing network usage and system resources. You told us that the Paging 2.0 API was not enough - that you wanted easier error handling, more flexibility to implement list transformations like <code>map</code> or <code>filter</code>, and support for list separators, headers, and footers. So we launched Paging 3.0 (now in alpha02), a complete rewrite of the library using Kotlin coroutines (still supporting Java users) and offering the features you asked for. </p> <h2>Paging 3 highlights</h2> <p> The Paging 3 API provides support for common functionality that you would otherwise need to implement yourself when loading data in pages: </p> <ul><li>Keeps track of the keys to be used for retrieving the next and previous page. </li><li>Automatically requests the correct next page when the user scrolls to the end of the loaded data. </li><li>Ensures that multiple requests aren’t triggered at the same time. </li><li>Tracks loading state and allows you to display it in a <code>RecyclerView</code> list item or elsewhere in your UI, and provides easy retry functionality for failed loads. </li><li>Enables common operations like <code>map</code> or <code>filter</code> on the list to be displayed, independently of whether you’re using <code>Flow</code>, <code>LiveData</code>, or RxJava <code>Flowable</code> or <code>Observable</code>. </li><li>Provides an easy way of implementing list separators. </li><li>Simplifies data caching, ensuring that you’re not executing data transformations at every configuration change. </li> </ul><p> We also made several Paging 3 components backwards compatible with Paging 2.0; so if you already use Paging in your app, you can <a href="https://developer.android.com/topic/libraries/architecture/paging/v3-migration">migrate</a> incrementally. </p> <h2>Adopting Paging 3 in your app</h2> <p> Let’s say that we’re implementing an app that displays all the good doggos. We get the doggos from a <code>GoodDoggos</code> API that supports index-based pagination. Let’s go over the Paging components we need to implement and how they fit into your app architecture. The following examples will be in Kotlin, using coroutines. For examples in the Java programming language using LiveData/RxJava, check out the <a href="https://developer.android.com/topic/libraries/architecture/paging/v3-overview">documentation</a>. </p> <p> The Paging library integrates directly into the recommended Android app architecture in each layer of your app: </p> <a href="https://3.bp.blogspot.com/-WDij3mAUZEo/XxXYliprwbI/AAAAAAAAPRY/EaHnaoH0S60ydry-Q7ZPpw1L5FuPG_cnACLcBGAsYHQ/s1600/Screenshot%2B2020-07-01%2Bat%2B13.41.47.png"><img border="0" src="https://3.bp.blogspot.com/-WDij3mAUZEo/XxXYliprwbI/AAAAAAAAPRY/EaHnaoH0S60ydry-Q7ZPpw1L5FuPG_cnACLcBGAsYHQ/s1600/Screenshot%2B2020-07-01%2Bat%2B13.41.47.png" data-original-width="1600" data-original-height="446" alt="Paging components"></a> <p> Paging components and their integration in the app architecture" </p>id="imgCaption"> <h3>Defining the data source</h3> <p> Depending on where you’re loading data from, implement only a <code><a href="https://developer.android.com/reference/kotlin/androidx/paging/PagingSource">PagingSource</a></code> or a <code>PagingSource</code> and a <code><a href="https://developer.android.com/reference/kotlin/androidx/paging/RemoteMediator">RemoteMediator</a></code>: </p><ul><li>If you’re loading data from a <strong>single source</strong>, like network, local database, a file, etc, implement the <code>PagingSource</code> (if you’re using Room, it <a href="https://developer.android.com/training/data-storage/room/accessing-data#paging-integration">implements</a> the <code>PagingSource</code> for you starting in Room 2.3.0-alpha). </li><li>If you’re loading data from a <strong>layered source</strong>, like a network data source with a local database cache, implement the <code>RemoteMediator</code> to merge the two sources and a <code>PagingSource</code> for the local database cache. </li> </ul><h3>PagingSource</h3> <p> A <code><a href="https://developer.android.com/reference/kotlin/androidx/paging/PagingSource">PagingSource</a></code> defines the source of paging data and how to retrieve data from that single source. The <code>PagingSource</code> should be part of the repository layer. Implement <code><a href="https://developer.android.com/reference/kotlin/androidx/paging/PagingSource#load">load()</a></code> to retrieve paged data from your data source and return the loaded data together with information about next and previous keys. This is a <code>suspend</code> function, so you can call other <code>suspend</code> functions here, such as the network call: </p><pre>class DoggosRemotePagingSource(     val backend: GoodDoggosService ) : PagingSource<Int, Dog>() {   override suspend fun load(     params: LoadParams<Int>   ): LoadResult<Int, Dog> {     try {       // Load page 1 if undefined.       val nextPageNumber = params.key ?: 1       val response = backend.getDoggos(nextPageNumber)       return LoadResult.Page(         data = response.doggos,         prevKey = null, // Only paging forward.         nextKey = response.nextPageNumber + 1       )     } catch (e: Exception) {       // Handle errors in this block         return LoadResult.Error(exception)     }   } }</pre> <h3>PagingData and Pager</h3> <p> The container for paginated data is called <code><a href="https://developer.android.com/reference/kotlin/androidx/paging/PagingData">PagingData</a></code>. A new instance of <code>PagingData</code> is created every time your data is refreshed. To build a stream of <code>PagingData</code> create a <code><a href="https://developer.android.com/reference/kotlin/androidx/paging/Pager">Pager</a></code> instance, using a <code><a href="https://developer.android.com/reference/kotlin/androidx/paging/PagingConfig">PagingConfig</a></code> configuration object and a function that tells the <code>Pager</code> how to get an instance of your <code>PagingSource</code> implementation. </p><p> In your <code>ViewModel</code> you construct the <code>Pager</code> object and expose a <code>Flow<PagingData></code> to the UI. <code>Flow<PagingData></code> has a handy <code><a href="https://developer.android.com/reference/kotlin/androidx/paging/package-summary#cachedin">cachedIn()</a></code> method that makes the data stream shareable and allows you to cache the content of a <code>Flow<PagingData></code> in a <code>CoroutineScope</code>. That way if you implement any transformations on the data stream, they will not be triggered again each time you <code>collect</code> the <code>flow</code> after <code>Activity</code> recreation. The caching should be done as close to the UI layer as possible, but not in the UI layer, as we want to make sure it persists beyond configuration change. The best place for this would be in a <code>ViewModel</code>, using the <code><a href="https://developer.android.com/reference/kotlin/androidx/lifecycle/package-summary#viewmodelscope">viewModelScope</a></code>: </p><pre>val doggosPagingFlow = Pager(PagingConfig(pageSize = 10)) { DogRemotePagingSource(goodDoggosService) }.flow.cachedIn(viewModelScope)</pre> <h3>PagingDataAdapter</h3> <p> To connect a <code>RecyclerView</code> to the <code>PagingData</code>, implement a <code><a href="https://developer.android.com/reference/kotlin/androidx/paging/PagingDataAdapter">PagingDataAdapter</a></code>: </p><pre>class DogAdapter(diffCallback: DiffUtil.ItemCallback<Dog>) : PagingDataAdapter<Dog, DogViewHolder>(diffCallback) { override fun onCreateViewHolder( parent: ViewGroup, viewType: Int ): DogViewHolder { return DogViewHolder(parent) } override fun onBindViewHolder(holder: DogViewHolder, position: Int) { val item = getItem(position) if(item == null) { holder.bindPlaceholder() } else { holder.bind(item) } } }</pre> <p> Then, in your <code>Activity</code>/<code>Fragment</code> you’ll have to collect the <code>Flow<PagingData></code> and submit it to the <code>PagingDataAdapter</code>. This is what the implementation would look like in an <code>Activity onCreate()</code>: </p> <pre>val viewModel by viewModels<DoggosViewModel>() val pagingAdapter = DogAdapter(DogComparator) val recyclerView = findViewById<RecyclerView>(R.id.recycler_view) recyclerView.adapter = pagingAdapter lifecycleScope.launch { viewModel.doggosPagingFlow.collectLatest { pagingData -> pagingAdapter.submitData(pagingData) } }</pre> <h2>Paged data transformations</h2> <a href="https://2.bp.blogspot.com/-97PVeeAEpNk/XxXah7PeWZI/AAAAAAAAPRs/TaNPCBrtBMkzlbxBJkdv6dJEsbCuwSQ5ACLcBGAsYHQ/s1600/Screenshot%2B2020-07-19%2Bat%2B12.31.10.png"><img border="0" src="https://2.bp.blogspot.com/-97PVeeAEpNk/XxXah7PeWZI/AAAAAAAAPRs/TaNPCBrtBMkzlbxBJkdv6dJEsbCuwSQ5ACLcBGAsYHQ/s1600/Screenshot%2B2020-07-19%2Bat%2B12.31.10.png" data-original-width="668" data-original-height="1314" alt="A filtered list"></a> <p> Displaying a filtered list </p>id="imgCaption"> <p> Transforming <code>PagingData</code> streams is very similar to the way you would any other data stream. For example, if we only want to display playful doggos from our <code>Flow<PagingData<Dog>></code> we would need to map the <code>Flow</code> object and then <code>filter</code> the <code>PagingData</code>: </p> <pre>doggosPagingFlow.map { pagingData -> pagingData.filter { dog -> dog.isPlayful } }</pre> <a href="https://1.bp.blogspot.com/-BhEPdp1l9P8/XxXbF-Z0F0I/AAAAAAAAPR4/KyDkrVZTmuMFMfRqhIuYf9ifj7x87KE9QCLcBGAsYHQ/s1600/Screenshot%2B2020-07-19%2Bat%2B12.23.26.png"><img border="0" src="https://1.bp.blogspot.com/-BhEPdp1l9P8/XxXbF-Z0F0I/AAAAAAAAPR4/KyDkrVZTmuMFMfRqhIuYf9ifj7x87KE9QCLcBGAsYHQ/s1600/Screenshot%2B2020-07-19%2Bat%2B12.23.26.png" data-original-width="668" data-original-height="1318" alt="list with separators"></a> <p> List with separators </p>id="imgCaption"> <p> Adding <strong>list separators</strong> is also a paged data transformation where we transform the <code>PagingData</code> to insert separator objects into the list. For example, we can insert letter separators for our doggos’ names. When using separators, you will need to implement your own UI model class that supports the new separator items. To modify your <code>PagingData</code> to add separators, you will use the <code><a href="https://developer.android.com/reference/kotlin/androidx/paging/PagingData#insertseparators">insertSeparators</a></code> transformation: </p><pre>pager.flow.map { pagingData: PagingData<Dog> -> pagingData.map { doggo -> // Convert items in stream to UiModel.DogModel. UiModel.DogModel(doggo) } .insertSeparators<UiModel.DogModel, UiModel> { before: Dog, after: Dog -> return if(after == null) { // we're at the end of the list null } else if (before == null || before.breed != after.breed) { // breed above and below different, show separator UiModel.SeparatorItem(after.breed) } else { // no separator null } } } }.cachedIn(viewModelScope)</pre> <p> Just as before, we're using <code>cachedIn</code> right before the UI layer. This ensures that loaded data and the results of any transformations can be cached and reused after a configuration change. </p> <h3>Advanced Paging work with RemoteMediator</h3> <p> If you’re paging data from a <strong>layered source</strong>, you should implement a <code><a href="https://developer.android.com/reference/kotlin/androidx/paging/RemoteMediator">RemoteMediator</a></code>. For example, in the implementation of this class you need to request data from the network and save it in the database. The <code><a href="https://developer.android.com/reference/kotlin/androidx/paging/RemoteMediator#load">load()</a></code> method will be triggered whenever there is no more data in the database to be displayed. Based on the <code><a href="https://developer.android.com/reference/kotlin/androidx/paging/PagingState">PagingState</a></code> and the <code><a href="https://developer.android.com/reference/kotlin/androidx/paging/LoadType">LoadType</a></code> we can construct the next page request. </p><p> It’s your responsibility to define how the previous and next remote page keys are constructed and retained as the Paging library doesn’t know what your API looks like. For example, you can associate remote keys to every item you receive from the network and save them in the database. </p> <pre>override suspend fun load(loadType: LoadType, state: PagingState<Int, Dog>): MediatorResult { val page = ... // computed based on loadType and state try { val doggos = backend.getDoggos(page) doggosDatabase.doggosDao().insertAll(doggos) val endOfPaginationReached = emails.isEmpty() return MediatorResult.Success(endOfPaginationReached = endOfPaginationReached) } catch (exception: Exception) { return MediatorResult.Error(exception) } }</pre> <p> When you’re loading data from the network and saving it to the database, the database is the source of truth for the data displayed on the screen. This means that the UI will be displaying data from your database, so you’ll have to implement a <code>PagingSource</code> for your database. If you’re using Room, you’ll just need to add a new query in your DAO that returns a <code>PagingSource</code>: </p> <pre>@Query("SELECT * FROM doggos") fun getDoggos(): PagingSource<Int, Dog></pre> <p> The <code>Pager</code> implementation changes slightly in this case, as you need to pass the <code>RemoteMediator</code> instance as well: </p> <pre>val pagingSourceFactory = { database.doggosDao().getDoggos() } return Pager( config = PagingConfig(pageSize = NETWORK_PAGE_SIZE), remoteMediator = DoggosRemoteMediator(service, database), pagingSourceFactory = pagingSourceFactory ).flow</pre> <p> Check out the <a href="https://developer.android.com/topic/libraries/architecture/paging/v3-network-db">docs</a> to find out more about working with RemoteMediator. For a complete implementation of <code>RemoteMediator</code> in an app, check out step 15 of the <a href="https://codelabs.developers.google.com/codelabs/android-paging/#14">Paging codelab</a> and the <a href="https://github.com/googlecodelabs/android-paging/blob/step13-19_network_and_database/app/src/main/java/com/example/android/codelabs/paging/data/GithubRemoteMediator.kt">accompanying code</a>. </p> <br><p> We’ve designed the Paging 3 library to help you accommodate both simple and complex uses of Paging. It makes it easier to work with large sets of data whether it’s being loaded from the network, a database, in-memory cache, or some combination of these sources. The library is built on coroutines and <code>Flow</code>, making it easy to call suspend functions and work with streams of data. </p> <p> As Paging 3 is still in alpha, we need your help to make it better! To get started, find out more about Paging in our <a href="https://developer.android.com/topic/libraries/architecture/paging/v3-overview">documentation</a> and try it out by taking our <a href="https://codelabs.developers.google.com/codelabs/android-paging/">codelab</a> or checking out the <a href="https://github.com/android/architecture-components-samples/tree/master/PagingWithNetworkSample">sample</a>. Then, let us know how we can improve the library by creating issues on the <a href="https://issuetracker.google.com/issues?q=componentid:413106%20status:openhttps://issuetracker.google.com/issues?q=componentid:413106%20status:open">Issue Tracker</a>. </p><div> <a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=BK5IcZZce8c:EGCBoyG6j5g:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?d=yIl2AUoC8zA" border="0"></a> <a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=BK5IcZZce8c:EGCBoyG6j5g:-BTjWOF_DHI"><img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?i=BK5IcZZce8c:EGCBoyG6j5g:-BTjWOF_DHI" border="0"></a> </div><img src="http://feeds.feedburner.com/~r/blogspot/hsDu/~4/BK5IcZZce8c" height="1" width="1" alt="">

11 Weeks of Android: Languages

Posted by David Winer, Product Manager This blog post is part of a weekly series for #11WeeksOfAndroid. Each week we’re diving into a key area of Android so you don’t miss anything. This week, we spotlighted languages; here’s a look at what you ...

Google Home reduces #1 cause of crashes by 33%

The Google Home app helps set up, manage, and control your Google Home, Google Nest, and Chromecast devices—plus thousands of connected home products like lights, cameras, thermostats, and more. The engineering team behind the Google Home app ben...

Learn Android and Kotlin with no programming experience

<img src="https://4.bp.blogspot.com/-2xdRboZXPwo/Xw-uR2xUiWI/AAAAAAAAPQM/noNfBUf3VQQeNwgkJoBpstxBn8cQg_Z2QCLcBGAsYHQ/s1600/Screen%2BShot%2B2020-07-15%2Bat%2B5.29.55%2BPM.png"><p><em>Posted by <a href="https://twitter.com/katherine_kuan">Kat Kuan</a>, Developer Advocate, Android </em></p><p> </p><p> Many people today are considering career paths that enable them to work remotely. App development allows for that style of work. For people who want a new opportunity, it’s possible to start learning Android today, even without prior programming experience. </p> <p> In 2016, we released our <a href="https://android-developers.googleblog.com/2016/06/introducing-android-basics-nanodegree.html">Android Basics curriculum</a>, which assumes no programming experience, and the response has been tremendous. Hundreds of thousands of students have been learning Android development and programming concepts simultaneously as they build apps. Since then, there have been big platform changes with four major releases of Android and support added for the Kotlin programming language. We also introduced Jetpack, a suite of libraries that make it easier to build better apps with less code. With all these new updates, it’s time to release the next generation of training content for beginners. </p> <p> Today we’re announcing the launch of <a href="http://g.co/android/basics">Android Basics in Kotlin</a>, a new online course for people without programming experience to learn how to build Android apps. The course teaches Kotlin, a modern programming language that developers love because of its conciseness and how it increases productivity. Kotlin is quickly gaining momentum in industry. Over a single year from 2018 - 2019, <a href="https://www.hiringlab.org/2019/11/26/fastest-rising-tech-skills/">Indeed Hiring Lab</a> found a 76% increase in Kotlin jobs.* </p> <p> Google announced that Android development is Kotlin-first, and 60% of professional Android developers have already adopted the language. In the Play Store, 70% of the top 1,000 apps use Kotlin. To keep pace and prepare for the future, there has never been a more opportune time to learn Android with Kotlin. </p> <p> Learning to code for the first time can feel intimidating, but it is possible to learn without a technical background. From a recent <a href="https://insights.stackoverflow.com/survey/2020#developer-profile-undergraduate-major-professional-developers2">Stack Overflow Developer Survey</a>, nearly 40% of the professional developers who studied at university did not receive a formal computer science or software engineering degree. </p> <p> To build your confidence, the <a href="http://g.co/android/basics">Android Basics in Kotlin</a> course offers step-by-step instructions on how to use Android Studio to build apps, as well as how to run them on an Android device (or virtual device). The goal is to expose you to the tools and resources that professional Android developers use. With hands-on practice, you learn the fundamentals of programming. By the end of the course, you will have completed a collection of Android apps to start building a portfolio. </p><div> <a href="https://1.bp.blogspot.com/-i8np-BrbX3A/Xw9zh1xDXMI/AAAAAAAAPPU/tjMtRPmYyVwCtxYyASUulsGICoJuzpKuQCLcBGAsYHQ/s1600/BirthdayCardApp_framed.png"><img border="0" src="https://1.bp.blogspot.com/-i8np-BrbX3A/Xw9zh1xDXMI/AAAAAAAAPPU/tjMtRPmYyVwCtxYyASUulsGICoJuzpKuQCLcBGAsYHQ/s1600/BirthdayCardApp_framed.png" data-original-width="360" data-original-height="720" alt="Object detection & tracking gif"></a> <a href="https://3.bp.blogspot.com/-4ya4NMqA6GU/Xw90F5KcyWI/AAAAAAAAPPc/G5C37EIWU6I8PsPA2WT1_fo3PNTy7ZNSQCLcBGAsYHQ/s1600/DiceRollerApp_framed.png"><img border="0" src="https://3.bp.blogspot.com/-4ya4NMqA6GU/Xw90F5KcyWI/AAAAAAAAPPc/G5C37EIWU6I8PsPA2WT1_fo3PNTy7ZNSQCLcBGAsYHQ/s1600/DiceRollerApp_framed.png" data-original-height="720" alt="Text recognition + Language ID + Translate gif"></a> </div> <p> App screenshots from the course </p>id="imgCaption"> This course is split up into units, where each unit is made up of a series of pathways. At the end of each pathway, there is a quiz to assess what you’ve learned so far. If you pass the quiz, you earn a badge that can be saved to your <a href="https://google.dev/help">Google Developer Profile</a>. <div> <a href="https://3.bp.blogspot.com/-L6PH6lZ9IC8/Xw92SPtMJTI/AAAAAAAAPPs/KhcFNLEYBPIAQf52UD5M6B5MAQzzP_IfQCLcBGAsYHQ/s1600/GDev-Badge-Birthday-Card-App%25402x%2B%25281%2529.png"><img border="0" src="https://3.bp.blogspot.com/-L6PH6lZ9IC8/Xw92SPtMJTI/AAAAAAAAPPs/KhcFNLEYBPIAQf52UD5M6B5MAQzzP_IfQCLcBGAsYHQ/s1600/GDev-Badge-Birthday-Card-App%25402x%2B%25281%2529.png" data-original-width="360" data-original-height="720" alt="Object detection & tracking gif"></a> <a href="https://1.bp.blogspot.com/-EDmBvK7Qico/Xw93LA6NWyI/AAAAAAAAPQA/in9wGV1MqpI4S6JcSmha-8UO_ZRTwIxSQCLcBGAsYHQ/s1600/GDev-Badge-Adventures-in-Kotlin%25402x%2B%25281%2529.png"><img border="0" src="https://1.bp.blogspot.com/-EDmBvK7Qico/Xw93LA6NWyI/AAAAAAAAPQA/in9wGV1MqpI4S6JcSmha-8UO_ZRTwIxSQCLcBGAsYHQ/s1600/GDev-Badge-Adventures-in-Kotlin%25402x%2B%25281%2529.png" data-original-height="720" alt="Text recognition + Language ID + Translate gif"></a> </div> <p> Badges you can earn </p>id="imgCaption"> <p> The course is free for anyone to take. Basic computer literacy and basic math skills are recommended prerequisites. Unit 1 of the course is available today, with more units being released as they become available. If you’ve never built an app before but want to learn how, check out the <a href="http://g.co/android/basics">Android Basics in Kotlin</a> course. </p> <p> If you already have programming experience, check out the other free training courses we offer in Kotlin: </p> <ul><li><a href="https://developer.android.com/courses/kotlin-bootcamp/overview">Kotlin Bootcamp for Programmers</a> </li><li><a href="https://developer.android.com/courses/kotlin-android-fundamentals/overview">Android Kotlin Fundamentals</a> </li><li><a href="https://developer.android.com/courses/kotlin-android-advanced/overview">Advanced Android in Kotlin</a> </li> </ul><p> We can’t wait to see what you build! </p> <p> <em> <small> *from US tech job postings on Indeed.com</small> </em> </p><div> <a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=pFFLyW6Oz5c:HKBcteu8yMY:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?d=yIl2AUoC8zA" border="0"></a> <a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=pFFLyW6Oz5c:HKBcteu8yMY:-BTjWOF_DHI"><img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?i=pFFLyW6Oz5c:HKBcteu8yMY:-BTjWOF_DHI" border="0"></a> </div><img src="http://feeds.feedburner.com/~r/blogspot/hsDu/~4/pFFLyW6Oz5c" height="1" width="1" alt="">

11 Weeks of Android: Android 11 Compatibility

Posted by Dirk Dougherty, Android Developer Relations This post is part of a weekly series for 11 Weeks of Android. This week, we spotlighted Android 11 Compatibility; here’s a look at what you should know. The big news With Beta 2 now i...

Accelerating Android Updates

Posted by Eddie Hsu (Technical Program Manager), Brent VerWeyst (Product Manager), Maya Ben Ari (Product Manager), Amith Dsouza (Technical Account Manager), Iliyan Malchev (Project Treble Architect) Over the past few years we’ve introduced new capa...

Android 11 Beta 2 and Platform Stability

Posted by Dave Burke, VP of Engineering A few weeks ago we unwrapped the first Beta of Android 11 with a focus on people, controls, and privacy. As we highlighted in the #Android11Beta Launch, we’re making Android more people-centric and expressiv...

Testing app compatibility in Android 11

Posted by Diana Wong, Product Manager, Android This blog post is part of a weekly series for #11WeeksOfAndroid. For each #11WeeksOfAndroid, we’re diving into a key area so you don’t miss anything. This week, we’re spotlighting Android 11 compatibi...

Bringing modern storage to Viber’s users

This blogpost is a collaboration between Google and Viber. Authored by Kseniia Shumelchyk from Google and Anton Novikov, Sergey Kozlov from Viber. As a messaging app, Viber needs to store, process and share a significant amount of data. Viber ai...

System hardening in Android 11

Posted by Platform Hardening Team In Android 11 we continue to increase the security of the Android platform. We have moved to safer default settings, migrated to a hardened memory allocator, and expanded the use of compiler mitigations that defe...

11 Weeks of Android: Privacy and Security

Posted by:Charmaine D’Silva, Product Lead, Android Privacy and FrameworkNarayan Kamath, Engineering Lead, Android Privacy and FrameworkStephan Somogyi, Product Lead, Android SecuritySudhi Herle, Engineering Lead, Android Security This blog post i...

Android 11 Developer Preview on Android TV

Posted by Xiaodao Wu, Developer Advocate With the rise in quality content that’s keeping us glued to the big screen, it’s no surprise watch time on the TV continues to grow. As users spend more time in their living rooms, they are also looking to...

New features to acquire and retain subscribers

Posted by Angela Ying, Product Manager, Google Play Subscription continues to be one of the fastest growing business models for apps in Google Play. As your subscription business evolves and becomes more sophisticated, our platform continues to evo...

11 Weeks of Android: People & Identity

Posted by Dr. Stefan Frank, Senior Product Manager, Android System UI This blog post is part of a weekly series for #11WeeksOfAndroid. Each week we’re diving into a key area of Android so you don’t miss anything. This week, we spotlight people ...

Messenger and Conversations

This blogpost is a collaboration between Google and Messenger from Facebook. Authored by Aaron Labiaga with support from Caleb Gomer and Samuel Guirado from Messenger. Messenger is ubiquitous in the messaging app world and has pioneered the...