01 Aug 2026

feedTalkAndroid

Why This Action-Packed Blockbuster Is Charlize Theron’s Highest-Rated Film Ever

If you think Charlize Theron's action career peaked with any of her more recent films, think again. Audiences…

01 Aug 2026 3:00pm GMT

Google Maps’ most immersive Android Auto upgrade finally hits more drivers—are you next?

Ready for the next level of Google Maps while you drive? Google has started rolling out some long-awaited…

01 Aug 2026 6:30am GMT

This Gerard Butler Fantasy Film Is Already the Highest-Rated Cinematic Event of 2025

French audiences have spoken: The live-action remake of Dragons, led by Gerard Butler, soared to the top of…

01 Aug 2026 6:00am GMT

31 Jul 2026

feedTalkAndroid

Jackery Enters Canada With HomePower Series, Launch Deals to $699

The two units arrive with up to 12kWh of expandable capacity and a 3+2 year warranty

31 Jul 2026 4:05pm GMT

She discovers a forgotten photo of her late dog on Google Maps—”For a moment, it felt like he was still here”

Technology often brings us convenience, but sometimes it delivers unexpected waves of emotion. Becky Turner experienced just that…

31 Jul 2026 3:00pm GMT

Pixel 11 Colors Leak in New Renders From Evan Blass

Four shades across three phones, and a design that barely moved from the Pixel 10

31 Jul 2026 12:16pm GMT

Samsung Explains the Engineering Behind Its New AI Glasses

A tenth of a millimeter mattered, and battery life tops out at nine hours per charge

31 Jul 2026 11:01am GMT

Tecno Teases Concept Phone With Industry-First 0mm Bezel

The concept device shrinks its screen border to zero microns ahead of a September IFA debut

31 Jul 2026 10:18am GMT

China’s Giant Solar Park Is Turning a Desert Green—Why Scientists Are Stunned

Who would have guessed that installing thousands of solar panels in the middle of a barren desert would…

31 Jul 2026 6:30am GMT

Four-day workweek: Iceland’s success story proves Gen Z was right all along

Can a four-day workweek really make us happier, more productive, and less stressed? In Iceland, the answer is…

31 Jul 2026 6:00am GMT

30 Jul 2026

feedTalkAndroid

Leaked Renders Show Google’s Full Pixel 11 Pro Fold Lineup

The renders also reveal the Fold's redesigned camera bar and thinner profile

30 Jul 2026 4:26pm GMT

FCC’s New Robot Ban Covers Future Robot Vacuums From Your Favorite Brands

Your current Roomba is safe, but new imports from China face a steep waiver hurdle.

30 Jul 2026 3:54pm GMT

Samsung Gaming Hub’s July Update Brings Halo and Palworld 1.0

: Xbox Cloud Gaming, Amazon Luna, and Netflix Games all get real firepower this month

30 Jul 2026 3:15pm GMT

The most jaw-dropping Kim Jee-woon film ever made—critics call it a cinematic shockwave!

Looking for an unforgettable jolt of cinema? Kim Jee-woon, one of South Korea's most influential directors, has thrilled…

30 Jul 2026 3:00pm GMT

Official: This Epic Adaptation Is Rated the Best Film of 2024—Over 9 Million Viewers, Rave Reviews, and Major Awards!

If you see one movie from 2024, this is the one not to miss. Nearly ten million moviegoers…

30 Jul 2026 6:30am GMT

Most Android Auto Users Miss This Secret Menu—Unlock Hidden Features in Seconds

Think you know everything Android Auto can do? Think again. Hidden beneath its familiar interface is a developer…

30 Jul 2026 6:00am GMT

29 Jul 2026

feedAndroid Developers Blog

Delivering safer, age-appropriate experiences on Google Play

Posted by Paul Feng, VP of Product Management, Google Play





Providing a safe online experience and protecting users from harm is a top priority at Google Play. We take this responsibility seriously and have been investing continuously to offer baseline protections on our platform while also empowering parents with the tools they need to make decisions for their families. Importantly, we also want to empower Play developers with the capabilities to deliver age-appropriate experiences based on their app's content.

To support this, today, we are taking another big step in our ongoing partnership with parents and developers by announcing the expansion of the Google Play Age Signals API to all Play developers globally. Building on current availability in Brazil, we will expand this experience first to users in Australia and Canada by mid-August, with a full global rollout to all users later this year.

Empowering developers to create age-appropriate experiences

The Play Age Signals API is a privacy-preserving tool that puts parents in the driver's seat allowing them to share their child's age range (e.g. 16-17) directly with apps. It also enables adults to easily share their age when prompted by the app developer. In turn, developers receive the signals they need to tailor their own in-app safety experiences and content for users in an age-appropriate way.

We want to give developers the ability to choose the right protections for the nature of their app. A weather app, for example, shouldn't need the same safety settings as entertainment or media apps. Rather than enforcing one-size-fits-all rules, we give developers the flexibility to choose how they integrate safety signals. With this reliable signal, you retain complete agency to tailor your app's content, features, and settings to match your audience.

Users have a choice to share their age range in a privacy-friendly way

Simplifying controls for parents

Parents shouldn't have to manage complex safety settings across dozens of different apps to keep their children safe. The Play Age Signals API simplifies this by putting age-sharing controls in one place, directly inside the Google Family Link app. Parents have a choice to share their child's age range, and if they choose to share, all Play apps that use Play Age Signals API can receive age signals. This lets children jump straight into age-appropriate content without parents having to manually configure settings inside these apps. Age ranges are never shared by default, and parents can update or turn off these settings at any time.

Centralized and easy way to manage age sharing settings for parents via Family Link App

Building on our broader safety tools

The Play Age Signals API builds upon a strong foundation of established safety features and strict policies we have long enforced on Google Play. Today, we already mandate that apps designed for families meet rigorous safety standards, and we continuously review and scan applications to ensure they are safe for children. For developers, we also offer built-in tools like Restrict Minor Access in the Play Console to help them manage who can discover their apps. For parents, Google Family Link remains a trusted, central dashboard where they can manage screen-time limits, PIN-based content filters, and app download approvals.

Expanding the Play Age Signals API globally adds a powerful new tool to our existing safety suite, helping parents and developers work together to make Google Play an even safer, more trustworthy place for families.


29 Jul 2026 1:00pm GMT

28 Jul 2026

feedAndroid Developers Blog

Celebrating 5 years of Jetpack Compose

Posted by Rebecca Franks, Developer Relations Engineer, Nick Butcher, Product Manager, Loryn Hairston, Product Marketing Manager, Android



Today, we officially celebrate five years since the release of Jetpack Compose 1.0. From version 1.0, announced on July 28th, 2021, to our latest 1.11 release, we've seen the APIs evolve significantly over the years, and we're taking a moment to celebrate.

When we officially announced the 1.0 release, we promised a simpler, faster, and more intuitive way to build native interfaces on Android. Looking back, it's safe to say that Compose didn't just deliver on that promise, but also completely changed the Android ecosystem, with more than 68% of the top 1,000 apps using it in production today.

History

Over the last five years, Compose has grown steadily. In the early days, we explored showing you how to build layouts with the basic Box, Row, and Column. Today, we've expanded Compose to work not just on mobile devices, but to other form factors such as Compose for TV, WearOS, Glance for Widgets, and even display glasses with Jetpack Compose Glimmer.



We recorded an Android Developers Backstage episode with Clara Bayarri, Engineering Lead for Jetpack, and two former leads of the team, Romain Guy and Chet Haase, along with Tor Norbye, Senior Engineering Director. In this episode, they discuss the history of Compose and the early days of development.




Compose highlights over the years

Looking back

The beginnings of Compose were very different from what you know today. Two projects were happening in parallel inside the Android team.

At the time, the Views toolkit team was thinking of unbundling the UI Toolkit into a library to help with development speed, and make it easier for developers to adopt and control updates. Meanwhile, a team was working on a novel idea to build declarative layouts by embedding XML inside Kotlin, which looked something like this:



Those two efforts merged to produce what you know today - a fully declarative UI Toolkit that utilizes the power of a compiler plugin, runtime, and Kotlin:

@Composable
fun Newsfeed(stories: List<Story>) {
    LazyColumn {
        items(stories) { story ->
            Card {
                val author = story.author
                Image(painterResource(author.profilePhoto),
                    contentDescription = author.name)
                Text(author.name)
                Text(story.content)
                if (story.hasCommentsEnabled()) {
                    for(comment in story.comments) {
                        Text(comment.mainContent)
                    }
                }
            }
        }
    }
}

And you, the community, helped us very early on! Before 2021, Compose had a pre-alpha phase, which helped ensure Compose was fit to solve the problems of our developers.

One of our favorite memories is the Android Dev Challenge. We challenged the community to build four different tasks with Compose, filling our feeds with Puppy apps, clocks, and weather apps, and giving us a ton of direct feedback that helped shape the 1.0 release.

Compose has continued to evolve, from launching with a set of Material 2 components to now supporting Material 3 Expressive.

Material 2 in Compose

Material 3 Expressive in Compose

Looking ahead

As of today, Compose 1.11 is the latest version with 1.12 coming soon, offering so much more than 1.0, 5 years ago. This year, we introduced more adaptive APIs, such as FlexBox, Grid, MediaQuery, and Styles. These APIs let you advance to the next level of premium, adaptive UI development with Compose.

At Google I/O 2026, we announced that we are now Compose-first, meaning that all future UI development will happen only in Compose, while the Views toolkit enters maintenance mode. Material Design is also shifting focus entirely to Compose, signaling an end to the findViewById era.

Community is at the heart of Compose

Over the years, you've inspired us with creative examples of how you've used Compose, and we'd love to highlight a few more examples of where we've seen exciting work. JetBrains has been a great partner for Google with Compose, expanding Compose to work across platforms with Compose Multiplatform and enabling desktop, iOS, and web developers to also enjoy the benefits of Compose.

We've really enjoyed following our most beloved newsletters from JetpackCompose.app's Dispatch, AndroidWeekly, to jetc - helping Android Developers stay up-to-date with the latest in the world of Compose and Android.

Another standout contributor is sinasamaki. They've created many delightful experiences using Compose, such as this fun ribbon modifier and the glitchy effect:


Saket Narayan has also always been an inspiration when it comes to creating useful tools for Compose, such as telephoto, a library featuring support for pan and zoom gestures and automatic sub-sampling of large images, or the latest library, Touch Robot, which allows you to easily test interaction animations:

paparazzi.gif(end = 3_000) {
  DebitCard(
    Modifier.testTag("card")
  )

  val touchRobot = rememberTouchRobot()
  LaunchedEffect(Unit) {
    touchRobot.onNode(hasTestTag("card")).performGesture {
      draw(
        path = createAndroidHeadPath(),
        duration = 3.seconds,
      )
    }
  }
}

/** A path drawing the Android head. */
fun createAndroidHeadPath(bounds: Rect): Path = TODO()

