Author Archives:

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

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!

Run Ray on TPU, Part 1: The foundations

Ray 2.55 introduces official, first-class support for Google Cloud TPUs, enabling developers to run distributed Python workloads on Google's accelerators using the familiar Ray task-and-actor APIs. To handle the strict networking requirement of keeping multi-host TPU "slices" together over their Inter-Chip Interconnect (ICI), the KubeRay Operator on GKE automatically provisions and labels the underlying hardware layout. Ray Core utilizes these labels via its slice_placement_group() primitive to atomically reserve complete slices, allowing developers to deploy jobs through KubeRay, Ray Train, or Ray Serve simply by declaring a hardware topology (like "4x4") without writing custom placement code.

Import and create combo charts in Google Sheets

Google Sheets now offers enhanced support for combo charts, providing a more seamless experience when creating multi-series visualizations. Users can create new “Combo” chart types, enabling complex dataset visualization with different scales and metrics without requiring manual re-plotting. These include:

  • Clustered Column - Line
  • Clustered Column - Line on Secondary Axis
  • Custom Combo
Sheets combo chart support also comes with enhanced Microsoft Excel import compatibility. Previously, importing external files that contained combo charts with a secondary axis would result in the secondary axis being dropped. This update ensures that secondary axis configurations and combo chart types are preserved during file import.


User creating a combo chart in Google Sheets

Getting started

Rollout pace

Availability

  • Available to all Google Workspace customers and users with personal Google accounts

Resources

Enabling Local Inventory Ads by Default for Shopping Campaigns starting on August 31, 2026

What is changing?

On August 31, 2026, we are aligning Shopping campaigns with Performance Max for Retail campaigns by enabling Local Inventory Ads (LIA) by default. Previously, developers and advertisers had to explicitly set the enable_local field to true within a campaign's ShoppingSetting in order to serve products in their LIA feed.

With this change, the Campaign.ShoppingSetting.enable_local field will no longer have any effect on Shopping campaigns. The Google Ads API backend will automatically override this value to true for all Shopping campaigns, effectively turning on the "Local products" setting behind the scenes.

What you need to do

For v25.1 and future versions, you’ll need to update your code to avoid setting enable_local to false, otherwise you will see a ContextError.OPERATION_NOT_PERMITTED_FOR_CONTEXT error. For any versions prior to v25.1, no immediate code changes are required, and any requests to mutate the enable_local field for a Shopping campaign will treat the value as true.

If you previously relied on setting enable_local to false to prevent local offers from serving in specific Shopping campaigns, you should instead use the CampaignCriterionService to add a listing scope with product_channel set to ONLINE, or use the "Inventory filter" section in the campaign settings UI to filter out local inventory and silo budgets by channel (Online vs. Local).

Note that this change only applies to Shopping campaigns. The enable_local field will continue to function as before for other supported campaign types, such as Performance Max and Demand Gen.

If you have any questions or want to discuss this post, please reach out to us on our “Google Advertising and Measurement Community” Discord server.

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:

  • Manual Radio Management: You must ensure that the necessary radios (Wi-Fi or Bluetooth) are enabled before initiating Nearby Connections tasks.
  • User Notification: If the required radios are disabled, your app must now inform the user and request that they enable them manually. The API will no longer programmatically turn them on for you.

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.

Google Workspace Weekly Recap – July 17, 2026

Google Credential Provider for Windows (GCPW) now supports FIDO2-compliant physical security keys as a second factor for authentication

Google Credential Provider for Windows (GCPW) has been updated to support FIDO2-compliant physical security keys as a second factor for authentication. This update helps organizations improve their security posture by enabling administrators to enforce 2-Step Verification (2SV) using hardware security keys at the Windows login screen. | Learn more.

Improvement to in-room problem reporting for Google Meet hardware

Maintaining an enterprise-grade video conferencing environment requires visibility into the health of its devices. We're introducing new ways to see Google Meet hardware user-reported feedback directly in the Admin console. | Learn more.

New refinement capabilities allow custom editing with Help me write in Gmail

Users can now edit and revise their email drafts in Gmail via the prompt bar, using custom refine instructions in Help me write. Previously the refines were limited to preset options like Polish, Formalize, and Shorten. | Learn more.

Now available: group conversations with external collaborators in Google Chat

For many teams, it’s essential to be able to work in real-time with partners from outside your organization. We’re improving external collaboration in Google Chat by making it possible to create group conversations that include external users. | Learn more.

NotebookLM is now Gemini Notebook

