<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Ash Nohe on Medium]]></title>
        <description><![CDATA[Stories by Ash Nohe on Medium]]></description>
        <link>https://medium.com/@ashley.nohe?source=rss-54b43884b5c2------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*0dQdET0RLC8J6ZRVvRTr4Q.jpeg</url>
            <title>Stories by Ash Nohe on Medium</title>
            <link>https://medium.com/@ashley.nohe?source=rss-54b43884b5c2------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 15 Nov 2026 00:47:15 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@ashley.nohe/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Make WebViews edge-to-edge]]></title>
            <link>https://medium.com/androiddevelopers/make-webviews-edge-to-edge-a6ef319adfac?source=rss-54b43884b5c2------2</link>
            <guid isPermaLink="false">https://medium.com/p/a6ef319adfac</guid>
            <category><![CDATA[android-app-development]]></category>
            <category><![CDATA[edge-to-edge]]></category>
            <category><![CDATA[webview]]></category>
            <category><![CDATA[android-16]]></category>
            <category><![CDATA[android-15]]></category>
            <dc:creator><![CDATA[Ash Nohe]]></dc:creator>
            <pubDate>Tue, 25 Mar 2025 19:43:00 GMT</pubDate>
            <atom:updated>2025-03-25T19:43:00.543Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vYYSHqniJAFO-mOIG45wYg.png" /></figure><p>Ensure your WebViews are compatible with Android 16, as <a href="https://developer.android.com/about/versions/16/behavior-changes-16#edge-to-edge">Android 16 removes the ability to opt-out of drawing your app edge-to-edge</a>. The way you handle insets for WebViews depends on whether or not your app owns the web content.</p><p>This post assumes basic knowledge of handling insets and is applicable if your WebViews are drawing underneath system bars or display cutouts. See the <a href="https://developer.android.com/develop/ui/compose/layouts/insets">Compose</a> and <a href="https://developer.android.com/develop/ui/views/layout/edge-to-edge">Views</a> documentation, and the <a href="https://medium.com/androiddevelopers/insets-handling-tips-for-android-15s-edge-to-edge-enforcement-872774e8839b">Inset handling tips</a> blog for guidance on handling insets.</p><p>If you’re looking for guidance on how to make your webpage edge-to-edge on Chrome, see the <a href="https://developer.chrome.com/docs/css-ui/edge-to-edge">Chrome on Android edge-to-edge migration guide</a> instead.</p><p>This post covers the following topics:</p><ul><li>How to handle WebViews if your app doesn’t own the web content</li><li>How to handle WebViews if your app owns the web content</li><li>Handling IME insets in WebViews</li></ul><h3>If your app doesn’t own the web content</h3><p>WebViews displaying external content cannot easily draw edge-to-edge and should instead be inset to avoid the system bars and display cutout. The implementation is different depending on if you’re using Compose or Views, but generally follows these steps:</p><ol><li>Wrap the WebView in a container and apply insets as padding on that container.</li><li>Set the app’s background color in a best-effort attempt to match the webpage.</li></ol><figure><img alt="Three app screenshots showing WebView layout issues and fixes." src="https://cdn-images-1.medium.com/max/960/0*9kQWMYl0gSFBKbuo" /><figcaption><strong>Figure 1.</strong> Left to right. (a) The left image shows a full screen WebView in an app targeting SDK 35, at which point edge-to-edge is enforced. The top of the WebView collides with status bar icons. (b) The middle image shows the result of padding the WebView’s parent. The app’s background is set to red to make it apparent that the WebView is inset. (c) The right image is the desired result. The app’s background is set to white in a best-effort attempt to match the webpage.</figcaption></figure><p>See the following code samples.</p><h4>Apply insets to a WebView in a Compose app</h4><p>To ensure a WebView in Compose avoids overlapping with system bars, display cutout and keyboard, apply Modifier.windowInsetsPadding(WindowInsets.safeDrawing) to its wrapper (e.g. AndroidView). This provides the necessary padding to keep the WebView content within the safe area of the screen.</p><pre>@Composable<br>fun WebViewInCompose() {<br>    AndroidView(<br>        modifier = Modifier.windowInsetsPadding(WindowInsets.safeDrawing),<br>        factory = { context -&gt;<br>            WebView(context).apply {<br>                // Configure WebView options here<br>            }<br>        }<br>    )<br>}</pre><p>Then, update your app’s background so it matches the WebView’s background as much as possible.</p><h4>Apply insets to a WebView in a Views app</h4><p>To ensure a WebView in Views avoids overlapping the system bars, display cutout and keyboard, wrap the WebView in a container like a FrameLayout and do one of the following:</p><ul><li>Set android:fitsSystemWindows=&quot;true&quot;</li><li>Use ViewCompat.setOnApplyWindowInsetsListener() and apply <a href="https://developer.android.com/reference/kotlin/androidx/core/view/WindowInsetsCompat.Type#systemBars()">systemBars</a>, <a href="https://developer.android.com/reference/kotlin/androidx/core/view/WindowInsetsCompat.Type#displayCutout()">displayCutout</a>, and <a href="https://developer.android.com/reference/kotlin/androidx/core/view/WindowInsetsCompat.Type#ime()">ime</a> insets on the container. See the <a href="https://developer.android.com/develop/ui/views/layout/edge-to-edge">Views</a> documentation for a code sample using the listener.</li></ul><p>Finally, update android:windowBackground in your themes.xml so it matches the WebView’s background if possible.</p><h3>If your app owns the web content</h3><p>If your app owns the web content, either pad the WebView’s parent as described above; or, use JavaScript to inject padding into the web page to draw the page edge-to-edge as described below.</p><p>To inject padding into the web page, first add &lt;meta name=”viewport” content=”viewport-fit=cover”&gt; to your HTML.</p><pre>&lt;meta name=&quot;viewport&quot; content=&quot;viewport-fit=cover, initial-scale=1&quot; /&gt;</pre><p>Second, define CSS variables for top, right, bottom and left safe area insets, as the env(safe-area-inset-*) <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/env">variables</a> return 0px on Android at the time of writing this blog.</p><pre>/* CSS */<br>body {<br>  padding-top: var(--safe-area-inset-top);<br>  padding-right: var(--safe-area-inset-right);<br>  padding-bottom: var(--safe-area-inset-bottom);<br>  padding-left: var(--safe-area-inset-left);<br>}</pre><p>Instead of applying insets on the WebView’s container, use JavaScript to pass the insets to your CSS variables to pad the webpage. The implementation is different depending on if you’re using Compose or Views, but it generally follows these steps:</p><ol><li>Retrieve the top, right, bottom and left system bar, display cutout and IME insets as raw pixel values.</li><li>Convert the raw pixel values to density independent pixels.</li><li>Inject the density independent pixels into the CSS variables as CSS pixels. When the website renders on the Android device, the WebView converts the CSS pixels back to density independent pixels. See <a href="https://developer.android.com/develop/ui/views/layout/webapps/targeting">Support different screens in web apps</a> for more information.</li><li>In Compose, recompose when the software keyboard expands or collapses if applicable.</li><li>In Views, dispatch insets when the webpage first loads.</li></ol><figure><img alt="Two app screenshots. Top: WebView overlapping system bars and cutout. Bottom: WebView correctly padded using JavaScript." src="https://cdn-images-1.medium.com/max/1024/0*-ntY5AusKSyICBQL" /><figcaption><strong>Figure 2.</strong> Top to bottom. (a) The top image shows a full screen WebView in an app targeting SDK 35, at which point edge-to-edge is enforced. The WebView collides with system bars and display cutout. (b) The bottom image shows the result of using JavaScript to inject padding into the webpage, which is the edge-to-edge result we want.</figcaption></figure><p>See the following code samples.</p><h4>Using Compose and JavaScript to inject insets into web pages</h4><p>A code sample showing how to use JavaScript to inject insets into webpages in a Compose app.</p><pre>import android.webkit.WebView<br>import android.webkit.WebViewClient<br>import androidx.compose.foundation.layout.WindowInsets<br>import androidx.compose.foundation.layout.ime<br>import androidx.compose.foundation.layout.safeDrawing<br>import androidx.compose.ui.unit.Dp<br>...<br><br>@Composable<br>fun MainScreen() {<br>    Box(modifier = Modifier.fillMaxSize()) {<br>        <br>        // Retrieve insets as raw pixels<br>        val insets = WindowInsets.safeDrawing<br>        WebViewInCompose(<br>            initialUrl = &quot;file:///android_asset/example.html&quot;,<br>            insets = insets<br>        )<br>    }<br>}<br><br>@SuppressLint(&quot;SetJavaScriptEnabled&quot;)<br>@Composable<br>fun WebViewInCompose(<br>    initialUrl: String,<br>    insets: WindowInsets,<br>    density: Density = LocalDensity.current,<br>    layoutDirection: LayoutDirection = LocalLayoutDirection.current,<br>    myWebViewClient: CustomWebViewClient = remember { CustomWebViewClient(<br>        insets, density, layoutDirection<br>    ) }<br>) {<br>    <br>    // Don&#39;t apply insets to the container <br>    AndroidView(<br>        factory = { context -&gt;<br>            WebView(context).apply {<br>                webViewClient = myWebViewClient<br>                settings.javaScriptEnabled = true<br>                loadUrl(initialUrl)<br>            }<br>        }, update = { view -&gt;<br>            <br>            // Updates webpage when software keyboard expands or collapses.<br>            // If your webpage doesn&#39;t have an input field that opens the <br>            // software keyboard, remove this line.<br>            applySafeAreaInsetsToWebView(insets, density, layoutDirection, view)<br>        }<br>    )<br>}<br><br>class CustomWebViewClient(<br>    private val insets: WindowInsets,<br>    private val density: Density,<br>    private val layoutDirection: LayoutDirection<br>) : WebViewClient(){<br><br>    override fun onPageFinished(view: WebView?, url: String?) {<br>        super.onPageFinished(view, url)<br>        <br>        // Inject insets into the webpage once the page has fully loaded<br>        applySafeAreaInsetsToWebView(insets, density, layoutDirection, view)<br>    }<br>}<br><br>private fun applySafeAreaInsetsToWebView(<br>    insets: WindowInsets,<br>    density: Density,<br>    layoutDirection: LayoutDirection,<br>    webView: WebView?){<br><br>    // Convert raw pixels to density independent pixels<br>    val top = insets.getTop(density).toDp(density).value<br>    val right = insets.getRight(density, layoutDirection).toDp(density).value<br>    val bottom = insets.getBottom(density).toDp(density).value<br>    val left = insets.getLeft(density, layoutDirection).toDp(density).value<br><br>    val safeAreaJs = &quot;&quot;&quot;<br>            document.documentElement.style.setProperty(&#39;--safe-area-inset-top&#39;, &#39;${top}px&#39;);<br>            document.documentElement.style.setProperty(&#39;--safe-area-inset-right&#39;, &#39;${right}px&#39;);<br>            document.documentElement.style.setProperty(&#39;--safe-area-inset-bottom&#39;, &#39;${bottom}px&#39;);<br>            document.documentElement.style.setProperty(&#39;--safe-area-inset-left&#39;, &#39;${left}px&#39;);<br>            &quot;&quot;&quot;<br><br>    // Inject the density independent pixels into the CSS variables as CSS pixels<br>    webView?.evaluateJavascript(safeAreaJs, null)<br>}<br><br>private fun Int.toDp(density: Density): Dp = with(density) { this@toDp.toDp() }</pre><h4>Using Views and JavaScript to inject insets into web pages</h4><p>A code sample showing how to use JavaScript to inject insets into webpages in a Views app.</p><pre>import androidx.core.util.TypedValueCompat.pxToDp<br>import <br>androidx.core.view.WindowInsetsCompat.Type.displayCutout<br>import androidx.core.view.WindowInsetsCompat.Type.ime<br>import androidx.core.view.WindowInsetsCompat.Type.systemBars<br>...<br><br>override fun onCreate(savedInstanceState: Bundle?) {<br>    ...<br><br>    val myWebView: WebView = findViewById(R.id.webView)<br>    myWebView.settings.javaScriptEnabled = true<br>    myWebView.loadUrl(&quot;file:///android_asset/example.html&quot;)<br><br>    ViewCompat.setOnApplyWindowInsetsListener(myWebView) { _, windowInsets -&gt;<br>        <br>        // Retrieve insets as raw pixels<br>        val safeDrawingInsets = windowInsets.getInsets(<br>            systemBars() or displayCutout() or ime()<br>        )<br>        val displayMetrics = myWebView.context.resources.displayMetrics<br><br>        // Convert raw pixels to density independent pixels <br>        val top = pxToDp(safeDrawingInsets.top.toFloat(), displayMetrics)<br>        val right = pxToDp(safeDrawingInsets.right.toFloat(), displayMetrics)<br>        val bottom = pxToDp(safeDrawingInsets.bottom.toFloat(), displayMetrics)<br>        val left = pxToDp(safeDrawingInsets.left.toFloat(), displayMetrics)<br><br>        val safeAreaJs = &quot;&quot;&quot;<br>            document.documentElement.style.setProperty(&#39;--safe-area-inset-top&#39;, &#39;${top}px&#39;);<br>            document.documentElement.style.setProperty(&#39;--safe-area-inset-right&#39;, &#39;${right}px&#39;);<br>            document.documentElement.style.setProperty(&#39;--safe-area-inset-bottom&#39;, &#39;${bottom}px&#39;);<br>            document.documentElement.style.setProperty(&#39;--safe-area-inset-left&#39;, &#39;${left}px&#39;);<br>            &quot;&quot;&quot;<br><br>        // Inject the density independent pixels into the CSS variables as CSS pixels<br>        myWebView.evaluateJavascript(safeAreaJs, null)<br><br>        windowInsets<br>    }<br><br>    myWebView.webViewClient = object : WebViewClient() {<br>        override fun onPageFinished(view: WebView, url: String) {<br>            super.onPageFinished(myWebView, url)<br>            // dispatch insets because insets aren&#39;t applied when the webpage first loads.<br>            view.requestApplyInsets()<br>        }<br>    }<br>}</pre><p><strong>Note:</strong> If the injected insets look too large, it might be because your website’s <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Viewport_meta_tag">Viewport initial-scale</a> is more than 1. In this case, divide the top, right, bottom, and left variables by the scale.</p><h3>Handling IME insets in WebViews</h3><p>To ensure your web page correctly adjusts when the on-screen keyboard (IME) appears, you must also account for IME insets. The provided Compose and Views code example already includes this by retrieving <a href="https://developer.android.com/reference/kotlin/androidx/compose/foundation/layout/package-summary#(androidx.compose.foundation.layout.WindowInsets.Companion).safeDrawing()">WindowInsets.safeDrawing()</a> in Compose or <a href="https://developer.android.com/reference/androidx/core/view/WindowInsetsCompat.Type#ime()">WindowInsetsCompat.Type.ime()</a> in Views:</p><pre>// Getting IME insets from the above Compose code sample<br>// safeDrawing includes ime, systemBars, and displayCutout<br>WindowInsets.safeDrawing<br><br><br>// Getting IME insets from the above Views code sample<br>val safeDrawingInsets = windowInsets.getInsets(<br>    systemBars() or displayCutout() or ime()<br>)</pre><p>Omitting IME insets will lead to issues where the webpage content is obscured by the keyboard. For example, when the user taps an HTML text input and the IME expands, the webpage won’t resize, preventing the user from seeing content hidden behind the keyboard. By including IME insets, the webpage dynamically adjusts its layout when the IME is displayed, ensuring all content remains accessible to the user.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*3e88JJfzuyOX22BM" /><figcaption><strong>Figure 3.</strong> Left (incorrect implementation) to right (correct implementation). (a) The left GIF shows a full-screen WebView where IME insets <em>aren’t</em> handled. When the IME appears, the user cannot scroll to view content behind it. (b) The right image shows the same WebView with correct IME inset handling. After the IME appears, the user can scroll to access the full webpage content.</figcaption></figure><p>In summary, ensuring WebViews are compatible with an edge-to-edge display requires different approaches depending on whether the app owns the web content. For external content, wrap the WebView in a container and apply insets as padding. For owned content, either pad the container or inject JavaScript to handle insets within the webpage.</p><p>The code snippets in this blog have the following license:</p><pre>// Copyright 2024 Google LLC. SPDX-License-Identifier: Apache-2.0</pre><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a6ef319adfac" width="1" height="1" alt=""><hr><p><a href="https://medium.com/androiddevelopers/make-webviews-edge-to-edge-a6ef319adfac">Make WebViews edge-to-edge</a> was originally published in <a href="https://medium.com/androiddevelopers">Android Developers</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Insets handling tips for Android 15’s edge-to-edge enforcement]]></title>
            <link>https://medium.com/androiddevelopers/insets-handling-tips-for-android-15s-edge-to-edge-enforcement-872774e8839b?source=rss-54b43884b5c2------2</link>
            <guid isPermaLink="false">https://medium.com/p/872774e8839b</guid>
            <category><![CDATA[android-15]]></category>
            <category><![CDATA[display-cutouts]]></category>
            <category><![CDATA[edge-to-edge]]></category>
            <category><![CDATA[windowinsets]]></category>
            <category><![CDATA[system-bars]]></category>
            <dc:creator><![CDATA[Ash Nohe]]></dc:creator>
            <pubDate>Tue, 03 Sep 2024 18:12:32 GMT</pubDate>
            <atom:updated>2024-09-03T18:12:32.484Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cbWmzhcQsly95rHdfYZA1g.png" /></figure><p><em>This blog post is part of our series: Spotlight Week on Android 15, where we provide resources — blog posts, videos, sample code, and more — all designed to help you prepare your apps and take advantage of the latest features in Android 15. You can </em><a href="https://android-developers.googleblog.com/2024/09/android-15-spotlight-week.html"><em>read more in the overview of Spotlight Week: Android 15 here</em></a><em>, which will be updated throughout the week.</em></p><p>Users prefer edge-to-edge over non edge-to-edge screens for both gesture navigation and three button navigation, according to an internal Google user study.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/672/0*slB_IINZvaY5hs-C" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/672/0*MbXvOJFjbxi9J3P_" /><figcaption><strong>Figure 1. Top or Left:</strong> an edge-to-edge app. The app’s background draws under the status bar at the top and the navigation bar at the bottom. <strong>Bottom or Right:</strong> an app that is not edge-to-edge. The app’s background and content avoid the status bar and navigation bar.</figcaption></figure><h3>Android 15 enforces edge-to-edge</h3><p>Before target SDK 35 (Android 15), your app does <em>not</em> draw edge-to-edge without explicit code changes to intentionally go edge-to-edge. After setting targetSdk=35 or higher, the system will draw <a href="https://developer.android.com/about/versions/15/behavior-changes-15#edge-to-edge">your app edge-to-edge</a> by default on Android 15 and later devices. While this change can make it easier for many apps to go edge-to-edge, critical UI elements may also be inaccessible to users. Your app must handle insets to ensure critical UI elements remain accessible.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/960/0*QoPHCruOvGLpOFiW" /><figcaption><strong>Figure 2. </strong>App targeting SDK 34 on an Android 15 device. The app is not edge-to-edge.</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/960/0*gccufnF3rDqd2Q43" /><figcaption><strong>Figure 3. </strong>App targeting SDK 35 on an Android 15 device. The app is edge-to-edge but insets are <em>not</em> handled. The status bar, navigation bar, and the display cutout obscure UI.</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/960/0*4kDbb37Y1otVy5fw" /><figcaption><strong>Figure 4. </strong>App targeting SDK 35 on an Android 15 device. The app is edge-to-edge and insets are handled so that critical UI isn’t obscured.</figcaption></figure><p>If your app is already edge-to-edge or in immersive mode, you’re unaffected. However, it’s still worth testing your app for breakages.</p><h3>Insets handling tips</h3><p>There are various APIs and attributes you can use to handle insets to avoid the System UI and display cutout.</p><p>This article explains the following tips that are applicable to Compose and Views:</p><ol><li>Use material components to make handling insets easier</li><li>Draw backgrounds edge-to-edge, and inset critical UI</li><li>Handle display cutout and caption bar insets</li><li>Don’t forget the last list item</li><li>Don’t forget IMEs</li><li>For backwards compatibility, use enableEdgeToEdge instead of setDecorFitsSystemWindows</li><li>Background protect system bars only when necessary</li></ol><p>It also provides these tips that are specific to Compose:</p><p>8. Use Scaffold’s PaddingValues</p><p>9. Use high level WindowInset APIs</p><p>Finally, it includes these tips specific to Views:</p><p>10. Prefer ViewCompat.setOnApplyWindowInsetsListener over fitsSystemWindows=true</p><p>11. Apply insets based on app bar height on bar layout</p><h4>1. Use material components to make handling insets easier</h4><p>Many material components automatically handle insets, meaning the component’s background draws inside the system bar region and pads critical UI (see tip #2). Some material components do <em>not</em> automatically handle insets, but instead provide methods to make handling insets easier.</p><p>Material 3 Components (androidx.compose.material3) that automatically handle insets:</p><ul><li>BottomAppBar</li><li>CenterAlignedTopAppBar</li><li>DismissibleDrawerSheet</li><li>LargeTopAppBar</li><li>MediumTopAppBar</li><li>ModalBottomSheet</li><li>ModalDrawerSheet</li><li>NavigationBar</li><li>NavigationRail</li><li>NavigationSuiteScaffold</li><li>PermanentDrawerSheet</li><li>TopAppBar</li><li>SmallTopAppBar</li></ul><p>Material 2 Components (androidx.compose.material) don’t automatically handle insets themselves by default, unlike Material 3 components. Consider updating to <a href="https://m3.material.io/blog/migrating-material-3">Material 3 Components</a>. Otherwise, many Material 2 components support specifying the window insets to apply with the windowInsets parameter, like the <a href="https://developer.android.com/reference/kotlin/androidx/compose/material/package-summary#BottomAppBar(androidx.compose.foundation.layout.WindowInsets,androidx.compose.ui.Modifier,androidx.compose.ui.graphics.Color,androidx.compose.ui.graphics.Color,androidx.compose.ui.graphics.Shape,androidx.compose.ui.unit.Dp,androidx.compose.foundation.layout.PaddingValues,kotlin.Function1)">BottomAppBar</a>, <a href="https://developer.android.com/reference/kotlin/androidx/compose/material/package-summary#TopAppBar(androidx.compose.foundation.layout.WindowInsets,androidx.compose.ui.Modifier,androidx.compose.ui.graphics.Color,androidx.compose.ui.graphics.Color,androidx.compose.ui.unit.Dp,androidx.compose.foundation.layout.PaddingValues,kotlin.Function1)">TopAppBar</a>, <a href="https://developer.android.com/reference/kotlin/androidx/compose/material/package-summary#BottomNavigation(androidx.compose.foundation.layout.WindowInsets,androidx.compose.ui.Modifier,androidx.compose.ui.graphics.Color,androidx.compose.ui.graphics.Color,androidx.compose.ui.unit.Dp,kotlin.Function1)">BottomNavigation</a>, and <a href="https://developer.android.com/reference/kotlin/androidx/compose/material/package-summary#NavigationRail(androidx.compose.foundation.layout.WindowInsets,androidx.compose.ui.Modifier,androidx.compose.ui.graphics.Color,androidx.compose.ui.graphics.Color,androidx.compose.ui.unit.Dp,kotlin.Function1,kotlin.Function1)">NavigationRail</a>. Likewise, use the contentWindowInsets parameter for <a href="https://developer.android.com/reference/kotlin/androidx/compose/material/package-summary#Scaffold(androidx.compose.foundation.layout.WindowInsets,androidx.compose.ui.Modifier,androidx.compose.material.ScaffoldState,kotlin.Function0,kotlin.Function0,kotlin.Function1,kotlin.Function0,androidx.compose.material.FabPosition,kotlin.Boolean,kotlin.Function1,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.compose.ui.unit.Dp,androidx.compose.ui.graphics.Color,androidx.compose.ui.graphics.Color,androidx.compose.ui.graphics.Color,androidx.compose.ui.graphics.Color,androidx.compose.ui.graphics.Color,kotlin.Function1)">Scaffold</a>. Otherwise, apply the insets as padding.</p><p>Material View Components (com.google.android.material) that automatically handle insets:</p><ul><li>BottomAppBar</li><li>BottomNavigationView</li><li>NavigationRailView</li><li>NavigationView</li></ul><h4>2. Draw backgrounds edge-to-edge, and inset critical UI.</h4><p>Oftentimes, apps will set the system bars to the same color as the app bars to appear edge-to-edge, which is an anti-pattern.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*EQXSmlavPzOkBAPf" /><figcaption><strong>Figure 5. </strong>App targeting SDK 34 on an Android 15 device. The app has set the status bar and navigation bar colors, which is no longer supported after targeting SDK 35. The status and navigation bar color are intentionally set to a slightly different shade so you can distinguish the system bars from the app bars, but usually apps will use the same colors for the system and app bars to appear edge-to-edge.</figcaption></figure><p>Apps using this anti-pattern do <em>not</em> appear edge-to-edge all the time, especially on large screen devices.</p><p>To improve this app’s UX after edge-to-edge is enforced, extend the background of the app bars so they draw underneath the transparent system bars, then inset the text and buttons to avoid the system bars. Material 3 components TopAppBars and BottomAppBars do this automatically. For Material 2 components, use the windowInsets parameter. For Views, some Material components handle this automatically. Otherwise, you’ll use fitsSystemWindows or ViewCompat.setOnApplyWindowInsetsListener.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/723/1*EI14QRwSWhfsKyuG3r46nQ.png" /><figcaption><strong>Figure 6.</strong> Edge-to-edge enforced. <strong>Left:</strong> Insets not handled. <strong>Right:</strong> Insets handled. App bars draw under transparent system bars and text and icons avoid the system bars.</figcaption></figure><h4>3. Handle display cutout and caption bar insets</h4><p>While handling insets, account for the display cutouts and caption bars in addition to the status and navigation bars.</p><p><strong>Display cutouts</strong></p><p>A display cutout often contains the camera. After targeting SDK 35, your app might have important UI under the display cutout, especially when the cutout is on the left or right edges of the device.</p><p>For example, prior to targeting SDK 35, your app might have a large white box to account for a camera cutout in landscape.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*999HQOP2NqGP0MVW" /><figcaption><strong>Figure 7. </strong>App targeting SDK 34 on an Android 15 device.</figcaption></figure><p>After targeting SDK 35, the white box disappears and all content moves to the left. Some content draws underneath the camera cutout.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*ipbhbNLa__duKA_V" /><figcaption><strong>Figure 8. </strong>App targeting SDK 35 on an Android 15 device. The camera hides Sheep’s photo.</figcaption></figure><p><strong>Handling display cutouts in Compose</strong></p><p>In Compose, easily handle display cutouts using WindowInsets.safeContent, WindowInsets.safeDrawing, or WindowInsets.safeGestures. Or, use WindowInsets.displayCutout for fine-grained control. Unfortunately, at the time of writing this blog, Scaffold’s PaddingValues does <em>not</em> yet account for the display cutout.</p><pre>// Shows using WindowInsets.displayCutout for fine-grained control.<br>// But, it&#39;s often sufficient and easier to instead use<br>// WindowInsets.safeContent, WindowInsets.safeDrawing, or WindowInsets.safeGestures<br>@Composable<br>fun ChatRow(...) {<br>   val layoutDirection = LocalLayoutDirection.current<br>   val displayCutout = WindowInsets.displayCutout.asPaddingValues()<br>   val startPadding = displayCutout.calculateStartPadding(layoutDirection)<br>   val endPadding = displayCutout.calculateEndPadding(layoutDirection)<br>   Row(<br>       modifier = modifier.padding(<br>               PaddingValues(<br>                   top = 16.dp,<br>                   bottom = 16.dp,<br>                   // Ensure content is not hidden by display cutouts<br>                   // when rotating the device.<br>                   start = startPadding.coerceAtLeast(16.dp),<br>                   end = endPadding.coerceAtLeast(16.dp)<br>               )<br>           ),<br>       ...<br>   ) { ... }</pre><p>After handling display cutouts, the app looks like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*EyFEUe2QkbzeiVkI" /><figcaption><strong>Figure 9. </strong>App targeting SDK 35 on an Android 15 device. Display cutout insets handled. Note: ideally “Chats” should also be padded to the right.</figcaption></figure><p>You can test various display cutout configurations on the <a href="https://developer.android.com/studio/debug/dev-options">Developer options</a> screen under Display cutout.</p><p>Learn more about this example in the codelab, <a href="https://developer.android.com/codelabs/edge-to-edge#4">Handle edge-to-edge enforcements in Android 15</a>.</p><p><strong>Handling display cutouts in Views</strong></p><p>In Views, handle display cutouts using WindowInsetsCompat.Type.displayCutout. See the <a href="https://developer.android.com/develop/ui/views/layout/edge-to-edge#cutout-insets">documentation</a> for a code sample.</p><p>Note: If your app has a non-floating window (for example, an Activity) that is using <a href="https://developer.android.com/reference/android/view/WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT">LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT</a>, <a href="https://developer.android.com/reference/android/view/WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER">LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER</a> or <a href="https://developer.android.com/reference/android/view/WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES">LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES</a>, Android will interpret these cutout modes to be <a href="https://developer.android.com/reference/android/view/WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS">LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS</a> starting in Android 15, causing your window to draw into the display cutout region. Ensure to test your screens that use DEFAULT, NEVER, or SHORT_EDGES.</p><p><strong>Caption bars</strong></p><p>When your app appears in a desktop emulator or in a free form window, it has a caption bar instead of a status bar.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*KZl5e5OImbl1sHht" /><figcaption><strong>Figure 10. </strong>The caption bar in a desktop emulator.</figcaption></figure><p>While handling insets in Compose, use either Scaffold’s PaddingValues, WindowInsets.safeContent, WindowInsets.safeDrawing, or WindowInsets.systemBars, which all include the caption bar. Don’t use WindowInsets.statusBars.</p><p>In your app’s View-based layouts, use WindowInsetsCompat.Type.systemBars. Don’t use WindowInsetsCompat.Type.statusBars.</p><h4>4. Don’t forget the last list item</h4><p>After targeting SDK 35, the last item of your lists might be inaccessible, especially if it’s behind three-button navigation or the taskbar.</p><p><strong>Handling the last list item in Compose</strong></p><p>To handle the last list item in Compose, use LazyColumn’s <a href="https://developer.android.com/develop/ui/compose/lists#content-padding">contentPadding</a> to add a space to the last item unless you are using TextField:</p><pre>Scaffold { innerPadding -&gt;<br>    LazyColumn(<br>        contentPadding = innerPadding<br>    ) {<br>        // Content that does not contain TextField<br>    }<br>}</pre><p>For TextField, use a Spacer to draw the last TextField in a LazyColumn. For an in-depth overview of handling insets with lists, see <a href="https://developer.android.com/develop/ui/compose/layouts/insets#inset-consumption">Inset consumption</a>.</p><pre>LazyColumn(<br>    Modifier.imePadding()<br>) {<br>    // Content with TextField<br>    item {<br>        Spacer(<br>            Modifier.windowInsetsBottomHeight(<br>                WindowInsets.systemBars<br>            )<br>        )<br>    }<br>}</pre><p><strong>Handling the last list item in Views</strong></p><p>Adding clipToPadding=”false” can ensure the last list item appears above the navigation bar for RecyclerView or NestedScrollView. Take this app for example. After targeting SDK 35, the app’s list UI shows the last list item underneath the navigation bar.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/738/0*vLj4l9sX6rOCYHGe" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/432/0*7T3mATW6UP43AEfr" /><figcaption><strong>Figure 11.</strong> App with Recycler View. <strong>Left:</strong> targeting SDK 34. Last list item appears above three-button navigation. <strong>Right:</strong> targeting SDK 35. Last list item draws underneath three-button navigation.</figcaption></figure><p>We can use the window inset listener so that all list items, including the last list item, are padded above the navigation bar.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/432/0*cOXuH_fMjEV1CHak" /><figcaption><strong>Figure 12. </strong>App has handled insets, but feels less immersive because content does not scroll behind system bars.</figcaption></figure><pre>// Figure 12<br>ViewCompat.setOnApplyWindowInsetsListener(<br>    findViewById(R.id.recycler_view)<br>) { v, insets -&gt;<br>    val innerPadding = insets.getInsets(<br>        // Notice we&#39;re using systemBars, not statusBar<br>        WindowInsetsCompat.Type.systemBars()<br>        // Notice we&#39;re also accounting for the display cutouts<br>        or WindowInsetsCompat.Type.displayCutout()<br>        // If using EditText, also add <br>        // &quot;or WindowInsetsCompat.Type.ime()&quot;<br>        // to maintain focus when opening the IME<br>    )<br>    v.setPadding(<br>        innerPadding.left,<br>        innerPadding.top,<br>        innerPadding.right,<br>        innerPadding.bottom)<br>    insets<br>}</pre><p>However, now the app looks less immersive. To get the result we want, add clipToPadding=false to ensure the last list item sits above the navigation bar and the list is visible while scrolling behind the navigation bar (and status bar).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/354/1*GH7LgZ5kBvAOH0EFe8EGPw.gif" /><figcaption><strong>Figure 13. </strong>App displays edge-to-edge and the last list item is fully visible. This is the result we want.</figcaption></figure><pre>&lt;!-- Figure 13 --&gt;<br>&lt;RecyclerView<br>    ...<br>    android:clipToPadding=&quot;false&quot; /&gt;</pre><h4>5. Don’t forget IMEs</h4><p>Set <a href="https://developer.android.com/guide/topics/manifest/activity-element#wsoft">android:windowSoftInputMode=”adjustResize”</a> in your Activity’s AndroidManifest.xml entry to make room for the IME (or soft keyboard) on screen.</p><p><strong>Handling IMEs insets in Compose</strong></p><p>Account for the IME using <a href="https://developer.android.com/reference/kotlin/androidx/compose/ui/Modifier#(androidx.compose.ui.Modifier).imePadding()">Modifier.imePadding()</a>. For example, this can help maintain focus on a TextField in a LazyColumn when the IME opens. See the <a href="https://developer.android.com/reference/kotlin/androidx/compose/ui/Modifier#(androidx.compose.ui.Modifier).imePadding()">Inset consumption</a> section for a code example and explanation.</p><p><strong>Handling IMEs insets in Views</strong></p><p>Before targeting SDK 35, using android:windowSoftInputMode=”adjustResize” was all you needed to maintain focus on — for example — an EditText in a RecyclerView when opening an IME. With “adjustResize”, the framework treated the IME as the system window, and the window’s root views were padded so content avoids the system window.</p><p>After targeting SDK 35, you must also account for the IME using ViewCompat.setOnApplyWindowInsetsListener and <a href="https://developer.android.com/reference/androidx/core/view/WindowInsetsCompat.Type#ime()">WindowInsetsCompat.Type.ime()</a> because the framework will <em>not</em> pad the window’s root views. See Figure 12&#39;s code example.</p><h4>6. For backward compatibility, use enableEdgeToEdge instead of setDecorFitsSystemWindows</h4><p>After your app has handled insets, make your app edge-to-edge on previous Android versions. For this, use <a href="https://developer.android.com/develop/ui/views/layout/edge-to-edge#enable-edge-to-edge-display">enableEdgeToEdge</a> instead of <a href="https://developer.android.com/develop/ui/views/layout/edge-to-edge-manually">setDecorFitsSystemWindows</a>. The enableEdgeToEdge method encapsulates the about <a href="https://medium.com/androiddevelopers/is-your-app-providing-a-backward-compatible-edge-to-edge-experience-2479267073a0">100 lines of code</a> you need to be truly backward compatible.</p><h4>7. Background protect system bars only when necessary</h4><p>In many cases, keep the new Android 15 defaults. The status bar and gesture navigation bar should be transparent, and three button navigation translucent after targeting SDK 35 (see Figure 1).</p><p>However, there are some cases where you wish to preserve the background color of the system bars, but the APIs to set the status and navigation bar colors are <a href="https://developer.android.com/about/versions/15/behavior-changes-15#deprecated-apis">deprecated</a>. We are planning to release an AndroidX library to support this use case. In the meantime, if your app must offer custom background protection to 3-button navigation or the status bar, you can place a composable or view behind the system bar using WindowInsets.Type#tappableElement() to get the 3-button navigation bar height or WindowInsets.Type#statusBars.</p><p>For example, to show the color of the element behind the 3-button navigation in Compose, set the window.isNavigationBarContrastEnforced property to false. Setting this property to false makes 3-button navigation fully transparent (note: this property does <em>not</em> affect gesture navigation).</p><p>Then, use <a href="https://developer.android.com/reference/kotlin/androidx/compose/foundation/layout/WindowInsets.Companion#(androidx.compose.foundation.layout.WindowInsets.Companion).tappableElement()">WindowInsets.tappableElement</a> to align UI behind insets for tappable system UI. If non-0, the user is using tappable bars, like three button navigation. In this case, draw an opaque view or box behind the tappable bars.</p><pre>class MainActivity : ComponentActivity() {<br>    override fun onCreate(savedInstanceState: Bundle?) {<br>        super.onCreate(savedInstanceState)<br>        setContent {<br>            window.isNavigationBarContrastEnforced = false<br>            MyTheme {<br>                Surface(...) {<br>                    MyContent(...)<br>                    ProtectNavigationBar()<br>                }<br>            }<br>        }<br>    }<br>}<br><br><br>// Use only if required.<br>@Composable<br>fun ProtectNavigationBar(modifier: Modifier = Modifier) {<br>   val density = LocalDensity.current<br>   val tappableElement = WindowInsets.tappableElement<br>   val bottomPixels = tappableElement.getBottom(density)<br>   val usingTappableBars = remember(bottomPixels) {<br>       bottomPixels != 0<br>   }<br>   val barHeight = remember(bottomPixels) {<br>       tappableElement.asPaddingValues(density).calculateBottomPadding()<br>   }<br><br>   Column(<br>       modifier = modifier.fillMaxSize(),<br>       verticalArrangement = Arrangement.Bottom<br>   ) {<br>       if (usingTappableBars) {<br>           Box(<br>               modifier = Modifier<br>                   .background(MaterialTheme.colorScheme.background)<br>                   .fillMaxWidth()<br>                   .height(barHeight)<br>           )<br>       }<br>   }<br>}</pre><h3>Inset handling tips for UIs that use Compose</h3><p>The following tips apply only for apps that use <a href="https://developer.android.com/jetpack/compose">Jetpack Compose</a>. See additional Compose-related tips in this video: <a href="https://www.youtube.com/watch?v=QRzepC9gHj4">Edge-to-edge and insets | Compose Tips</a>.</p><h4>8. Use Scaffold’s PaddingValues</h4><p>For Compose, use <a href="https://developer.android.com/develop/ui/compose/layouts/insets#scaffold">Scaffold</a> instead of Surface to organize your app’s UI with TopAppBar, BottomAppBar, NavigationBar, and NavigationRail. Use Scaffold’s PaddingValues parameter to inset your critical UI. In most cases, that’s all you need to do.</p><p>However, there are cases where applying Scaffold’s PaddingValues will cause unexpected results. Scaffold’s PaddingValues includes insets for the top, bottom, start and end edges of the screen. You may need values for only certain edges. One approach is to make a copy of the parameter and manually adjust top, bottom, start and end insets so as to not apply too much padding.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*n-U_9nCJ6UDMvc2TBUcHKA.png" /><figcaption><strong>Figure 14. Left:</strong> The input field at the bottom is obscured by the system’s navigation bar after targeting SDK 35. <strong>Middle</strong>: Scaffold’s PaddingValues applied to the input field. The system uses the size of the status bar and the top app bar to calculate the top padding value, which creates excess padding above the input field. <strong>Right</strong>: Scaffold’s PaddingValues applied but with top padding manually removed.</figcaption></figure><p>Here’s the incorrect code, causing the excess padding seen in the middle image of Figure 14.</p><pre>// Causes excess padding, seen in the middle image of Figure 14.<br>Scaffold { innerPadding -&gt; // innerPadding is Scaffold&#39;s PaddingValues<br>    InputBar(<br>        ...<br>        contentPadding = innerPadding<br>     ) {...}<br>}</pre><p>Here’s the corrected code that generates proper padding, as seen in the right-side image of Figure 14.</p><pre>// Function to make a copy of PaddingValues, using existing defaults unless an<br>// alternative value is specified<br>​​private fun PaddingValues.copy(<br>    layoutDirection: LayoutDirection,<br>    start: Dp? = null,<br>    top: Dp? = null,<br>    end: Dp? = null,<br>    bottom: Dp? = null,<br>) = PaddingValues(<br>    start = start ?: calculateStartPadding(layoutDirection),<br>    top = top ?: calculateTopPadding(),<br>    end = end ?: calculateEndPadding(layoutDirection),<br>    bottom = bottom ?: calculateBottomPadding(),<br>)<br><br>// Produces correct padding, seen in the right-side image of Figure 14.<br>Scaffold { innerPadding -&gt; // innerPadding is Scaffold&#39;s PaddingValues<br>    val layoutDirection = LocalLayoutDirection.current<br>    InputBar(<br>        ...<br>        contentPadding = innerPadding.copy(layoutDirection, top = 0.dp)<br>    ) {...}<br>}</pre><h4>9. Use high level WindowInsets APIs</h4><p>Similar to Scaffold’s PaddingValues, you can also use the high-level WindowInset APIs to easily and safely draw critical UI elements. These are:</p><ul><li><a href="https://developer.android.com/reference/kotlin/androidx/compose/foundation/layout/package-summary#(androidx.compose.foundation.layout.WindowInsets.Companion).safeDrawing()">WindowInsets.safeDrawing</a></li><li><a href="https://developer.android.com/reference/kotlin/androidx/compose/foundation/layout/package-summary#(androidx.compose.foundation.layout.WindowInsets.Companion).safeGestures()">WindowInsets.safeGestures</a></li><li><a href="https://developer.android.com/reference/kotlin/androidx/compose/foundation/layout/package-summary#(androidx.compose.foundation.layout.WindowInsets.Companion).safeContent()">WindowInsets.safeContent</a></li></ul><p>See <a href="https://developer.android.com/develop/ui/compose/layouts/insets">Inset fundamentals</a> to learn more.</p><h3>Inset handling tips for UIs that use Views</h3><p>The following apply only for Views-based apps.</p><h4>10. Prefer ViewCompat.setOnApplyWindowInsetsListener over fitsSystemWindows=true</h4><p>You <em>could</em> use fitsSystemWindows=true to inset your app’s content. It’s an easy 1-line code change. However, don’t use fitsSystemWindows on a View that contains your entire layout (including the background). This will make your app look <em>not</em> edge-to-edge because fitsSystemWindows handles insets on all edges.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/723/1*FNyMJoggLceqihBdLF1Bew.png" /><figcaption><strong>Figure 15.</strong> Edge-to-edge enforced. <strong>Left</strong>: fitsSystemWindows=false (the default). <strong>Right</strong>: fitsSystemWindows=true. This is not the result we want because the app does not look edge-to-edge.</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*gMBc_ymK3g_50TbZ" /><figcaption><strong>Figure 16. </strong>Edge-to-edge enforced, fitsSystemWindows=true. The gap on the left edge is due to a display cutout, which is not visible here. This is not the result we want because the app doesn’t look edge-to-edge.</figcaption></figure><p>fitsSystemWindows can create an edge-to-edge experience if using CoordinatorLayouts or AppBarLayouts.Add fitsSystemWindows to the CoordinatorLayout and the AppBarLayout, and the AppBarLayout draws edge-to-edge, which is what we want.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/723/1*fsLJQdoMEQSmaJcQhNg0jA.png" /><figcaption><strong>Figure 17.</strong> Edge-to-edge enforced. <strong>Left:</strong> AppBarLayout does not automatically handle insets. <strong>Right:</strong> Add fitsSystemWindows to AppBarLayout and CoordinatorLayout to draw edge-to-edge.</figcaption></figure><pre>&lt;!-- Figure 17 --&gt;<br>&lt;CoordinatorLayout<br>    android:fitsSystemWindows=&quot;true&quot;<br>    ...&gt;<br>    &lt;AppBarLayout<br>        android:fitsSystemWindows=&quot;true&quot;<br>        ...&gt;<br>        &lt;TextView<br>            android:text=&quot;App Bar Layout&quot;<br>            .../&gt;<br>    &lt;/AppBarLayout&gt;<br>&lt;/CoordinatorLayout&gt;</pre><p>In this case, AppBarLayout used fitsSystemWindows to draw underneath the status bar rather than avoiding it, which is the opposite of what we might expect. Furthermore, AppBarLayout with fitsSystemWindows=true only applies padding for the top and not the bottom, start, or end edges.</p><p>The CoordinatorLayout and AppBarLayout objects have the following behavior when overriding fitsSystemWindows:</p><ul><li>CoordinatorLayout: backgrounds of child views draw underneath the system bars if those views also set fitsSystemWindows=true. Padding is automatically applied to the content of those Views (e.g. text, icons, images) to account for system bars and display cutouts.</li><li>AppBarLayout: draws underneath the system bars if fitsSystemWindows=true and automatically applies top padding to content.</li></ul><p>In most cases, handle insets with ViewCompat.setOnApplyWindowInsetsListener because it allows you to define which edges should handle insets and has consistent behavior. See tips #4 and #11 for a code example.</p><h4>11. Apply insets based on app bar height during the layout phase</h4><p>If you find that your app’s content is hiding underneath an app bar, you might need to apply insets after the app bar is laid out, taking the app bar height into account.</p><p>For example, if you have scrolling content underneath an AppBarLayout in a FrameLayout, you could use code like this to ensure the scrolling content appears after the AppBarLayout. Notice padding is applied within doOnLayout.</p><pre>val myScrollView = findViewById&lt;NestedScrollView&gt;(R.id.my_scroll_view)<br>val myAppBar = findViewById&lt;AppBarLayout&gt;(R.id.my_app_bar_layout)<br><br><br>ViewCompat.setOnApplyWindowInsetsListener(myScrollView) { scrollView, windowInsets -&gt;<br>   val insets = windowInsets.getInsets(<br>       WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout()<br>   )<br>   myAppBar.doOnLayout { appBar -&gt;<br>       scrollView.updatePadding(<br>           left = insets.left,<br>           right = insets.right,<br>           top = appBar.height,<br>           bottom = insets.bottom<br>       )<br>   }<br>   WindowInsetsCompat.CONSUMED<br>}</pre><p>Likewise, if you have scrolling content that should sit above a BottomNavigationView, you’ll want to account for the BottomNavigationView’s height once it is laid out.</p><h3>Need more time to migrate?</h3><p>It might take significant work to properly support an edge-to-edge experience. Before you target SDK 35, consider how long you need to make the necessary changes in your app.</p><p>If you need more time to handle insets to be compatible with the system’s default edge-to-edge behavior, you can temporarily opt-out using R.attr#windowOptOutEdgeToEdgeEnforcement. But do <em>not</em> plan to use this flag indefinitely as it will be non-functional in the near future.</p><p>The flag might be particularly helpful for apps that have tens to hundreds of Activities. You might opt-out each Activity, then — make your app edge-to-edge one Activity at a time.</p><p>Here’s one approach to using this flag. Assuming your minSDK is less than 35, this attribute must be in values-v35.xml.</p><pre>&lt;!-- In values-v35.xml --&gt;<br>&lt;resources&gt;<br>    &lt;!-- TODO: Remove once activities handle insets. --&gt;<br>    &lt;style name=&quot;OptOutEdgeToEdgeEnforcement&quot;&gt;<br>        &lt;item name=&quot;android:windowOptOutEdgeToEdgeEnforcement&quot;&gt;true&lt;/item&gt;<br>    &lt;/style&gt;<br>&lt;/resources&gt;</pre><p>Create an empty style for past versions in values.xml:</p><pre>&lt;!-- In values.xml --&gt;<br>&lt;resources&gt;<br>    &lt;!-- TODO: Remove once activities handle insets. --&gt;<br>    &lt;style name=&quot;OptOutEdgeToEdgeEnforcement&quot;&gt;<br>        &lt;!-- android:windowOptOutEdgeToEdgeEnforcement<br>             isn&#39;t supported before SDK 35. This empty<br>             style enables programmatically opting-out. --&gt;<br>    &lt;/style&gt;<br>&lt;/resources&gt;</pre><p>Call the style before accessing the decor view in setContentView:</p><pre>class MainActivity : AppCompatActivity() {<br>    override fun onCreate(savedInstanceState: Bundle?) {<br><br>        // Call before the DecorView is accessed in setContentView<br>        theme.applyStyle(R.style.OptOutEdgeToEdgeEnforcement, /* force */ false)<br><br>        super.onCreate(savedInstanceState)<br>        setContentView(R.layout.activity_main)<br>        ...<br>    }<br>}</pre><h3>Resources</h3><p>Android 15 AOSP released today. Our team has created blogs, videos, and codelabs to help get your app ready to handle the <a href="https://developer.android.com/about/versions/15/behavior-changes-15#edge-to-edge">Android 15 edge-to-edge enforcement</a>. What follows is a list of old and new resources for further learning.</p><h4>Documentation</h4><ul><li><a href="https://developer.android.com/about/versions/15/behavior-changes-15#edge-to-edge">Behavior changes for apps targeting Android 15: Edge-to-edge enforcement</a></li><li><a href="https://developer.android.com/develop/ui/compose/layouts/insets">Window insets in Compose</a></li><li><a href="https://developer.android.com/develop/ui/compose/system/cutouts">Cutouts in Compose</a></li><li><a href="https://developer.android.com/develop/ui/views/layout/edge-to-edge">Display content edge-to-edge in your app</a> (Views)</li><li><a href="https://developer.android.com/develop/ui/views/layout/display-cutout">Support display cutouts</a> (Views)</li></ul><h3>Videos</h3><ul><li><a href="https://www.youtube.com/watch?v=QRzepC9gHj4">Edge to Edge &amp; Insets</a> (Compose)</li><li><a href="https://www.youtube.com/watch?v=mlL6H-s0nF0">Insets: Compose edition</a></li><li><a href="https://m.youtube.com/watch?v=RimGfoOU67s">3 things to improve the user experience of your Android app: Handle edge-to-edge enforcements in Android 15</a> walkthrough (Compose)</li></ul><h3>Codelabs</h3><p><a href="https://developer.android.com/codelabs/edge-to-edge#0">Handle edge-to-edge enforcements in Android 15</a> (Compose)</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=872774e8839b" width="1" height="1" alt=""><hr><p><a href="https://medium.com/androiddevelopers/insets-handling-tips-for-android-15s-edge-to-edge-enforcement-872774e8839b">Insets handling tips for Android 15’s edge-to-edge enforcement</a> was originally published in <a href="https://medium.com/androiddevelopers">Android Developers</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Now in Android #108]]></title>
            <link>https://medium.com/androiddevelopers/now-in-android-108-42291f14ba37?source=rss-54b43884b5c2------2</link>
            <guid isPermaLink="false">https://medium.com/p/42291f14ba37</guid>
            <category><![CDATA[google-ai-studio]]></category>
            <category><![CDATA[android-studio]]></category>
            <category><![CDATA[now-in-android]]></category>
            <category><![CDATA[featured]]></category>
            <category><![CDATA[android-15]]></category>
            <dc:creator><![CDATA[Ash Nohe]]></dc:creator>
            <pubDate>Thu, 27 Jun 2024 21:29:33 GMT</pubDate>
            <atom:updated>2024-06-27T21:29:33.822Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*0VEHBhtQU_6AvaaIhR1kCA.png" /></figure><h4><a href="https://android-developers.googleblog.com/2024/06/the-third-beta-of-android-15.html">Android 15 Beta 3</a>, two <a href="https://medium.com/androiddevelopers/building-jetcaster-on-all-form-factors-8e3418eeac13">Compose case studies</a>, <a href="https://android-developers.googleblog.com/2024/06/3-fun-experiments-to-try-for-your-next-android-app-using-google-ai-studio.html">Google AI Studio</a>, <a href="https://adbackstage.libsyn.com/episode-207-ai-development-assistance">Gemini in Android Studio</a>, and <a href="https://developer.android.com/jetpack/androidx/versions/all-channel">lots of stable AndroidX releases</a>.</h4><p>Welcome to episode 108 of Now in Android: your ongoing guide to what’s new and notable in the world of Android development.</p><p>In this episode, we’ll cover <a href="https://android-developers.googleblog.com/2024/06/the-third-beta-of-android-15.html">Android 15 Beta 3</a>, two Compose case studies, <a href="https://android-developers.googleblog.com/2024/06/3-fun-experiments-to-try-for-your-next-android-app-using-google-ai-studio.html">Google AI Studio</a>, <a href="https://adbackstage.libsyn.com/episode-207-ai-development-assistance">Gemini in Android Studio</a>, and lots of stable <a href="https://developer.android.com/jetpack/androidx/versions/all-channel">AndroidX releases</a>.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FgMh07qifhQE%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DgMh07qifhQE&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FgMh07qifhQE%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/9aa29707abec843b01c72b5fa3ee0cef/href">https://medium.com/media/9aa29707abec843b01c72b5fa3ee0cef/href</a></iframe><iframe src="https://cdn.embedly.com/widgets/media.html?src=%2F%2Fhtml5-player.libsyn.com%2Fembed%2Fepisode%2Fid%2F31919802%2Fheight%2F90%2Ftheme%2Fcustom%2Fthumbnail%2Fyes%2Fdirection%2Fforward%2Frender-playlist%2Fno%2Fcustom-color%2F88AA3C%2F&amp;display_name=Libsyn&amp;url=https%3A%2F%2Fnowinandroid.libsyn.com%2F108-android-15-beta-3-google-ai-studio-gemini-in-android-studio-and-more&amp;image=https%3A%2F%2Fassets.libsyn.com%2Fsecure%2Fitem%2F31919802&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=libsyn" width="600" height="90" frameborder="0" scrolling="no"><a href="https://medium.com/media/ce382ad3995412ba7040ce29ccd7d75d/href">https://medium.com/media/ce382ad3995412ba7040ce29ccd7d75d/href</a></iframe><p>Most of the content of this post is available in the form of a <a href="https://youtu.be/gMh07qifhQE">video</a> or <a href="https://nowinandroid.libsyn.com/108-android-15-beta-3-google-ai-studio-gemini-in-android-studio-and-more">podcast</a>, so feel free to <a href="https://youtu.be/gMh07qifhQE">watch</a> or <a href="https://nowinandroid.libsyn.com/108-android-15-beta-3-google-ai-studio-gemini-in-android-studio-and-more">listen</a> rather than read on. (Or do all three to help you remember! There won’t be a quiz.)</p><h3><a href="https://android-developers.googleblog.com/2024/06/the-third-beta-of-android-15.html">The Third Beta of Android 15</a> 🧑‍💻</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-b_VBwmqYCNltLlmUpBuQQ.png" /></figure><p>Android 15 Beta 3 is released, taking Android 15 to Platform Stability. This means the developer APIs and all app-facing behaviors are final for you to review. Also, Apps targeting Android 15 can be published in Google Play.</p><p>The Beta 3 post highlights how users will be able to sign-into apps that target Android 15 using passkeys in a single step with facial recognition, fingerprint, or screen lock.</p><p>The post also covers how the WebSettings DatabaseEnabled getter and setter, which was used for WebSQL inside of a WebView, is deprecated. The World Wide Web Consortium encourages apps needing web databases to instead adopt Web Storage API technologies like IndexedDB.</p><p><a href="https://android-developers.googleblog.com/2024/06/the-third-beta-of-android-15.html">The Third Beta of Android 15</a></p><h3>Android Developers blog 📝</h3><p>Tomáš discusses how Max implemented UI changes 30% faster with Jetpack Compose by reducing boilerplate code, increasing the re-usability of UI elements, and boosting overall developer productivity.</p><p><a href="https://android-developers.googleblog.com/2024/06/max-implemented-ui-changes-faster-using-jetpack-compose.html">Max implemented UI changes 30% faster using Jetpack Compose</a></p><p>Chris discusses how the sample Jetcaster app was enhanced to support additional form factors. He emphasizes code sharing while adding support for Tablets, Desktops, Foldables, TV, Wear OS, and Widgets.</p><p><a href="https://medium.com/androiddevelopers/building-jetcaster-on-all-form-factors-8e3418eeac13">Building Jetcaster on all Form Factors</a></p><p>Robbie highlights several apps from Australia that are improving lives as part of #WeArePlay. One app helps people during natural disasters, another promotes wellbeing through houseplants.</p><p><a href="https://android-developers.googleblog.com/2024/06/weareplay-meet-people-creating-apps-and-games-australia.html">#WeArePlay | Meet the people creating apps and games in Australia</a></p><p>Paris wrote about successful experiments with Android development in Google AI Studio involving turning designs into code, fixing UI, and prompting to add new features.</p><p><a href="https://android-developers.googleblog.com/2024/06/3-fun-experiments-to-try-for-your-next-android-app-using-google-ai-studio.html">3 fun experiments to try for your next Android app, using Google AI Studio</a></p><h3><strong>Android Developers Backstage🎙️</strong></h3><p>On <a href="https://adbackstage.libsyn.com/episode-207-ai-development-assistance">episode 207: “AI development assistance”</a>, Tor and Romain invite Kathy from Google’s AI Developer Assistance team to discuss integrating <a href="https://developer.android.com/studio/preview/gemini">Gemini in Android Studio</a>. You’ll hear inside information about fine-tuning the model for Android, along with how Gemini retrieves information from the internet that is not in the training data to supplement its capabilities. They also discuss future AI possibilities, like providing personalization based off of the users codebase and writing edge test cases.</p><p>Listen to it in <a href="https://adbackstage.libsyn.com/episode-207-ai-development-assistance">podcast</a> or <a href="https://www.youtube.com/watch?v=tprU6FTZrHc">video</a> format.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=%2F%2Fhtml5-player.libsyn.com%2Fembed%2Fepisode%2Fid%2F31827772%2Fheight%2F90%2Ftheme%2Fcustom%2Fthumbnail%2Fyes%2Fdirection%2Fforward%2Frender-playlist%2Fno%2Fcustom-color%2F88AA3C%2F&amp;display_name=Libsyn&amp;url=https%3A%2F%2Fadbackstage.libsyn.com%2Fepisode-207-ai-development-assistance&amp;image=https%3A%2F%2Fassets.libsyn.com%2Fsecure%2Fitem%2F31827772&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=libsyn" width="600" height="90" frameborder="0" scrolling="no"><a href="https://medium.com/media/b466089afeaf9ff62ab66ac23f3e343f/href">https://medium.com/media/b466089afeaf9ff62ab66ac23f3e343f/href</a></iframe><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FtprU6FTZrHc%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DtprU6FTZrHc&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FtprU6FTZrHc%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/ab955cc68b0510bbc032157188fa07ba/href">https://medium.com/media/ab955cc68b0510bbc032157188fa07ba/href</a></iframe><h3>Videos💡</h3><p>Nick recaps the top three I/O announcements from Google Play including enhanced store listings, expanded payment options, and SDK Console improvements.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2Fve9_jM39dgQ%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3Dve9_jM39dgQ&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2Fve9_jM39dgQ%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/449b58521a0ce09a3daf7f73c509cf74/href">https://medium.com/media/449b58521a0ce09a3daf7f73c509cf74/href</a></iframe><p>At Google I/O Yigit advises developers to start experimenting with Kotlin Multiplatform.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2F3l8hkC6_fqg&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3D3l8hkC6_fqg&amp;image=http%3A%2F%2Fi.ytimg.com%2Fvi%2F3l8hkC6_fqg%2Fhqdefault.jpg&amp;key=d04bfffea46d4aeda930ec88cc64b87c&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/13ff66f32715c30cf27b92b5332928d5/href">https://medium.com/media/13ff66f32715c30cf27b92b5332928d5/href</a></iframe><p>And Zarah shares why they are excited for shared element transitions and screenshot testing.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2F_-B5uy_bzks%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3D_-B5uy_bzks&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2F_-B5uy_bzks%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/94a18403e75f01b18f4f14ce6829bab3/href">https://medium.com/media/94a18403e75f01b18f4f14ce6829bab3/href</a></iframe><h3><a href="https://developer.android.com/jetpack/androidx/versions/all-channel">AndroidX Releases</a> 🚀</h3><p>There were a lot of stable releases.</p><p><a href="https://developer.android.com/jetpack/androidx/releases/glance#1.1.0">Glance 1.1.0</a> adds unit testing support and more components for building foundational UI elements for your homescreen widgets.</p><p><a href="https://developer.android.com/jetpack/androidx/releases/fragment#1.8.0">Fragment 1.8.0</a> includes AndroidFragment — an API for embedding Fragments in Compose.</p><p>If you’re seeing ‘LocalLifecycleOwner not present’ when using Compose, try upgrading Lifecycle to <a href="https://developer.android.com/jetpack/androidx/releases/lifecycle#2.8.2">Lifecycle 2.8.2</a>, which you can use with any version of Compose without workarounds.</p><p>Several testing libraries are stable, including <a href="https://developer.android.com/jetpack/androidx/releases/test#core-1.6.0">Core-ktx 1.6.0</a>, <a href="https://developer.android.com/jetpack/androidx/releases/test#espresso-3.6.0">Espresso 3.6.0</a>, <a href="https://developer.android.com/jetpack/androidx/releases/test#espresso_device_100_3">Espresso Device 1.0.0</a>, <a href="https://developer.android.com/jetpack/androidx/releases/test#junit_extensions_120_2">JUnit Extensions 1.2.0</a>, <a href="https://developer.android.com/jetpack/androidx/releases/test#truth_extensions_160_2">Truth Extensions 1.6.0</a>, <a href="https://developer.android.com/jetpack/androidx/releases/test#monitor_170_3">Monitor 1.7.0</a>, <a href="https://developer.android.com/jetpack/androidx/releases/test#orchestrator_150_3">Orchestrator 1.5.0</a>, <a href="https://developer.android.com/jetpack/androidx/releases/test#runner-1.6.0">Runner 1.6.0</a>, <a href="https://developer.android.com/jetpack/androidx/releases/test#rules_160_3">Rules 1.6.0</a> and <a href="https://developer.android.com/jetpack/androidx/releases/test#services_150_3">Services 1.5.0</a>.</p><p>Several other stable releases dropped, including <a href="https://developer.android.com/jetpack/androidx/releases/camera#1.3.4">Camera 1.3.4</a>, <a href="https://developer.android.com/jetpack/androidx/releases/compose-animation#1.6.8">Compose Animation 1.6.8</a>, <a href="https://developer.android.com/jetpack/androidx/releases/compose-foundation#1.6.8">Compose Foundation 1.6.8</a>, <a href="https://developer.android.com/jetpack/androidx/releases/compose-material#1.6.8">Compose Material 1.6.8</a>, <a href="https://developer.android.com/jetpack/androidx/releases/compose-runtime#1.6.8">Compose Runtime 1.6.8</a>, <a href="https://developer.android.com/jetpack/androidx/releases/compose-ui#1.6.8">Compose UI 1.6.8</a>, <a href="https://developer.android.com/jetpack/androidx/releases/concurrent#1.2.0">Concurrent 1.2.0</a>, <a href="https://developer.android.com/jetpack/androidx/releases/core#core-remoteviews-1.1.0">Core-RemoteViews 1.1.0</a>, <a href="https://developer.android.com/jetpack/androidx/releases/games#games-controller-2.0.2">Games-Controller 2.0.2</a>.</p><p><a href="https://developer.android.com/jetpack/androidx/versions/all-channel">Recent Release Notes | Android Developers</a></p><h3>Now then… 👋</h3><p>That’s it for this week with Android 15 Beta 3, two Compose case studies, Google AI Studio, Gemini in Android Studio, and lots of stable AndroidX releases.</p><p>Check back soon for your next update from the Android developer universe! 💫</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=42291f14ba37" width="1" height="1" alt=""><hr><p><a href="https://medium.com/androiddevelopers/now-in-android-108-42291f14ba37">Now in Android #108</a> was originally published in <a href="https://medium.com/androiddevelopers">Android Developers</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Now in Android #101]]></title>
            <link>https://medium.com/androiddevelopers/now-in-android-101-6e0df9a15355?source=rss-54b43884b5c2------2</link>
            <guid isPermaLink="false">https://medium.com/p/6e0df9a15355</guid>
            <category><![CDATA[android-15]]></category>
            <category><![CDATA[now-in-android]]></category>
            <category><![CDATA[gemini-nano]]></category>
            <category><![CDATA[google-io-2024]]></category>
            <category><![CDATA[featured]]></category>
            <dc:creator><![CDATA[Ash Nohe]]></dc:creator>
            <pubDate>Thu, 21 Mar 2024 22:02:21 GMT</pubDate>
            <atom:updated>2024-03-21T22:02:21.509Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*aIux1an8zPUXIhTLY7psfw.png" /></figure><h4><a href="https://android-developers.googleblog.com/2024/03/the-second-developer-preview-of-android-15.html">Android 15 Developer Preview 2</a>, #<a href="https://android-developers.googleblog.com/2024/03/tas24-recap.html">TheAndroidShow</a>, the <a href="https://android-developers.googleblog.com/2024/03/google-io-24-save-the-date.html">Google I/O date</a>, the <a href="https://android-developers.googleblog.com/2024/03/android-14-meta-early-adoption-enhanced-user-experience.html">Meta Android OS Readiness Program</a>, <a href="https://www.youtube.com/watch?v=DeEmqBydY24">Google Play’s enhanced fraud protections</a> and more!</h4><p>Welcome to Now in Android; your ongoing guide to what’s new and notable in the world of Android development.</p><p>In this episode we cover <a href="https://android-developers.googleblog.com/2024/03/the-second-developer-preview-of-android-15.html">Android 15 Developer Preview 2</a>, <a href="https://android-developers.googleblog.com/2024/03/tas24-recap.html">The Android Show</a>, the <a href="https://android-developers.googleblog.com/2024/03/google-io-24-save-the-date.html">Google I/O date</a>, the <a href="https://android-developers.googleblog.com/2024/03/android-14-meta-early-adoption-enhanced-user-experience.html">Meta Android OS Readiness Program</a>, <a href="https://www.youtube.com/watch?v=DeEmqBydY24">Google Play’s enhanced fraud protections</a>, and more.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FRUc1jc5BzWM&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DRUc1jc5BzWM&amp;key=d04bfffea46d4aeda930ec88cc64b87c&amp;type=text%2Fhtml&amp;schema=google" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/c225228214ec0b974a114f6bad050846/href">https://medium.com/media/c225228214ec0b974a114f6bad050846/href</a></iframe><iframe src="https://cdn.embedly.com/widgets/media.html?src=%2F%2Fhtml5-player.libsyn.com%2Fembed%2Fepisode%2Fid%2F30484993%2Fheight%2F90%2Ftheme%2Fcustom%2Fthumbnail%2Fyes%2Fdirection%2Fforward%2Frender-playlist%2Fno%2Fcustom-color%2F88AA3C%2F&amp;display_name=Libsyn&amp;url=https%3A%2F%2Fnowinandroid.libsyn.com%2F101-android-15-dp-2-theandroidshow-the-google-io-date-and-more&amp;image=https%3A%2F%2Fassets.libsyn.com%2Fsecure%2Fitem%2F30484993&amp;key=d04bfffea46d4aeda930ec88cc64b87c&amp;type=text%2Fhtml&amp;schema=libsyn" width="600" height="90" frameborder="0" scrolling="no"><a href="https://medium.com/media/0ad0c5c54d5c0f8f6f2347071eac2148/href">https://medium.com/media/0ad0c5c54d5c0f8f6f2347071eac2148/href</a></iframe><p>Most of the content of this post is available in the form of a <a href="https://youtu.be/RUc1jc5BzWM?si=fACbCKjkoEKWjG6I">video</a> or <a href="https://nowinandroid.libsyn.com/101-android-15-dp-2-theandroidshow-the-google-io-date-and-more">podcast</a>, so feel free to <a href="https://youtu.be/RUc1jc5BzWM?si=fACbCKjkoEKWjG6I">watch</a> or <a href="https://nowinandroid.libsyn.com/101-android-15-dp-2-theandroidshow-the-google-io-date-and-more">listen</a> rather than read on. (Or do all three to help you remember! There won’t be a quiz.)</p><h3>The Second Developer Preview of Android 15 🧑‍💻</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-b_VBwmqYCNltLlmUpBuQQ.png" /></figure><p>We released <a href="https://android-developers.googleblog.com/2024/03/the-second-developer-preview-of-android-15.html">the second Developer Preview of Android 15</a>. This developer preview focuses on communications, developer productivity, app flexibility across screens, privacy, app efficiency, and media refinements.</p><p>Android 15 Developer Preview 2 improves communication by extending platform support for satellite connectivity and making the tap to pay experience more seamless and reliable. It improves developer productivity with an enhanced PdfRenderer, automatic language switching refinements in speech recognition, granular line break controls to improve readability, and expanded IntentFilter Functionality to help with web-hosted deep links. It improves privacy by allowing apps to detect that they are being recorded. It adds support to improve app efficiency with the ApplicationStartInfo API, APIs for detailed app size information, and new APIs to help you migrate away from the dataSync Foreground Service type. Media refinements include HDR Headroom control, and an API to help you take advantage of audio dynamic range metadata to manage loudness inconsistencies.</p><p><a href="https://developer.android.com/about/versions/15/get">Get started today</a> testing your app with Android 15 in the emulator, or by flashing a system image onto a Pixel 6+, Pixel Fold, or Pixel Tablet device.</p><p><a href="https://android-developers.googleblog.com/2024/03/the-second-developer-preview-of-android-15.html">The Second Developer Preview of Android 15</a></p><h3>#TheAndroidShow: the latest from MWC, Gemini Nano, Android 15 and more! 📹</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*WpFFScBC5PmoiKEojK8AWw.png" /></figure><p>In our quarterly show for Android developers, we unpack the <a href="https://www.youtube.com/watch?v=BcGfpspxX2E">latest Android foldables</a> and large screens coming out of Mobile World Congress ’24 and how to build for these devices leveraging the <a href="https://developer.android.com/wear/gallery">Wear OS</a> and <a href="https://developer.android.com/large-screens/gallery">Large Screen galleries</a>. We learned that <a href="https://www.youtube.com/watch?v=hHIMUgTuoXE">Generative AI with Gemini Nano and AICore</a> has reduced latency and robust capability despite its small size. App developers shared their amazing work too. Adidas showed they built features up to 30% faster with <a href="https://developer.android.com/jetpack/compose">Jetpack Compose</a>, TikTok users log in up to 30x faster with <a href="https://developer.android.com/design/ui/mobile/guides/patterns/passkeys">Passkeys</a>, and Infinite Painter saw decreased drawing latency using <a href="https://developer.android.com/reference/kotlin/androidx/graphics/package-summary">Jetpack Graphic Core</a> and <a href="https://developer.android.com/reference/androidx/input/motionprediction/MotionEventPredictor">Motion Prediction Library</a>.</p><p><a href="https://android-developers.googleblog.com/2024/03/tas24-recap.html">#TheAndroidShow: the latest from MWC, Gemini Nano, Android 15 and more!</a></p><h3><a href="https://android-developers.googleblog.com/2024/03/google-io-24-save-the-date.html">Google I/O is arriving this year on May 14th</a></h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*bNL49OT6D5o--gDdeUlYYA.png" /></figure><p>Google I/O is arriving this year on <a href="https://android-developers.googleblog.com/2024/03/google-io-24-save-the-date.html">May 14th</a> and you’re invited to join us online! I/O offers something for everyone, whether you are developing a new application or modernizing an existing one.</p><p><a href="https://android-developers.googleblog.com/2024/03/google-io-24-save-the-date.html">Tune in for Google I/O on May 14</a></p><h3>Videos💡</h3><p>We released <a href="https://www.youtube.com/watch?v=DeEmqBydY24">developer guidance for Google Play Protect enhanced fraud protections</a> to explain a new pilot program to block fraudulent apps and offer <a href="https://developers.google.com/android/play-protect/warning-dev-guidance#app_blocked_by_play_protect">resources to developers</a> to avoid getting their apps blocked.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FDeEmqBydY24%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DDeEmqBydY24&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FDeEmqBydY24%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/6172ab50d3065fea3cd31dcdb574ce37/href">https://medium.com/media/6172ab50d3065fea3cd31dcdb574ce37/href</a></iframe><h3>Android Developers Blog 📝</h3><p><a href="https://android-developers.googleblog.com/2024/03/android-14-meta-early-adoption-enhanced-user-experience.html">Meta created an Android OS Readiness Program</a> to accelerate their apps’ targetSDK adoption to within 1 or 2 months of the AOSP release. Terrance covered Meta’s journey working with the Android betas including, testing apps early, utilizing latest tools like the SDK Upgrade Assistant and the <a href="https://developer.android.com/about/versions/14/reference/compat-framework-changes">Compatibility Framework Tool</a>.</p><p><a href="https://android-developers.googleblog.com/2024/03/android-14-meta-early-adoption-enhanced-user-experience.html">Embracing Android 14: Meta&#39;s Early Adoption Empowered Enhanced User Experience</a></p><p><a href="https://android-developers.googleblog.com/2024/03/introducing-new-text-to-speech-engine-wear-os.html">Wear OS introduced a new lightweight Text to Speech engine</a>, and Ouiam covered how to use it to help with accessibility services, coaching cues for exercise apps, navigation cues, and reading aloud incoming alerts through the watch speaker or Bluetooth connected headphones.</p><p><a href="https://android-developers.googleblog.com/2024/03/introducing-new-text-to-speech-engine-wear-os.html">Introducing a new Text-To-Speech engine on Wear OS</a></p><p>Android 14 QPR2 added app screen sharing, so users no longer have to broadcast their entire screen while screen sharing or casting. Francesco covered how <a href="https://android-developers.googleblog.com/2024/03/enhanced-screen-sharing-capabilities-in-android-14.html">Google Meet</a> uses this with the <a href="https://developer.android.com/reference/kotlin/android/media/projection/MediaProjection">MediaProjection APIs</a> to protect users from sharing private information on the screen — like messages and notifications — while screen sharing.</p><p><a href="https://android-developers.googleblog.com/2024/03/enhanced-screen-sharing-capabilities-in-android-14.html">Enhanced screen sharing capabilities in Android 14 (and Google Meet) improve meeting productivity</a></p><p>Geoffrey covered the <a href="https://android-developers.googleblog.com/2024/03/introducing-fused-orientation-provider-api.html">Fused Orientation Provider</a> (FOP), a new API in Google Play services that provides quality and consistent device orientation by fusing signals from accelerometer, gyroscope and magnetometer.</p><p><a href="https://android-developers.googleblog.com/2024/03/introducing-fused-orientation-provider-api.html">Introducing the Fused Orientation Provider API: Consistent device orientation for all</a></p><h3><a href="https://developer.android.com/jetpack/androidx/versions/all-channel#march_6_2024">AndroidX Releases</a> 🚀</h3><p>AndroidX libraries are moving to a <a href="https://developer.android.com/jetpack/androidx/versions/all-channel">default minimum supported Android API level 21</a> (previously 19) starting with releases in April, 2024. If you are currently supporting a lower minSdkVersion, we recommend bumping up to 21 and cleaning up any code to support prior versions.</p><p>There were many new AndroidX Releases including:</p><ul><li><a href="https://developer.android.com/jetpack/androidx/releases/browser#1.8.0">Browser 1.8.0</a> is stable and allows you to further customize your custom tabs.</li><li><a href="https://developer.android.com/jetpack/androidx/releases/compose-material#1.7.0-alpha04">Compose Material 1.7.0-alpha04</a> allows you to use bottom sheets in Navigation Compose with the androidx.compose:material:material-navigation artifact.</li><li><a href="https://developer.android.com/jetpack/androidx/releases/compose-ui#1.7.0-alpha04">Compose UI 1.7.0-alpha04</a> supports stylus handwriting for BasicTextField2 on devices after Android 14.</li><li><a href="https://developer.android.com/jetpack/androidx/releases/navigation#2.8.0-alpha04">Navigation 2.8.0-alpha04</a> lets you customize the sizeTransform at a destination by destination level to fix issues with resizing content when transitioning between screens.</li><li><a href="https://developer.android.com/jetpack/androidx/releases/wear-protolayout#1.2.0-alpha01">Wear Protolayout 1.2.0-alpha01</a> introduces ProtoLayout Arc to help with right-to-left layouts; APIs to help prevent the primary label, secondary label, and bottom chip from going offscreen; and a CircularProgressIndicator for smaller components.</li></ul><p><a href="https://developer.android.com/jetpack/androidx/versions/all-channel#march_6_2024">Recent Release Notes | Android Developers</a></p><h3>Now then… 👋</h3><p>That’s it for this week with Android 15 Developer Preview 2, The Android Show, the Google I/O date, the Meta Android OS Readiness Program, Google Play’s enhanced fraud protections, and more.</p><p>Check back soon for your next update from the Android developer universe! 💫</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6e0df9a15355" width="1" height="1" alt=""><hr><p><a href="https://medium.com/androiddevelopers/now-in-android-101-6e0df9a15355">Now in Android #101</a> was originally published in <a href="https://medium.com/androiddevelopers">Android Developers</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>