Jake Wharton, who has used Compose in innovative ways (like molecule, and even building UI with Compose for the terminal with mosaic). Chris Banes, who has built many Compose libraries over the years, with our most recent favourite - Haze for background blurring, and many of the Android Google Developer Experts like Akshay Chordiya, Huyen Tue Dao, and Katie Barnett, who've contributed to the success of Compose. But this is not about selecting individuals - there have been so many great contributors to the Compose codebase, and many of you continue to inspire us with your fun examples, libraries, and in-depth talks. Without the community, Jetpack Compose wouldn't be as successful as it is today.

Cheers to the next 5 years, and more!

Jetpack Compose has grown from an experimental idea into the standard for Android UI Development. Thank you to the entire Toolkit team at Google, and to the incredible global developer community that wrote libraries, filed bugs, and pushed the boundaries of what declarative UI can do.

This week, we'll be celebrating with some in-person birthday parties across the globe, and a live "Birthday party" on the Android Developers YouTube channel on July 30th at 13:00 UTC. During this time, we'll hang out and discuss Compose and answer your questions!

Cheers to the next 5 years, and happy composing!

28 Jul 2026 4:00pm GMT

27 Jul 2026

feedAndroid Developers Blog

How R8 made Kotlin Coroutines on Android 2x faster

Posted by Andrei Shikov, Senior Software Engineer, Android Toolkit and Jonathan Starup, Software Engineer, R8 Team






Starting from AGP 9.2.0, R8 optimizes most Atomic*FieldUpdater calls into Unsafe variants that perform 2x to 4x better on common operations. This has a particularly large impact on the kotlinx.atomicfu library that implements atomics for kotlinx.coroutines, making launching and cancelling coroutines up to 2x faster. In order to get the benefits, update your AGP to 9.2.0 or above.

With the majority of Android apps adopting Kotlin as their main language of choice, kotlinx.coroutines has become a de-facto standard for asynchronous programming. The library offers a well-designed and structured way of managing concurrent flows that is native to Kotlin. Jetpack Compose was no exception, adopting coroutines for managing pointer events, animations and other interactions. At the time of writing, most concurrent APIs in Compose call suspend functions under the hood and are launching and/or cancelling coroutines to handle updates.

As the Compose team started to investigate performance, coroutines were discovered to be a bottleneck for many operations that happen outside of composition. As an example, 80% of the time spent on creating and updating Modifier.clickable was consumed by launching and cancelling internal coroutines that handled InteractionSource updates. Based on those observations, much of early performance work was focused on removing coroutines from the default path and delaying initialization until necessary.

The cost of a coroutine

The easiest way to analyze a function's internal behavior on Android is to capture an Android Runtime (ART) method trace. An ART method trace is a tool that records the execution flow of an app, showing exactly which methods are called, their order, and how much time is spent in each, allowing developers to identify performance bottlenecks. For an empty LaunchedEffect { } call, it would look something like this:

LaunchedEffect method trace visualized in the Perfetto UI

The method trace above can be separated into three parts:

Cancelling LaunchedEffect is similar to normal completion, except it also creates a CancellationException.

From the profile above, one thing that is immediately suspicious is frequent calls into java.util.concurrent.AtomicReferenceFieldUpdater (purple or green boxes with j… labels). While each call is relatively fast, the frequency is concerning; any non-negligible overhead that is spread out across multiple invocations might add up to a noticeable regression. Zooming in on a call reveals that most of the time is spent on... reflection checks?



An up-close look at the method trace of AtomicReferenceFieldUpdater.get during LaunchedEffect initialization

Coroutines implement a lock-free tree structure for parent-child relationships that makes structured concurrency possible. Turns out, the kotlinx.atomicfu library implements lock-free atomic operations using a well-known JVM primitive, AtomicReferenceFieldUpdater. The updater uses a class reference and a field name to perform atomic operations at runtime, and it has to run several reflective safety checks to make sure the field exists and is accessible. Each operation in coroutines (starting, suspending, cancelling, completing) calls at least one atomic operation, so if it is slow, coroutines will not perform well.

Investigating AtomicReferenceFieldUpdater

But let's not get ahead of ourselves. AtomicReferenceFieldUpdater is actually well-optimized on JVM for over 10 years now, and method traces might capture overhead that is completely removed by a VM level optimization: just-in-time (JIT) or ahead-of-time (AOT) compilations. To verify performance, let's write a few benchmarks to measure the difference between atomic references from kotlinx.atomicfu and java.util.concurrent.atomic.

@RunWith(AndroidJUnit4::class)
class AtomicReferenceBenchmark {
    @get:Rule
    val benchmarkRule = BenchmarkRule()
    
    private val atomicReference = java.util.concurrent.atomic.AtomicReference(false)
    private val atomicRef = kotlinx.atomicfu.atomic<Boolean>(false)
    
    @Test
    fun atomicReference_compareAndSet() {
        benchmarkRule.measureRepeated { 
            atomicReference.compareAndSet(true, false)
            atomicReference.compareAndSet(false, true)
        }
    }

     @Test
    fun atomicRef_compareAndSet() {
        benchmarkRule.measureRepeated {
            atomicRef.compareAndSet(true, false)
            atomicRef.compareAndSet(false, true)
        }
    }

    /* measuring other methods from the method traces above */
}