We’re renaming NotebookLM to Gemini Notebook. While it remains a standalone product focused on being your premier research tool, the new name reflects how it will evolve to do more across the Google ecosystem. | Learn more.

Easily control the emotions and pacing of AI avatars and AI voiceovers in Google Vids

Users can now easily steer voiceover and avatar speaking in Google Vids by typing content within brackets like “[excitedly]”. | Learn more.

Expanded language support for Gemini in Google Docs

We are now expanding support for these features to 11 more languages, including Mandarin, Dutch, Malay, Hebrew, Polish, Turkish, Czech, Indonesian, Swedish, Danish, and Norwegian. These new additions join our previously supported languages: English, Spanish, Portuguese, Japanese, French, Korean, German, and Italian. | Learn more.

Generate higher quality AI video clips and edit any video with Gemini Omni in Vids

Users now have access to Gemini Omni directly within Google Vids. Omni provides higher quality video generation with significant improvements over previous models. Additionally, Omni’s world understanding unlocks simple video edits so you can ask Omni to tweak the video you have to get the video you need. | Learn more.

Cast yourself in AI video clips using your personal avatar with Gemini Omni in Vids

Users now have access to Gemini Omni directly within Google Vids. With Gemini Omni, you can create videos using your personal avatar to scale your presence without the studio time. Use a secure verification process to capture your likeness and then select it as a character in Omni generations within Vids. | Learn more.

New Google Meet 'Take notes for me' settings for admins and end users

To help users remember to capture notes for meetings when it’s most valuable, we’re updating the admin and end user settings that let them pre-configure AI note-taking for Google Meet. | Learn more.

The announcements above were published on the Workspace Updates blog over the last week. Please refer to the original blog posts for complete details.

Investing in the Future with the Boys and Girls Club

When asked to describe the impact of gFiber’s partnership with the Boys & Girls Club of Pocatello and Chubbuck in one word, Executive Director Mona Mannan said: "opportunity."

"GFiber is not just funding programming for the kids, it’s actually giving the program the opportunity that these kids and these families wouldn't usually have. [It's] investing in the future of people in Pocatello... we're removing barriers." — Mona Mannan

For local families, this partnership is more than just a summertime activity; it is a dedicated educational space for skill building. Each summer, the Club has provided youth with a safe environment while their parents are at work but, instead of sitting with tablets these elementary students are diving into real-world concepts. From designing electricity boards, building miniature robotics, lava lamps, and planning pathways for toy cars - this STEM curriculum is designed to stimulate screen-free, hands-on critical thinking. 

Thumbnail

"There are hardly any screens, outside of movie day which happens every few weeks," Mannan explained. "It’s all hands-on learning. We want them working with their hands, building, working together in groups, and staying active daily so they don't experience summer learning loss." Summer learning loss refers to knowledge or skills that fade when children are not mentally engaged on a regular basis like they are while at school. At the Boys and Girls Club of Pocatello and Chubbuck, this screen-free intention around learning is to motivate students to build their ideas offline and take their learning into the real world to see what actually works to improve their favorite experiments. Through GFiber’s support the learning experiences happen outside of the Club too, with field trips to Zoo Idaho focusing on biology and the bowling alley for a fun lesson on mass and force.  



The enrichment doesn’t stop when summer ends either, The Boys and Girls Club transitions into an after-school program that follows the District 25 calendar. Students receive homework support during "Power Hour," participate in a brand new expanded music program, and connect with community mentors from the fire department, police department, and Idaho State University student volunteers. The Club also utilizes trauma-informed care training to ensure staff can deeply support children from all backgrounds. This is made possible through strong community alliances and gFiber’s $10,000 annual contribution to the Club. Every dollar donated goes straight back into local operation, programming, and scholarships.

There is an alignment between GFiber’s mission and the Club’s goal of helping youth reach their full potential, as both organizations are dedicated to building a brighter, more connected future. For Mannan, the relationship is built on mutual respect and shared energy, personified by GFiber’s area representative Alberto Garcia, who initiated the partnership. "This has been amazing support for us to grow our program," Mannan shared. "You guys are really an important part of this community."

Chrome Dev for Desktop Update

The Dev channel has been updated to 152.0.7953.3 for Windows, Mac and Linux.

A partial list of changes is available in the Git log. Interested in switching release channels? Find out how. If you find a new issue, please let us know by filing a bug. The community help forum is also a great place to reach out for help or learn about common issues.

Chrome Release Team
Google Chrome