Running this benchmark on a Pixel 5 (while ensuring AtomicReferenceFieldUpdater#compareAndSet is JIT compiled during warmup), yields the following results on Pixel 5 (API 33):

 50.7 ns  atomicReference_compareAndSet
135   ns  atomicRef_compareAndSet

The measurements confirm the gap, with kotlinx.atomicfu version clearly being approximately 2.7x slower. This confirms that ART does not perform any hidden optimization and reflective access checks add real overhead during runtime.

Looking back at the original method trace, the only meaningful work performed by the AtomicReferenceFieldUpdater is the internal call into Unsafe.getObjectVolatile that actually executes the underlying atomic operation. In most cases, the updater initializer is static, and can be proved to be always correct based on the structure of the surrounding class. Thus, one could statically analyze most of the AtomicReferenceFieldUpdater usages and replace them with an internal Unsafe variant during compilation. It also just happens that Android build toolchain has its very own optimizing compiler that can do exactly that.

Optimization with R8

The Atomic*FieldUpdater classes support subtle, dynamic and reflection-based use, but are often used in statically obvious patterns. This both explains the slow baseline performance and the want for optimization. R8 is a full-program optimizing compiler and is well-suited to see through the simpler patterns to skim the overhead of the reflective safety checks. R8 receives JVM bytecode after the Java or the Kotlin compiler, but to ease readability these examples are presented in Java syntax. This is why there are no type arguments for AtomicReferenceFieldUpdater.

class Example {
    volatile String data = "";
    static final AtomicReferenceFieldUpdater updater =
        AtomicReferenceFieldUpdater.newUpdater(Example.class, String.class, "data");

    void example() {
        // ...
        updater.compareAndSet(this, "", "new");
        // ...
    }
}

The base example creates a static final updater which accesses a volatile field with simple constant arguments for the holder, the type, and the name of the field. The reflection used is totally transparent. It is clear to see this updater references a valid field and that the site of the updater creation has valid access to the field.

In its essence, Atomic*FieldUpdater is a wrapper around a field offset and calls to Unsafe. The best case scenario for the optimization is to replace the updater field with an offset field and replace the updater calls with calls to Unsafe.

Optimizing Atomic*FieldUpdater

The optimization is implemented in three parts: Instrumentation, Replacement, and Clean-up.

Instrumentation

The first step is to introduce offset fields alongside the updater field in order to facilitate direct access via the Unsafe call.

static final long updater$offset =
    SyntheticUnsafe.UNSAFE.objectFieldOffset(Example.class.getDeclaredField("data"))

The field is accessed via reflection, and Unsafe is used to extract the field offset on the class. This code represents the internals of Atomic*FieldUpdater if you disregard reflection validation. Instead, the holder type of the updater and the field type of the volatile field are tracked statically in the compiler.

Note that the original field and its initialization are left as-is. The optimization process optimistically facilitates and optimizes uses and then later cleans up. This is a simple approach to the implementation but also allows partial optimization of updater fields, where some uses are left as they were while others are optimized.

Replacement

At this point in the compiler, after a suitable concurrency join point, we have a list of instrumented updater fields. This means that we can optimize each call site individually based on a few conditions. Consider an example call:

updater.compareAndSet(holder, expectedValue, newValue);

The conditions that Atomic*FieldUpdater requires are these:

If all conditions are met, then the call is replaced by a call to Unsafe without any of the reflection checks.

SyntheticUnsafe.UNSAFE.compareAndSwapObject(holder, Example.updater$offset, expectedValue, newValue)

This new call is faster and simpler but it differs from the original call in regards to its handling of null values in updater and holder. Unless statically ruled out, null-checks are inserted for both.

Clean-up

At this point, the holding class has the original updater field and the new offset field along with call sites that might use either one of the two. If none of the call sites were optimized, then the offset field should be removed and if all of the call sites were optimized, then the updater field should be removed. In both cases the initializing call should also be deleted. The deletion of unused fields and removal of dead code is already done in the compiler, but removing the initializing code here requires a few more tricks.

Both the call to newUpdater and getDeclaredField might have side effects as they can throw exceptions (and their implementation is also unknown since it depends on the API version). This means that by generic optimization, they cannot safely be removed. So this clean-up required explicit consideration of the instrumented fields, since those are statically known to be free of exceptions.

In the end, the simple updater example shown above looks like this after optimization:

class Example {
    volatile String data = "";
    static final long updater$offset =
        SyntheticUnsafe.UNSAFE.objectFieldOffset(Example.class.getDeclaredField("data"))

    void example() {
        // ...
        SyntheticUnsafe.UNSAFE.compareAndSwapObject(this, Example.updater$offset, "", "new")
        // ...
    }
}

Results

After these optimizations, kotlinx.atomicfu and most explicit uses of AtomicInt/Long/ReferenceFieldUpdater now match AtomicReference performance with R8 applied. In fact, it is even faster in some benchmarks; kotlinx.atomicfu has a compiler plugin that can inline atomic instances into fields, reducing allocations required to create an atomically updated field.

Jetpack Compose was the main beneficiary of this work. Compose runtime has a number of microbenchmarks that track coroutine performance very closely to catch performance regressions early. When the benchmarks were updated to a new version of R8, we noticed a 2x improvement when launching and cancelling coroutines in LaunchedEffect!



Benchmark graph illustrating the time taken when starting and cancelling coroutines in LaunchedEffect (lower is better). The change in the graph corresponds to an R8 update, showcasing 2x improvement.

Aside from that, the ART team is implementing these optimizations natively at the VM level. If your app is targeting API 37 and is running on a recent version of Android, it is possible that your device is already optimizing coroutines in a similar way. The coroutine benchmarks above observed ~15% improvement in performance after JIT updates in the recent versions of ART.

Your app will receive this optimization by default when upgrading to AGP 9.2.0 or by using R8 9.2.0 directly. For more information, see D8 dexer and R8 shrinker.

27 Jul 2026 1:00pm GMT

22 Jul 2026

feedAndroid Developers Blog

Optimize your apps for the next generation of Samsung Galaxy devices

Posted by Fahd Imtiaz, Senior Product Manager and Miguel Montemayor, Developer Relations Engineer, Android Developer Experience



Today at Galaxy Unpacked, Samsung unveiled its latest lineup of foldable and wearable devices. For developers, this means that the variety of form factors, screen sizes, and device postures your app needs to support is expanding once again.

With devices like the Galaxy Z Fold8, the ecosystem is expanding to include hardware with a landscape-first natural orientation and a wider aspect ratio in its main display state. Whether a user is unfolding a large display, flipping open a cover screen, or glancing at their wrist, users expect a flawless experience. To help you meet this moment, we're sharing actionable guidance and new tooling updates to enable you to build adaptively proactively.

Rethink layout architecture for dynamic displays, including ultra-wide foldables

Building for the latest foldables means dropping assumptions about display orientation and size. This is especially true for the Galaxy Z Fold8, which adopts an ultra-wide display, adding to the variety of aspect ratios to account for. Devices with this landscape-first natural orientation show the limitations of hardcoded layout rules when users unfold the device. That's why we've introduced dedicated guidance for building for landscape foldables and trifolds.


To build a responsive UI that handles these physics seamlessly, focus on the following core pillars:

  • Build fluid, adaptive layouts: Wide aspect ratios and compact vertical heights require fluid UIs that scale responsively. Our updated adaptive design guidance advises considering the window class width first to determine layout changes, then adjusting for height. To let individual components fluidly adapt to the grid, structure your layout using flexible containers that allow your content to automatically wrap, span, and reflow. For design inspiration browse our adaptive sample app and dual-screen design galleries.
  • Track actual app space: Your app's display space rarely matches the physical device size, especially on an ultra-wide screen during multi-window, split-screen, or multitasking states. Sometimes even the orientations differ. Leverage Window Size Classes using the Jetpack Window Manager library to calculate the exact space your app occupies.


  • Leverage the latest Jetpack Compose Update: Start by adopting the stable Jetpack Compose April '26 release (Compose BOM version 2026.04.01).Take advantage of the new structural layout tools to manage complex architectures. The new Grid API allows you to define dynamic tracks and column spans without the performance overhead of a lazy list. Pair Grid with the new FlexBox layout API to easily handle multi-axis alignment and dynamic item wrapping. You can also use the new MediaQuery API to adapt your UI to its environment, using conditions to detect signals like device posture, window size, and keyboard types.
  • Make your app fold aware: Use the Jetpack WindowManager library, which provides an API surface for foldable device window features such as folds and hinges. When your app is fold aware, it can adapt its layout to avoid placing important content in the area of folds or hinges and use folds and hinges as natural separators.
  • Maintain app continuity: Avoid breaking the user journey when the device configuration shifts. Retain your UI state using ViewModel to ensure smooth transitions when a user folds or unfolds their device.

Ensure seamless camera capture on foldable devices

Camera implementation on foldables brings unique hardware quirks. Moving from a compact outer display to an expanded inner display introduces distinct layout aspect ratios while device rotation remains unchanged. If an app assumes a fixed portrait relationship between the camera sensor and the device layout, the app will likely suffer from sideways, stretched, or cropped previews during these folding transitions.
When optimizing your app's media pipeline, migrate your capture experiences to CameraX using the CameraX migration skill. The library's PreviewView automatically handles sensor orientation, device rotation, and scaling behind the scenes. This guarantees a clean, stable preview regardless of how the user holds or positions the device. If you are maintaining an existing Camera2 codebase, integrate the CameraViewfinder library to apply these complex aspect ratio and rotation transformations automatically without needing a total architecture overhaul.

Extend glanceable interactions to Wear OS 7

The opportunity to build for this new generation of devices extends right to the wrist. Launching with Wear OS 7, Wear Widgets give you a fresh surface to provide users with instant, glanceable access to their essential updates. You can build these highly expressive experiences using Jetpack Glance and RemoteCompose. Crucially, Widgets built with this framework can now populate multi-widget tiles that were previously reserved for first-party widgets.

Build intelligent features

Gemini intelligence already completes tasks on users' behalf, and you can experiment with the intelligence system by sharing your apps capabilities.

Samsung's new foldable devices come with Gemini Nano 4, our latest on-device model. Nano 4 provides support for over 140 languages, better multimodal understanding, and much more. Use ML Kit's Prompt API with advanced features like structured output and thinking mode to build intelligent features on-device.

Start optimizing today

The tools and frameworks are ready to help you optimize your app for all screen sizes. Begin by exploring our guidance for building adaptive apps to learn more about core adaptive design principles.

To dive deeper, check out our comprehensive YouTube playlist. Finally, ensure your app delivers a flawless, premium experience on the newest form factors by reviewing our dedicated quality guidelines for trifolds and landscape foldables and WearOS.

Unfold the future today!

22 Jul 2026 7:00pm GMT

21 Jul 2026

feedAndroid Developers Blog

Build intelligent Android apps: On-device inference

Posted by Caren Chang, Developer Relations Engineer, Android Developer Relations



Welcome back to the blog post series "Build intelligent Android apps" where we take a basic Android app and transform it into a personalized, intelligent, and agentic experience. In our previous post we introduced Jetpacker, the demo app we'll use throughout this series.

In this blog post, we will share how you can use Gemini Nano through ML Kit's Prompt API to build intelligent on-device features.

Building intelligent on-device features refers to the ability to process prompts and data directly on a device without sending data to a server. This offers a few advantages:

  • User data can be processed locally on the device, preserving user privacy
  • Functionality of the model is reliable even with spotty or no internet connection
  • No additional cloud inference cost, since everything runs on the user's hardware

With the benefits of on-device in mind, we identified three features to add in Jetpacker that can improve the user experience: summarizing trip itineraries, managing expenses, and capturing voice notes.

On-device features in Jetpacker: Summarizing trip itineraries, managing expenses, and voice notes


High quality tailored summarization of short texts

The itinerary screen gives users a quick overview of all activities for a given trip. Since this screen contains a lot of information, it can quickly become overwhelming. To help users prepare without feeling overwhelmed, we can add a 'Get ready for your trip' section at the top.

The romantic Paris trip is summarized as a classic Parisian adventure blending art, sights, and delicious food. A tip and some useful phrases are also added.

By inputting a trip itinerary and asking an LLM to summarize it, we can generate a quick summary of the trip along with packing tips and useful local phrases. This is a great use case for an on-device model for several reasons:

  • Performance and quality: Both the input and output text are relatively short. With that, we can expect the performance and quality of an on-device solution to be on par with more powerful cloud models.
  • Scalability: Shifting inference on-device allows us to scale this feature from a few users to millions without worrying about managing increasing cloud inference costs.
  • Low latency and reliability: On-device inference guarantees low latency, providing a reliable experience even when users are offline.

To build with on-device, we use Gemini Nano, Google's most efficient model optimized for mobile devices. Gemini Nano was first introduced a few years ago, and is now running on over 140 million devices. The latest version of the model, Gemini Nano 4, is built on the architecture foundation of the recently released Gemma 4 model, and is further optimized for maximum battery and performance efficiency.

Using ML Kit's Prompt API, we can take advantage of Gemini Nano 4's new model capabilities to prototype our on-device features. We'll create a prompt that includes the itinerary of a trip and ask the model to generate a summary along with any preparation tips.

// implementation("com.google.mlkit:genai-prompt:1.0.0-beta3") 

// Define the configuration for Gemini Nano 4 E2B preview model
val previewFastConfig = generationConfig {
    modelConfig = modelConfig {
        releaseStage = ModelReleaseStage.PREVIEW
        preference = ModelPreference.FAST
    }
}

val geminiNano2BPreviewModel = Generation.getClient(previewFastConfig)

val tripItinerary = ...

val getReadyForYourTripSummary = geminiNano2BPreviewModel
 .generateContent("Given this trip itinerary: $tripItinerary, 
     generate the following: overall vibe, tips on how to prepare for this
     trip, and common short phrases to learn for the trip.")

Finding the optimal prompt usually requires some iteration, and the AICore app is perfect for this step in the process. After opting into the developer preview option for AICore, we can download preview models such as Gemini Nano 4 to test prompts and see the model's expected outputs. With a few iterations on the prompt, we were able to improve the speed of the response from 13 seconds to under 2 seconds! Check out the final code implementation and prompt here.

The first iteration of our prompt generated way too many tokens, and optimizing it helped keep responses quick and to the point.

Local processing for sensitive user input

Next, to help users enjoy their trip even more, we'll build a simple expense manager that takes the manual work out of sorting through receipts and calculating budgets.


Taking a photo of a restaurant bill, data is parsed and shown in the expense overview screen of the app.

Since receipts might contain sensitive information like credit card number and addresses, this is another great use case for an on-device solution. With on-device, users can be confident that private information will be processed locally on the device without any of their data being sent to the cloud.

In addition, Gemini Nano 4 has improved model capabilities for multimodality, especially for image understanding tasks like OCR and visual data extraction, making it a great solution for tasks like extracting information from receipts.

For this use case, the prompt will analyze an image of the receipt, and output information such as: a generated title, amount spent and category of the expense. To ensure the model outputs the information in the preferred format, we can use ML Kit's Structured Output API to seamlessly output a Kotlin data object that we define.

// implementation("com.google.mlkit:genai-prompt:1.0.0-beta3")
// ksp("com.google.mlkit:genai-schema-compiler:1.0.0-alpha1")

@Generable("Information extracted from an expense receipt")
data class ParsedReceipt(
  @Guide("Generated title for the expense less than 6 words. Based on restaurant or activity name.")
  val title: String,
  @Guide("Total amount of the expense. Look for values at the bottom and words like total or balance due.")
  val amount: Double,
  @Guide("Type of expense", enumValues = ["travel", "food", "shopping", "entertainment", "other"])
  val category: String,
)

val prompt = "Determine if the image is a receipt or expense. 
    If it is NOT a receipt or expense, output the text 'NOT_A_RECEIPT'.
    Otherwise, parse the receipt information."

val request = generateContentRequest(ImagePart(bitmap), TextPart(prompt)) {}
val requestWithStructuredOutput = generateTypedContentRequest(request, ParsedReceipt::class)

// Define the configuration for Gemini Nano 4 E4B preview model  
// When selecting models, you can specify which performance charactertists are most important
//  for your use case. Use ModelPreference.FULL when you want to prioritize reasoning power over speed. 
//  Use ModelPreference.FAST when complex logic is not required and latency is a priority.
val previewFullConfig = generationConfig {
    modelConfig = modelConfig {
        releaseStage = ModelReleaseStage.PREVIEW
        preference = ModelPreference.FULL
    }
}

val geminiNano4BPreviewModel = Generation.getClient(previewFullConfig)
val response = geminiNano4BPreviewModel.generateContent(requestWithStructuredOutput)
val parsedReceipt: ParsedReceipt? = response.candidates.firstOrNull()?.response

Multimodal input

Lastly, to help users record audio memos during the trip, let's build a fully on-device voice notes feature. Using ML Kit's Speech Recognition API, we'll enable users to record short voice notes that are automatically transcribed to text. With the transcribed text, we'll use ML Kit's Prompt API to identify which trip activity is associated with the recorded voice note, letting users easily recap their trip as they scroll through the trip's itinerary.

The Roman holiday itinerary shows voice note extracts.

The ML Kit GenAI Speech Recognition API allows you to transcribe audio content to text fully on-device using two distinct modes. Basic mode uses a traditional on-device speech recognition model and is available on most Android devices with API level 31 and higher. Advanced mode uses Gemini Nano to offer broader language coverage and better quality, and is currently supported on Pixel 10 devices.

For our feature we combine the Speech Recognition API with the ML Kit GenAI Prompt API:

// implementation("com.google.mlkit:genai-prompt:1.0.0-beta3")
// implementation("com.google.mlkit:genai-speech-recognition:1.0.0-alpha1")

val tripEvents = ... 

// Set up speech recognition
val speechRecognizerOptions =
    speechRecognizerOptions {
        locale = Locale.US
        preferredMode = SpeechRecognizerOptions.Mode.MODE_ADVANCED
    }
val speechRecognizer: SpeechRecognizer = SpeechRecognition.getClient(speechRecognizerOptions)

suspend fun transcribeVoiceNote(recognizer: SpeechRecognizer) {
    // Display partial text as the user is recording audio
    var partialTextResponse = ""

    // Display the full text once user is finished recording audio
    var transcription = ""

    val request: SpeechRecognizerRequest
        = speechRecognizerRequest { audioSource = AudioSource.fromMic() }
    recognizer.startRecognition(request).collect { response ->
        when (response) {
            is SpeechRecognizerResponse.PartialTextResponse -> {
                partialTextResponse = response.text
            }
            is SpeechRecognizerResponse.FinalTextResponse -> {
                transcription = response.text
                processAndCategorizeVoiceNote(transcription, tripEvents)
            }
        }
    }
}

fun processAndCategorizeVoiceNote(transcribedVoiceNote: String, events: List) {
    val prompt = "Given the voice note $transcribedVoiceNote
     and the following events for this trip: $events, rewrite this transcription
     to remove filler words. Then, identify which events from the
     list this rewritten transcription matches to."

     // Utilize ML Kit's Prompt API to process voice note and tag it with the relevant trip activities
     Generation.getClient().generateContent(prompt)
}

Conclusion

Using ML Kit's GenAI APIs, we were able to take advantage of Gemini Nano to develop fully on-device intelligent features for the JetPacker app, and provide an improved user experience without any additional cloud costs.

Check out the full source code for Jetpacker on Github, and watch the video Build Intelligent Android apps with Google's AI to learn more about how to integrate intelligent features directly into your app using on-device models, cloud-powered reasoning, and the latest agentic frameworks.

Learn more

Check out the other parts of this blog post series:

Part 1: Introduction of the app and a high-level overview.
Part 2 (this post!): On-device intelligence. Deep-dive into ML Kit's GenAI APIs and Gemini Nano to build privacy-first features like itinerary summarization, receipt parsing, and local audio processing.
Part 3: Hybrid and cloud reasoning. Explore how to use Firebase AI Logic to ground LLM answers in real-world data like Google Maps and web context.
Part 4: System integration. Integrating with the Android intelligence system using AppFunctions.
Part 5 (coming soon): In-app agentic workflows. Extend the app with an end-to-end booking assistant powered by A2UI and ADK.

Interested in more on Android Development? Follow Android Developers on YouTube or LinkedIn!

All code snippets in this blog post follow the following copyright notice:

Copyright 2026 Google LLC.
SPDX-License-Identifier: Apache-2.0

21 Jul 2026 1:00pm GMT

Build intelligent Android apps: Introduction to Jetpacker

Posted by Jolanda Verhoef, Senior Developer Relations Engineer, Android Developer Relations


Building GenAI features in your app usually means navigating through various models, APIs and architecture choices:

  • Execution location: Where does your model run? On device, in the cloud, or both?
  • Complexity: How complex is your setup? Are you doing a single inference call or do you need a more agentic flow?
  • In-app or Android System: Should your feature be built into your Android app or does it fit better as an Android system integration?

In this blog post series we'll navigate these choices with you. We will take you along on a journey, starting with a basic mobile app and transforming it into a personalized, intelligent, and agentic experience.

Jetpacker: a demo travel app

Jetpacker is a technical showcase app that our team built from the ground up for this year's Google I/O (built using Antigravity). At its core, Jetpacker helps users plan, explore, and enjoy their next big adventure. It shows an overview of your trips, the itinerary of each trip, and details of each event on that trip. Of course following all best practices of Android development, including a beautifully expressive Material UI design.

And best of all? It's fully open source!

Today we are publishing a series of technical blog posts diving deep into each of these features. We'll provide detailed implementation steps, code snippets, and architectural insights to help you build your own intelligent Android applications.

On-device intelligence

On-device features in Jetpacker: Summarizing trip itineraries, managing expenses, and voice notes

Using an on-device model comes with no additional cloud inference costs, means you don't have to worry about internet connectivity, and lets users be confident that private information will be processed locally, on the device, without any of their data being sent to the cloud.

In Jetpacker, we chose on-device inference for three of our features:

  • The trip overview feature transforms a messy, multi-day itinerary into a concise, actionable summary. It leverages Gemini Nano through the ML Kit GenAI APIs to process data locally on the device. We consider this a nice-to-have feature where we don't want to incur extra cloud costs, making on-device inference the right choice.
  • The expense tracker automatically extracts structured data from receipt images to help users track their travel spending. It uses the multimodal capabilities of Gemini Nano 4 through the ML Kit GenAI APIs. We choose an on-device solution so that any privacy-sensitive information on the receipt images never leaves the user's device.
  • The audio diary records, transcribes, and categorizes voice notes into relevant trip activities. It is powered by the ML Kit Speech Recognition and GenAI Prompt APIs. We chose an on-device solution for privacy and connectivity reasons.

Cloud & hybrid inference













Cloud and hybrid features in Jetpacker: Museum assistant with web grounding, hybrid restaurant review drafting, and hotel support chat featuring custom-routed live translation.

Sometimes your use-case requires AI models with greater world knowledge or a much larger context window and with greater ability in handling complex tasks. In that case, we can switch from running an on-device model to using a cloud model instead.

Or, if you want to get the best of both worlds, you can use hybrid inference to dynamically choose either a cloud or on-device model at runtime. This allows us to lower costs by moving inference to the device when it is available, but at the same time support all Android devices running the app.

In Jetpacker, we implemented several features using cloud or hybrid inference:

  • The place Q&A feature answers user questions about specific locations by grounding responses in real-world data. It uses Firebase AI Logic integrated with Google Maps and web context. Using a cloud model is necessary here for its greater world knowledge.
  • The review drafting feature helps users compose detailed reviews for the places they have visited. It leverages both on-device and cloud models through Firebase AI Logic's new Hybrid inference API. This is a feature we wanted to make available to all app users, so we're using a cloud model as a fallback when an on-device model is unavailable.
  • The automatic chat translation dynamically translates chat messages in real time to facilitate seamless communication, demonstrating custom hybrid inference logic. Again, we want this feature to be available to all app users, but at the same time have some specific considerations on when to choose on-device versus cloud.

System integration

While not a feature you see in the app itself, the Android system integration opens up the app's core capabilities directly to the Android operating system. It uses the AppFunctions API to integrate with system-level intelligence.

In-app agentic workflows (coming soon!)

The booking assistant shows several in-progress flight bookings, asking the user for input before making a final booking.

Agenticness introduces a higher level of autonomy, enabling models to act as agents. Instead of a single inference call, an agent works towards a specific goal via an orchestration loop that allows it to reason, use tools, and adapt its path. Depending on your requirements, these intelligent agents can run either in the cloud, directly on-device, or in a hybrid setup.

For Jetpacker we added a booking assistant that automates end-to-end booking workflows directly within the application to streamline reservations. It is built using A2UI and ADK running in the cloud. The Android app functions as a front-end to the multi-agentic system running in the cloud.

Learn more

Check out the other parts of this blog post series:

Part 1 (this post!): Introduction of the app and a high-level overview.
Part 2: On-device intelligence. Deep-dive into ML Kit's GenAI APIs and Gemini Nano to build privacy-first features like itinerary summarization, receipt parsing, and local audio processing.
Part 3: Hybrid and cloud reasoning. Explore how to use Firebase AI Logic to ground LLM answers in real-world data like Google Maps and web context.
Part 4: System integration. Integrating with the Android intelligence system using AppFunctions.
Part 5 (coming soon): In-app agentic workflows. Extend the app with an end-to-end booking assistant powered by A2UI and ADK.

Interested in more on Android Development? Follow Android Developers on YouTube or LinkedIn!

21 Jul 2026 1:00pm GMT

Build intelligent Android apps: Integrate into Android's intelligence system using AppFunctions

Posted by Ben Weiss, Senior Developer Relations Engineer, Android Developer Relations



Welcome back to the blog post series "Build intelligent Android apps" where we take a basic Android app and transform it into a personalized, intelligent, and agentic experience. In our previous post, we explored how to leverage Firebase AI Logic to build cloud-hosted and hybrid AI features.

Traditional mobile UIs excel at focused, hands-on tasks, and the Android intelligence system is introducing complementary features to make complex, multi-step actions even easier. By supplementing traditional user interfaces, AppFunctions provide a powerful new entry point: A privileged agent on the device can access app features in the background. This can be particularly helpful when users are driving, walking or otherwise multitasking.

In this article, we'll show you how we designed and integrated these capabilities into our travel planning app, JetPacker, using Android AppFunctions. We'll explore the rationale behind our feature choices, discuss the specialized tooling we used to accelerate development, and dive into the code that makes it all work.

Designing AI-ready features: making choices that matter for your users

To select which features to provide to the intelligence system, we looked for tasks where a voice or text command is objectively faster than tapping through screens. In this side-by-side screen recording you can see this contrast perfectly: on the left, a user tapping through multiple screens to log an expense; on the right, the same task completed instantly in the background via a privileged agent.



Our first choice was expense tracking. Logging a coffee expense during a trip usually takes quite a few taps-unlocking the phone, opening the app, finding the active trip, navigating to the expenses tab, tapping the add button, taking a picture of the receipt, and checking the result. By providing the addExpense and getExpenses features as AppFunctions, the system agent handles the heavy lifting. When the user says, "Add a five-dollar coffee expense to my Paris trip," the agent automatically searches for the correct trip ID in the background and inserts the expense, skipping the manual UI flow entirely.

We also prioritized itinerary management. Finding what activity is next on a busy trip itinerary usually requires scrolling through a dense timeline view. By providing getItinerary and addItineraryEvent to the system, the user can simply ask, "What am I doing next in Paris?" and get an immediate answer.



Finally, we focused on hands-free note capturing. Typing out reminders or notes while walking down a busy street is difficult and unsafe. Exposing a voice note capability allows the user to say, "The flight was amazing, I saw a beautiful sunset and managed to sleep well," and the privileged agent automatically transcribes and saves it directly into the travel database using the addVoiceNote AppFunction.

Android MCP powered by AppFunctions

This entire experience is built on Android MCP. Under this design, the app acts as a local MCP server. Rather than remote APIs, you provide your app features directly to the on-device intelligence system.

Android AppFunctions is the API that brings this concept to life. It reads annotated Kotlin functions and compiles them into type-safe, sandboxed tool definitions that the privileged agent can discover and invoke locally on the device.







Diagram highlighting our apps, the android platform, and system agents coordinate AppFunctions.

Under the Android MCP model, your app acts as a local MCP server that exposes structured tools, while the Android platform serves as the central tool registry. On the MCP client side, agent apps are registered with the intelligence system after being granted system-privileged permissions to access the registry.

When a user interacts with a registered agent, its LLM determines if the request can be handled by an AppFunction, queries the platform's metadata, and executes the appropriate registered functions in the background. This local MCP client-server design gives you full control: you choose exactly which features are accessible to the agent, keeping the rest of your app's data private.

How we accelerated development with Android skills

To streamline the integration process, we leveraged the AppFunctions development skill. The AppFunctions development skill is a complete development companion. It guided us through the entire lifecycle: mapping Kotlin data classes to serialize parameters, generating the necessary Service entry points, refining our KDoc documentation to ensure the LLM understands parameter boundaries, and setting up automated testing using ADB.

Providing app features to the intelligence system

Enough with the theory, let's dive into the implementation.

Configuration and dependency setup

We begin by adding the AppFunctions dependencies. One for the API and one for the Kotlin Symbol Processing compiler.

implementation("androidx.appfunctions:appfunctions:1.0.0-alpha10")
ksp("androidx.appfunctions:appfunctions-compiler:1.0.0-alpha10")

Modeling custom data types

Any custom object exchanged with the agent must be annotated with @AppFunctionSerializable. In our TripSerializable.kt file, we define our trip data model:

@AppFunctionSerializable(isDescribedByKDoc = true)
data class TripSerializable(
    /** The trip's unique identifier. */
    val id: String,
    /** The trip's title. */
    val title: String,
    /** The trip's destination location. */
    val location: String,
    /** The trip's start date in milliseconds. */
    val startDate: Long,
    /** The trip's end date in milliseconds. */
    val endDate: Long,
    /** A list of participants. */
    val participants: List<String>,
)

Providing features using the @AppFunction annotation

Next, the skill wrote the Kotlin functions that perform the database queries and annotate them with @AppFunction. We can view this in searchTrip:

/**
 * Looks for trips based on optional filters like id, title (name), location, and dates.
 *
 * @param id The unique identifier of the trip.
 * @param title The title or name of the trip.
 * @param location The destination location.
 * @param startDate The minimum start date in milliseconds.
 * @param endDate The maximum end date in milliseconds.
 * @return A list of trips matching the filters.
 */
@AppFunction(isDescribedByKDoc = true)
suspend fun searchTrip(
    id: String? = null,
    title: String? = null,
    location: String? = null,
    startDate: Long? = null,
    endDate: Long? = null
): List<TripSerializable> {
    return withContext(Dispatchers.IO) {
    // implementation
}

Since AppFunctions run on the UI thread by default, we use withContext(Dispatchers.IO) to switch to a background dispatcher. Additionally, we refine our KDoc to use clear, imperative verbs and specify parameter constraints. This documentation compiles directly into the tool's schema, which the privileged agent uses to resolve parameters and handle runtime errors.

The service entry point and Hilt integration

To register these features with the intelligence system, we create an abstract base class that extends AppFunctionService. We annotate it with @AppFunctionServiceEntryPoint:

@RequiresApi(36)
@AndroidEntryPoint
@AppFunctionServiceEntryPoint(
    serviceName = "JetPackerAppFunctionService",
    appFunctionXmlFileName = "jetpacker_app_function_service"
)
abstract class BaseJetPackerAppFunctionService : AppFunctionService() {
    @Inject internal lateinit var tripDao: TripDao
    // DAOs and database references are injected here...
}

During compilation, KSP generates the final concrete service subclass, JetPackerAppFunctionService, as declared with the serviceName parameter. We also register app_metadata.xml in the app's manifest. This file provides global operational rules for JetPacker's declared AppFunctions.

Testing and verifying your AppFunctions

Once implemented, you should verify that your AppFunctions are registered and working correctly.

Running devices or emulators with Android 17 or newer, you can use ADB commands from your terminal to list and invoke your functions. Running adb shell cmd app_function list-app-functions displays all registered functions for your package. You can then execute a specific function and test its database integration by running adb shell cmd app_function execute-app-function while passing a raw JSON parameters string.

Instead of these ADB commands, you can also use the AppFunctions Testing Agent to inspect your configuration, list and execute AppFunctions, and even see how your AppFunctions behave in a real conversational flow.

Wrapping it up

When thinking about app features that can be contributed to the intelligence system using AppFunctions requires a slight shift in how we think about code and documentation. AppFunctions enable you to use this new interaction model for apps, which allows using an agent to access app features..

First, the AppFunctions development skill is an essential lifecycle tool, helping you discover features, implement and refine AppFunctions for your apps. Second, KDoc comments are a compiled API asset; clear parameter descriptions directly impact the execution accuracy of the system agent. Finally, Android MCP provides local-first execution allowing apps to safely collaborate with AI agents.

Contributing app features through AppFunctions makes your application ready for the intelligence system. Let us know how you are adapting your apps for the agentic era!

Learn more

Check out the other parts of this blog post series:
Part 1: Introduction of the app and a high-level overview.
Part 2: On-device intelligence. Deep-dive into ML Kit's GenAI APIs and Gemini Nano to build privacy-first features like itinerary summarization, receipt parsing, and local audio processing.
Part 3: Hybrid and cloud reasoning. Explore how to use Firebase AI Logic to ground LLM answers in real-world data like Google Maps and web context.
Part 4 (this post!): System integration. Integrating with the Android intelligence system using AppFunctions.
Part 5 (coming soon): In-app agentic workflows. Extend the app with an end-to-end booking assistant powered by A2UI and ADK.

Interested in more on Android Development? Follow Android Developers on YouTube or LinkedIn!

All code snippets in this blog post follow the following copyright notice:

Copyright 2026 Google LLC.
SPDX-License-Identifier: Apache-2.0

21 Jul 2026 1:00pm GMT

Build intelligent Android apps: Cloud and hybrid inference

Posted by Thomas Ezan, Jolanda Verhoef, Caren Chang, Senior Developer Relations Engineers, Android Developer Relations



Welcome back to the blog post series "Build intelligent Android apps" where we take a basic Android app and transform it into a personalized, intelligent, and agentic experience. In our previous post we explored how to build intelligent on-device features using Gemini Nano through ML Kit's Prompt API.

In this post, we will look at how you can leverage Firebase AI Logic to build cloud-hosted and hybrid AI features:


Sometimes a use case requires AI models with greater world knowledge, a much larger context window, or the ability to handle complex queries. In those scenarios, we can leverage cloud models.

Other times, you want the best of both worlds: using hybrid inference to run on-device when available to lower costs, while falling back to the cloud to ensure compatibility for all devices.


Cloud and hybrid features in Jetpacker: Museum assistant with web grounding, hybrid restaurant review drafting, and support chat featuring custom-routed live translation.

Let's look at how we implemented three cloud and hybrid features in Jetpacker:

Use LLM grounding for up-to-date informationMuseum assistant chatbot with LLM grounding

The Museum assistant is an interactive chatbot designed to help users plan their museum visits. It provides visitors with up-to-date details regarding specific exhibits, current opening hours, ticket pricing, and more.


Museum assistant is a chatbot that answers questions, such as
'How can I get a ticket discount for Le Louvre?'

When building AI features, getting the model to answer with fresh, accurate, and specific real-world information is a common challenge. While cloud models possess massive amounts of world knowledge, they might not know about seasonal exhibits or the current day's opening hours.



Grounding data is added to the context window to enable the model
to answer questions correctly and accurately.

To bridge this gap, we can use grounding techniques to add extra context to the model's context window. The Firebase AI Logic SDK supports three types of grounding:

In Jetpacker, we dynamically construct the available tools based on enabled feature flags and initialize the generative model using the Firebase AI SDK:

// implementation("com.google.firebase:firebase-ai-logic")

private var toolList = mutableListOf<Tool>()

init {
    if (ENABLE_SEARCH_GROUNDING) {
        toolList.add(Tool.googleSearch())
    }
    if (ENABLE_URL_GROUNDING) {
        toolList.add(Tool.urlContext())
    }
}

private val generativeModel = Firebase.ai(backend = GenerativeBackend.googleAI())
    .generativeModel(
        modelName = "gemini-3-flash",
        systemInstruction = content {
            text("You are a helpful museum assistant answering questions about a museum. Use plain text.")
        },
        tools = toolList
    )

When the user queries the assistant, if URL grounding is enabled, we append the specific museum resource URLs directly into the prompt:

val groundingText = if (FeatureFlags.ENABLE_URL_GROUNDING) {
    "\n If the following message above is about the rules and terms to visit Le Louvre, " +
    "if needed answer this urls ${urlList.joinToString()}"
} else {
    ""
}

val prompt = "$text $groundingText"

var response = chat.sendMessage(prompt)

Hybrid inference: On-device review generation with Maps deep link

Not every AI task requires a cloud-based model, and not every device is online. To help developers balance latency, cost, and offline availability, we recently introduced the Firebase API for Hybrid Inference.

In Jetpacker, the restaurant review feature lets users review select topics and automatically drafts a review. To enable this for all users, we prioritize local execution with Gemini Nano, and fall back to cloud models on devices that don't support Gemini Nano.


The restaurant review feature uses hybrid inference to draft a review based on topics

// implementation("com.google.firebase:firebase-ai-logic")
// implementation("com.google.firebase:firebase-ai-ondevice:16.0.0-beta03")


// Initialize the model with hybrid routing configuration
val reviewModel = Firebase.ai.generativeModel(
    modelName = "gemini-3.1-flash-lite",
    onDeviceConfig = OnDeviceConfig(
        inferenceMode = InferenceMode.PREFER_ON_DEVICE
    )
)

The Hybrid Inference API supports four distinct routing modes:

Once the review is generated, we copy it to the clipboard and use an intent to open Google Maps directly to the restaurant's review page, providing a seamless user experience:

private fun copyAndOpenMapsReview(context: Context, reviewText: String, placeId: String) {
    val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
    val clip = ClipData.newPlainText("User Review", reviewText)
    clipboard.setPrimaryClip(clip)

    val uri = Uri.parse("https://search.google.com/local/writereview/mobile?placeid=$placeId")
    val intent = Intent(Intent.ACTION_VIEW, uri).apply {
        setPackage("com.google.android.apps.maps")
    }
    context.startActivity(intent)
}

Custom hybrid routing: Hotel support chat translation with simulated personas

The hotel support chat was built to let users finalize logistics and check on hotel details. This feature uses system instructions to configure a localized receptionist assistant. By passing specific information-such as the preferred language and hotel information-in the instructions, we can set up a conversational persona representing a specific hotel.

private val generativeModel = Firebase.ai(backend = GenerativeBackend.googleAI())
    .generativeModel(
        systemInstruction = content {
            text("""
              You are a helpful hotel receptionist at $hotelName only speaking $language. 
              Answer politely in $language. The bar closes at 10pm and breakfast is from 7am to 10am.
              There's someone at the desk 24/7. You can retrieve your luggage from the storage room 
              at the back of the lobby at any time.
              """)
        },
        modelName = "gemini-3-flash-preview"
    )

Because receptionist responses are in the hotel's local language (for example, French for Hotel Le Meurice in Paris), we need to translate messages to the user's preferred language.


Hotel support chat messages are automatically translated to the user's preferred language

While hybrid models can configure simple routing preferences, complex scenarios require custom routing logic. In Jetpacker, we implement a custom routing stack that takes into account:

// implementation("com.google.android.gms:play-services-mlkit-language-id:17.0.0") 

// ML Kit for Language Identification (powered by Google Play Services)
private val languageIdentifier = LanguageIdentification.getClient()

// On-device translator model (prefer Gemini Nano) for translating common language pairs
private val hybridTranslationModel = Firebase.ai(backend = GenerativeBackend.googleAI())
    .generativeModel(
        modelName = "gemini-3-flash",
        onDeviceConfig = OnDeviceConfig(mode = InferenceMode.PREFER_ON_DEVICE)
    )

// Cloud translator model for more complex language pairs
private val cloudTranslationModel = Firebase.ai(backend = GenerativeBackend.googleAI())
    .generativeModel(
        modelName = "gemini-3-flash"
    )

When a message needs to be translated, we identify the source language and apply our custom routing logic, executing either on-device or cloud translation:

fun translateMessage(message: SupportChatMessage) {
    viewModelScope.launch {
        // 1. Detect language using ML Kit Language Identification
        val sourceLang = try {
            Tasks.await(languageIdentifier.identifyLanguage(message.text))
        } catch (e: Exception) {
            "Undefined"
        }

        // 2. Custom routing: we've verified the translation quality for English and Korean with Gemini Nano, and will translate message on-device for those two languages
        val routeToCloud = sourceLang != "en" && sourceLang != "kr"

        val prompt = "Translate the following text to $selectedLanguage. Just return the translated sentence: ${message.text}."

        val (translatedText, routePrefix) = if (routeToCloud) {
            val result = cloudTranslationModel.generateContent(prompt)
            result.text to "[Cloud]"
        } else {
            val result = hybridTranslationModel.generateContent(prompt)
            result.text to "[On-Device]"
        }

        if (translatedText != null) {
            _translations.update { current ->
                current + (message.id to "$routePrefix: $translatedText")
            }
        }
    }
}

In this example, the custom routing logic only takes into consideration the translation's source and target language. However, based on your app's use case, you can expand the routing logic to include other factors such as the on-device model version, network connectivity, battery status, and more.

Securing the AI Pipelines: Firebase App Check

Lastly, using AI in the cloud opens up possibilities of API key abuse or unauthorized billing. To secure API calls, we integrated Firebase App Check using both Play Integrity (production) and the local Debug Provider (for local development or emulators).

In the JetPackerApplication.kt file, we install the debug provider at startup and trigger anonymous authentication to establish a secure user session:

//  implementation("com.google.firebase:firebase-appcheck-playintegrity") 
//  implementation("com.google.firebase:firebase-appcheck-debug")  
//  implementation("com.google.firebase:firebase-auth") 

override fun onCreate() {
    super.onCreate()
    Firebase.initialize(context = this)
    Firebase.appCheck.installAppCheckProviderFactory(
        DebugAppCheckProviderFactory.getInstance()
    )
    Firebase.auth.signInAnonymously()
}

When building locally on an emulator, App Check prints a local token secret to logcat:

Enter this debug secret into the allow list in the Firebase Console: a8c2dd4c-xxxx-xxxx-xxxx-ef6c114ba27e

Once registered in the Firebase console, local requests are fully verified and authenticated by App Check, protecting our backend while letting us test the app locally.

Conclusion

By combining cloud model capabilities (grounding, system instructions) with on-device capabilities (hybrid routing, translation, security app checks), we created a travel app that is smart, secure, and available offline.

Check out the full source code for Jetpacker on GitHub, and explore the Firebase documentation to get started:

Firebase AI Logic Documentation
Firebase Hybrid Inference API

Learn more

Check out the other parts of this blog post series:

Part 1: Introduction of the app and a high-level overview.
Part 2: On-device intelligence. Deep-dive into ML Kit's GenAI APIs and Gemini Nano to build privacy-first features like itinerary summarization, receipt parsing, and local audio processing.
Part 3 (this post!): Hybrid and cloud reasoning. Explore how to use Firebase AI Logic to ground LLM answers in real-world data like Google Maps and web context.
Part 4: System integration. Integrating with the Android intelligence system using AppFunctions.
Part 5 (coming soon): In-app agentic workflows. Extend the app with an end-to-end booking assistant powered by A2UI and ADK.

Interested in more on Android Development? Follow Android Developers on YouTube or LinkedIn!

All code snippets in this blog post follow the following copyright notice:

Copyright 2026 Google LLC.
SPDX-License-Identifier: Apache-2.0

21 Jul 2026 1:00pm GMT

20 Jul 2026

feedAndroid Developers Blog

Upcoming Changes to the Nearby Connections API

Posted by Wei Wang, Engineering Manager, Android BeTo

User privacy and transparency are core to the Android experience. To better align with these principles, we are updating the default behavior of the Nearby Connections API regarding how it interacts with device radios.

What is changing?

Previously, the Nearby Connections API could automatically toggle Wi-Fi and Bluetooth radios ON to facilitate connections without explicit user intervention. Moving forward, the API will no longer automatically enable these radios for 1P and 3P applications.

What this means for developers

If your app relies on Nearby Connections, you will need to update your implementation to account for these changes:

Timing

These changes are scheduled to take effect in late 2026. We recommend reviewing your connection workflows now to ensure a seamless transition for your users.

20 Jul 2026 1:00pm GMT

14 Jul 2026

feedAndroid Developers Blog

Android Studio Quail 2 is Stable: Multi-task with the Android Studio AI agent

Posted by Amman Asfaw, Product Manager, Android Studio





Android Studio Quail 2 is now stable and ready for you to use in production, bringing a shift to your IDE with concurrent agentic workflows, natively integrated memory leak profiling, and context-aware crash remediation. Whether you are performing a sweeping architectural overhaul, tracing a memory leak, or resolving a critical production crash, Android Studio keeps you anchored in your workspace by reducing manual friction.

Here's a deep dive into what's new:

Multi-tasking with parallel chats

In Android Studio Quail 2, we've been hard at work redesigning Agent Mode from the ground up. This new architecture provides better performance, offers more flexibility for decomposing complex tasks, and improves the suite of internal tools the agent uses to do its work.

In addition to these behind-the-scenes improvements, these changes also allow you to converse across multiple agent chats simultaneously. Waiting for the Android Studio agent to finish a task before you can ask another question or initiate a separate task in Agent Mode is a bottleneck of the past. You can multi-task seamlessly: kick off a UI refactor in one tab, fix a ProGuard rule in a second, and generate documentation in a third.

You can also change which models the agent uses from chat to chat based on the requests you have. Take a look at Android Bench for an analysis of how LLMs perform Android development tasks.

Run multiple agent tasks in parallel with different models of your choice.

Use the History icon to navigate between active tasks.

Memory leak detection with LeakCanary

Memory leaks in Android occur when your code holds onto an object's reference long after its life cycle has ended. This prevents the Garbage Collector from reclaiming that memory, eventually leading to sluggish performance or OutOfMemoryError.

Hunting down memory leaks can be a tedious, manual task. Starting with Android Studio Quail 2, the popular open-source leak detector LeakCanary is natively integrated directly into the Profiler as a dedicated, first-class task.

This integration transforms your debugging performance by lifting and shifting the heap analysis off your resource-constrained testing phone, and onto your powerful development computer. By running the analysis on your computer, leak tracing is up to five times faster and jank-free, leaving your test app running smoothly on the device.

Once a leak is detected during a profiling session:

Review memory leaks identified via LeakCanary through the Fix with Agent button.

App Quality Insights agent integration

Tracking down the root cause of an app crash can require manually synthesizing stack traces, device data, and source code. However Android Studio's App Quality Insights (AQI) is now fully integrated with Agent Mode to do the heavy lifting for you.

When you click on a crash in the AQI panel, you immediately get a concise, high-level summary of the issue. If you need to dig deeper, simply click See more. This opens a dedicated chat where the agent uses your selected model and pulls in local source code and the full stack trace to deliver a comprehensive explanation of the failure.

With the new agent integration, you move directly from issue identification to resolution. By clicking Fix with AI, the agent will analyze the issue, propose a step-by-step fix plan, and-upon your approval-apply the necessary code changes directly to your project and verify the resulting fix

The Fix with AI button triggering the agent to analyze the issue, then propose the fix

Quality & stability improvements

Beyond new features, we've continued our focus on quality by addressing numerous bugs and incorporating the latest stability and performance improvements from the IntelliJ platform, making this a significant enhancement for your daily development.

Get Started

Ready to dive in and accelerate your development? Download Android Studio Quail 2 and start exploring these new features today! As always, your feedback is crucial to us. Check known issues, report bugs, and be part of our vibrant community on LinkedIn, Medium, YouTube, or X.

14 Jul 2026 11:00am GMT

08 Jul 2026

feedAndroid Developers Blog

Evolving how LLMs are measured for Android: the next era of Android Bench

Posted by Zoe Lopez-Latorre, Senior Developer Relations Engineer, Android



Back in March, we introduced Android Bench-our LLM leaderboard for real-world Android development tasks. Our goal was to provide transparency around model capabilities in Android development and to encourage model improvements, to give you more helpful AI options for your everyday workflow. Since then, we have enhanced the benchmark based on your feedback, including evaluating open-weight models and adding cost and efficiency dimensions to the leaderboard.

But AI capabilities are ever-evolving, and measurement needs to follow suit. As part of our July release, we have adopted the Harbor framework, which includes an updated version of the benchmarking agent used to evaluate models.

Along with this change to our evaluation, in this July release we're adding 8 new models (Claude Fable 5, Claude Sonnet 5, Claude Opus 4.8, GLM 5.2, Kimi K2.7 Code, MiniMax M3, Qwen 3.7 Plus and Qwen 3.7 Max) to the leaderboard. We're also sharing opportunities for you, the Android developer community, to contribute to the benchmark.

Upgrading our methodology with the Harbor framework

When we designed Android Bench, we anchored our methodology on leading industry standards available at the time. We used mini-swe-agent v1, a general-purpose benchmarking agent, and adapted it to the nuances of Android development to provide a baseline measurement for the capabilities of models for common Android development tasks.

To continue providing you with state-of-the-art evaluations that accurately measure the latest model capabilities on Android development, we are standardizing our benchmark to the Harbor framework. Harbor defines standards and integrations that make it easy for anyone to run the benchmark, evaluate their preferred set-up, or share results - providing you with additional transparency and visibility.

This upgrade enables us to more rigorously evaluate models and their capabilities, and we re-ran the benchmark on all models to establish an updated baseline. This means there is a minor shift in scoring, but you will still be able to view historical scores within the archive on our website.

We want to ensure Android Bench is helpful for you, so we will continuously update it as our evaluations and the industry mature.

Expanding the leaderboard with 8 new models

As part of our commitment to keeping the leaderboard fresh, we have added Claude Fable 5, Claude Sonnet 5, Claude Opus 4.8, GLM 5.2, Kimi K2.7 Code, MiniMax M3, Qwen 3.7 Plus and Qwen 3.7 Max to the Android Bench leaderboard.

You will see that Claude Fable 5 is at the top of the leaderboard with a score of 84.5, followed by GPT 5.5 with 80.2, with Claude Sonnet 5 in 3rd with a score of 76.2.

When just comparing Open-weight models, GLM 5.2 is at the top with 72.2, followed by Kimi K2.7 Code with a score of 70.4.

You can check out model performance and efficiency metrics on the updated leaderboard to see how these new and previous models navigate Android-specific challenges like Jetpack Compose migrations, wearable networking, and platform API updates.

Opening Android Bench to community contributions

From the beginning, we've valued an open and transparent approach, which is why we made our original methodology and test harness publicly available on GitHub. You've asked for a way to provide feedback on our dataset, so now we're taking collaboration a step further by giving you, the Android developer community, a chance to shape Android Bench.

Starting today, you can contribute to Android Bench in two ways:

We will be reviewing the submitted tasks and will be assessing if they get added to the benchmark. We hope to build a benchmark that truly reflects the diverse, day-to-day realities of the global Android developer community.

Looking ahead

With more and more options for agentic development, maintaining a cutting-edge benchmark ensures that the AI assistance you rely on keeps getting smarter, more helpful, and more effective. Head over to our GitHub repository to check out the tasks. We invite you to submit a task to our team for review, and you can check out Harbor Hub to explore the dataset or submit evaluations.

As always, you can find the updated leaderboard, or read the methodology on our website.

Android Bench, LLM leaderboard, Harbor framework, Android development, Claude Fable 5, GPT 5.5, Claude Sonnet 5, GLM 5.2, Kimi K2.7 Code, MiniMax M3, Qwen 3.7 Plus, Qwen 3.7 Max, AI benchmarking, Jetpack Compose migration, wearable networking, mobile AI agent, Zoe Lopez-Latorre, model evaluation, open-weight models, developer community contributions.

08 Jul 2026 1:00pm GMT

06 Jul 2026

feedAndroid Developers Blog

Google Play launches the first Indie Games Fund in Africa

Posted by Steph Pio, Strategic Partnerships Manager, Google Play EMEA



Sub-Saharan Africa is home to some of the world's most creative storytelling. To help bring those stories to a global audience, today, we're proud to announce the debut of Google Play's Indie Games Fund in Africa.

The region's unique creativity has fueled a vibrant game development scene, helping drive what is quickly becoming one of the most exciting, resilient, and fast-growing gaming markets. It's a space defined by immense talent. However, access to capital is a persistent hurdle, and a significant investment gap often holds back incredibly promising local studios.

With this inaugural fund, we're committing $1 million USD to help address that gap. This fund will empower 10 indie game studios across Sub-Saharan Africa to scale their businesses and realize their full potential.

Funding and support for selected studios

This program is designed to drive long-term growth, where it can make the biggest impact. Selected studios will receive a share of the $1 million fund, with individual investments ranging from $50,000 to $200,000 to help elevate their games. Alongside this financial backing, recipients will benefit from dedicated mentorship and hands-on technical support. Together, these awards are designed to help them scale their businesses and reach a global audience.

Who can apply?

The program is open to indie game developers based in Sub-Saharan Africa (see the list of eligible countries) who have launched a game-whether it's on Google Play, another mobile platform, PC, or console.

Review the eligibility criteria and apply now. Applications close at 12 noon UTC on July 31, 2026.

06 Jul 2026 1:00pm GMT

29 Jun 2026

feedAndroid Developers Blog

Eclipsa Video: HDR That Looks Right on Every Screen

Posted by Tibian Elsheikh, Product Manager, Android Core Graphics and Jeffrey Jose, Product Manager, Android Core Graphics



We've all been there: You're scrolling through your favorite social media feed in a dim room, and suddenly an HDR video pops up. It's so intensely bright that you have to squint, or maybe you find yourself turning down your screen brightness just to read the caption. Other times, a video that looks vibrant on your phone looks flat, dark, or washed out when you watch it on your living room TV.

While High Dynamic Range (HDR) technology was designed to make videos look richer and more lifelike, the lack of unified industry guidelines means that the exact same clip can render in unexpected and jarring ways depending on the display you're using.

To solve this, we're introducing Eclipsa Video-a new standard built to make your favorite videos look consistent, balanced, and comfortable on every screen. Eclipsa Video builds on the open SMPTE ST 2094-50 specification, which Google developed in collaboration with Apple and NBCUniversal.


Sudden brightness spikes during feed scrolling-fixed with Eclipsa Video.

More consistency, comfort, and creative control

Eclipsa Video moves past individual display guesswork. Instead of leaving it up to your device to interpret a video's brightness on its own, our format carries precise guidelines that tell compatible displays exactly how to render the image.

Designed to scale with your hardware, Eclipsa Video provides three core benefits:


Eclipsa Video preserves true highlight detail on any screen you watch.

Built natively into Android 17

Starting with Android 17, support for Eclipsa Video is built directly into the platform. This means a more comfortable, true-to-life HDR experience is coming natively to the phones, tablets, and TVs you rely on every day. The video you capture carries its creative intent with it, and the video you watch is shown exactly the way it was meant to be seen.

Guidelines for developers & creators

We're inviting the developer and creator ecosystem to help build a more reliable HDR environment:

What's next

Eclipsa Video is rolling out now, and you'll see more apps and devices supporting it over time. Because it's an open standard, any app developer or hardware manufacturer can integrate it to elevate the viewing experience.

Try out the new tools in Android 17, explore the open-source metadata, and let us know what you think on our developer channels. We can't wait to see what you create.

Notes & Availability

1. Device Compatibility: Eclipsa Video playback and capture are supported natively on devices running Android 17 (API level 37) and above with HDR displays passing Eclipsa Compliance tests.

2. Developer Resources: The SMPTE ST 2094-50 Specification is openly accessible for technical evaluation.

29 Jun 2026 8:00pm GMT

24 Jun 2026

feedAndroid Developers Blog

Expanded billing choice and lower fees on Google Play

Posted by Paul Feng, Vice President, Google Play Eng, Product, UX



At Google Play, we are committed to delivering the best possible experience to users, while ensuring developers have the tools and adaptability to succeed. Guided by this commitment, earlier this year we announced updates to our business model introducing more billing flexibility, lower fees, and new programs to help your business thrive.

With some of these changes rolling out soon, the breakdown below outlines what is coming, where to find more information, key dates, and how to get started.

More billing flexibility

Google Play's billing system safely, efficiently, and intuitively handles the complexities of taxes, compliance, and subscriptions across 195+ markets with 300+ local payment methods. However, we understand there are situations where your business needs more flexibility, and that's why we're offering you more options in how you handle digital commerce.




Building from existing programs, the new billing choice program is available to all developers globally who provide digital services or content to users within the United Kingdom and the European Economic Area, alongside programs in the United States. Following this initial phase, we will continue expanding availability to additional markets. You will find the global release schedule at the bottom of this post.

Through these programs, developers can offer an alternative billing system or link users to their own website for purchases, alongside Google Play's billing. You may also design your own choice screen in accordance with our UX guidelines, as an alternative to Google Play's default version.

Please find all the details in the program page here.

Lower, separate fees

To enable this new level of flexibility, we're separating our service fee from the billing fee. This starts on June 30, 2026, beginning with the United States, European Economic Area, and United Kingdom.

Regardless of whether you use Google Play's billing system, alternative billing, or external web links, the service fee starts at 10% on your first $1M (USD) in annual earnings. This 10% service fee also applies to all auto-renewing subscriptions. For all other transactions, the rates in the table below applies:




For other transactions, the service fee will be determined by whether the transacting user's install is new or existing relative to the regional rollout date:

  • New installs: A transaction from a user whose first-time install or first update of the app from Google Play occurred on or after the date that the new fee structure launched in their region.
  • Existing installs: A transaction from a user whose first-time install or first update of the app from Google Play occurred before the date that the new fee structure launches in their market.

For transactions that use Google Play's billing system, an additional billing fee applies. In the United States, United Kingdom, and the European Economic Area, the billing fee is set at 5%. We'll announce billing fee details for other markets soon. For transactions processed via alternative billing or external web links, the billing fee does not apply.

Review this Help Center article to understand how these rates apply to your business.

Games Level Up and Apps Experience program guidelines

We are also excited to announce even more opportunities for partners who deliver exceptional user experiences across the Android ecosystem: the revamped Games Level Up and the new Apps Experience program. Detailed guidelines are now available on the respective program websites.

Apps and games that meet all requirements are eligible for a new program rate card with reduced rates. See the table below for details:

Visit the Games Level Up and Apps Experience program websites, review the guidelines, and start preparing your games and apps ahead of September 30, 2026, when the program rate cards officially become available.

Global release schedule

Evolving our business model requires technical infrastructure and alignment with local regulations, so these updates will roll out on a staggered timeline. To help you plan, here is the previously announced release schedule for each update across all markets:

Here is a quick recap of the resources available to help you get started:

We look forward to building the next generation of Google Play experiences together.

24 Jun 2026 2:00pm GMT

18 Jun 2026

feedAndroid Developers Blog

Android developer verification: Building a safer ecosystem together

Posted by Matthew Forsythe, Director Product Management, Android App Safety






July 15, 2026: Updated Play Console requirements for Play developers

To meet Android developer verification and updated Play Console Requirements, Play developers must register their Play apps in Play Console. While 99% of apps on Play have been registered automatically, you should check your Play Console Home page to register any remaining apps by September 30, 2026 to avoid global removal from Google Play and ensure a seamless user installation experience.


You can also use Play Console to register apps you distribute outside of Google Play to ensure they can be installed on certified Android devices.


Last year, we introduced Android developer verification to strengthen ecosystem security and stop malicious actors from hiding behind anonymity to release harmful apps. Millions of apps have been registered since the verification launched in March, covering nearly all installs on Google Play and a large majority of installs from outside of Google Play. We appreciate the feedback and partnership from industry leaders, developers, and Android communities that helped us design this experience and drive strong adoption.

Initial launch across seven stores and four countries

These new developer verification protections will take effect on September 30, 2026, starting with users in Brazil, Indonesia, Singapore, and Thailand.

This rollout is an industry-wide effort to create a safer ecosystem. We will begin by verifying app installations from the following stores:

  • Google (Google Play)
  • Honor (HONOR App Market)
  • OPlus (OPPO App Market)
  • Samsung (Galaxy Store)
  • Transsion (Palm Store)
  • vivo (V-Appstore)
  • Xiaomi (GetApps)

Following this initial phase with our partners, we will expand these protections globally for all apps on certified Android devices in 2027.

Automate your workflow with new APIs

To further streamline app registration, we are launching a suite of developer-requested APIs to help you register apps in bulk or directly through your continuous integration and deployment (CI/CD) pipelines. The Android Developer ID Status API will let you check if a package name has already been registered, and the Android Developer Console API will let you register and manage package names directly within your development environment. Both APIs also support OAuth delegation, allowing third-party platforms, like Android app stores, to perform these operations natively on your behalf.

We'll launch these APIs over the next few months.

What's next

  • June 2026: Starting this month, we are rolling out a new system service that will be automatically installed on most Android devices. This service will be used later this year to verify developer registration.
  • July 2026: We'll launch the Android Developer ID Status API globally and begin early access for the Android Developer Console API. Early access also starts for limited distribution accounts on Android Developer Console. This new type of Android developer account is designed for students, hobbyists, and learners and lets you share your apps to up to 20 devices without a government-issued ID or a fee.
  • August 2026: Limited distribution accounts and the new Android Developer Console API will launch globally. We'll also launch an advanced flow for installing apps from unverified developers, which includes security checkpoints to resist coercion scams, while allowing power users to maintain the ability to sideload apps from unverified developers.
  • September 30, 2026: App registration becomes required for participating stores in Brazil, Indonesia, Singapore, and Thailand. Unregistered apps can be sideloaded with Android Debug Bridge (adb) or advanced flow.
  • 2027 and beyond: After incorporating the feedback from our partners, users, and developer community, we'll expand the Android verification requirement globally.


Get started with Android developer verification

If you distribute apps in Brazil, Indonesia, Singapore, or Thailand via the stores listed above, please ensure your verification is complete by the September deadline.

  • Google Play developers: Most Play developers are already verified, and over 99% of their apps have been registered. Go to your Play Console Home page to see your app's verification status, and register apps you want to continue distributing that weren't automatically registered.
  • Developers who distribute only outside of Google Play: Sign up for the Android Developer Console today to register your apps.
  • Students and hobbyists: Sign up here for early access to limited distribution accounts to help us refine the feature with your feedback.
Thank you for helping us build a safer Android ecosystem. Stay tuned for more updates as we approach September and the 2027 global rollout.

18 Jun 2026 2:00pm GMT

17 Jun 2026

feedAndroid Developers Blog

Building a Mixed-Reality Tour Guide with Android XR, the Geospatial API, and Gemini

Posted by Coco Fatus, UX Designer, Alon Hetzroni, UX Engineer, Azin Mehrnoosh, Product Manager Android XR






At this year's Google I/O, we announced an update for spatial experiences: the Geospatial API is now available as a preview in ARCore for Jetpack XR. By bringing Google's Visual Positioning System (VPS) to Android XR, Android XR enables anchoring digital content to the physical world with sub-meter accuracy and precise orientation in supported areas.* To explore what the Geospatial API could unlock, our team built a demo: the XR Geospatial Tour.

Imagine walking into a new city, putting on a pair of wired XR glasses (like the upcoming XREAL Project Aura), and instantly having a knowledgeable, local guide showing you around. You don't need to stare down at a 2D map-instead, 3D models gently guide your path, and an intelligent voice tells you about the historical landmarks right in front of you. We combined the Geospatial APIs, Gemini API using Firebase AI Logic, Google Maps Grounding, and Jetpack XR SDK to create a hands-free, immersive walking tour experience.

*Disclaimer: Video and Tour Guide application are for demonstration purposes only. Some sequences have been shortened. Any hardware depicted may be under development; final product details may differ.

Let's walk through the implementation details and show how we tied these APIs together to build a world-scale spatial experience.

1. Pinpointing the User with ARCore Geospatial API (VPS)

Enhance your navigation experience on XR by combining the power of GPS with the precision of VPS. The accuracy and precise orientation that comes with VPS allows 3D waypoints to align with the physical world.

This is why the Geospatial API on Android XR can help you build custom experiences. By using advanced computer vision, VPS tries to provide a GeospatialPose (including latitude, longitude, and heading) that is more accurate than GPS.

Here's how we retrieve the user's Geospatial pose by mapping the device's orientation to a Geospatial coordinate:

// Retrieve the current geospatial pose from the ARCore session
val result = geospatial.createGeospatialPoseFromPose(arDevice.state.value.devicePose)
if (result is CreateGeospatialPoseFromPoseSuccess) {
val pose = result.pose
Log.d("VPS", "Accurate Location: ${pose.latitude}, ${pose.longitude}")
}

Because the entire experience relies on this accuracy, we monitor the horizontalAccuracy and orientationYawAccuracy until they meet our thresholds. If the user is indoors or in an unrecognized area, we prompt them to "walk to an outdoor public space and look around".

2. Crafting the Itinerary with Gemini API & Google Maps Grounding

Once we have a location, we use the Gemini API using Firebase AI Logic to prompt the Gemini model to act as a local tour guide. We pass the user's coordinates to the model and ask it to output a structured JSON response containing nearby walking tours:

val configForTools = ToolConfig(
functionCallingConfig = null,
retrievalConfig = retrievalConfig {
latLng = FirebaseLatLng(pose.latitude, pose.longitude)
languageCode = "en"
}
)
val responseJsonSchema = Schema.obj(
mapOf(
"locationIntro" to Schema.string(),
"tours" to Schema.array(
Schema.obj(
mapOf(
"title" to Schema.string(),
"description" to Schema.string(),
"stops" to Schema.array(
Schema.obj(
mapOf(
"name" to Schema.string(),
"detailedName" to Schema.string(),
"description" to Schema.string()
)
)
)
)
)
)
)
)
val model = Firebase.ai(backend = GenerativeBackend.googleAI()).generativeModel(
modelName = "gemini-3.5-flash",
tools = listOf(Tool.googleMaps()),
generationConfig = generationConfig {
responseMimeType = "application/json"
responseSchema = responseJsonSchema
}
)
val result = model.generateContent("The user is at latitude ${pose.latitude} and longitude ${pose.longitude}. Generate exactly 3 diverse tours near this location (e.g., historical, food, nature). All tour ideas should be walking distance only.")

Large Language Models are great at generating rich descriptions, but they can sometimes hallucinate exact latitude/longitude coordinates. To solve this, we used Google Maps Grounding to ground the AI.

3. A Voice to Guide You: Gemini 2.5 TTS

To make the tour guide feel truly present, we implemented dynamic voiceovers.

Using the gemini-2.5-flash-tts model, we can configure our model generation config to natively return audio data instead of just text! Here's how you can request the ResponseModality.AUDIO:

val ttsModel = Firebase.ai(backend = GenerativeBackend.googleAI())
.generativeModel(
modelName = "gemini-2.5-flash-tts",
generationConfig = generationConfig {
// Instruct the model to return Audio
responseModalities = listOf(ResponseModality.AUDIO)
}
)
val response = ttsModel.generateContent("Say in a neutral but positive voice:\n$prompt")
// Extract the raw audio bytes from the response
val audioBytes = response.candidates.firstOrNull()?.content?.parts
?.filterIsInstance<InlineDataPart>()
?.firstOrNull { it.mimeType.contains("audio") }?.inlineData

4. Bringing it to Life in 3D with Jetpack XR

The final piece of the puzzle is rendering this data in the user's field of view. The Jetpack XR SDK makes it intuitive to transition from a 2D Android UI to spatial computing.

We used Jetpack Compose for XR to build spatial components. To represent points of interest along the tour, we built a Composable called InfoSphere, which contains a GltfModel of a 3D orb that floats in space and can be interacted with to reveal information.

Using Jetpack XR SDK, we can place 3D models alongside the Compose UI using SpatialBox and SceneCoreEntity. We also used InteractableComponent to respond to user taps.

@Composable
fun InfoSphere(
content: InfoBubbleContent,
session: Session,
sphereModel: GltfModel,
isSelected: Boolean,
onClick: () -> Unit
) {
// SpatialBox lets us arrange 3D components and SpatialPanels together
SpatialBox(
SubspaceModifier
.offset(x = 2.dp, y = 1.dp, z = (-3).dp) // Positioned in 3D space
) {
// Smoothly animate the visibility of our 2D Compose UI Panel
AnimatedSpatialVisibility(visible = isSelected) {
SpatialPanel {
InfoBubble(content) // Regular 2D Compose UI
}
}
// Render our interactive 3D sphere
SceneCoreEntity(
factory = {
GltfModelEntity.create(session, sphereModel).also { entity ->
// Make the 3D model respond to user taps
entity.addComponent(InteractableComponent.create(session) { inputEvent ->
if (inputEvent.action == InputEvent.Action.UP) {
onClick()
}
})
}
}
)
}
}

By combining AnimatedSpatialVisibility for traditional Compose UI surfaces with SceneCoreEntity 3D elements, we're able to seamlessly blend data into the physical world.

Explore what's possible with Android XR today

Building the XR Geospatial Tour app showed us that the barrier to entry for world-scale spatial experiences is lower than ever for Android developers. With the Geospatial API now available in preview on Android XR, your apps can seamlessly understand the physical world around them. By combining Compose for XR's APIs with the high-precision location data of VPS and the generative capabilities of Gemini, we can create experiences that understand both where the user is and what they are looking at.

To help you get hands-on with Android XR, we are thrilled to open applications for the Android XR Developer Catalyst Program, which includes XREAL Project Aura. Starting today, you can apply to get access to an XREAL Project Aura devkit or our display glasses devkit over the coming months!

*Disclaimer: Available on select devices. Internet connection required. Works on compatible apps and surfaces. Results may vary.


17 Jun 2026 5:00pm GMT