Skip to content

Commit 0ebdfdb

Browse files
authored
Merge pull request #40 from googlemaps-samples/mobile-URE-06172026
feat: Sync from internal staging.
2 parents f61b79e + 159009d commit 0ebdfdb

51 files changed

Lines changed: 4463 additions & 21 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎README.md‎

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
1111
Welcome to the **Maps Agentic UI Toolkit Samples**! 🎉
1212

13-
This repository (`a2ui-samples`) contains reference samples for the Maps Agentic UI Toolkit. It provides a fully working, interactive sample application implementing the Agent-to-User Interface (A2UI) standard, allowing AI agents to present rich, dynamic map interfaces directly in your web browser.
13+
This repository (`a2ui-samples`) contains reference samples for the Maps Agentic UI Toolkit. It provides fully working, interactive sample applications implementing the Agent-to-User Interface (A2UI) standard, allowing AI agents to present rich, dynamic map interfaces directly across Web, Android, and iOS platforms.
1414

1515
This project is intended for demonstration purposes to help you get up and running quickly!
1616

@@ -24,13 +24,20 @@ Here is an overview of how the directory structure looks when set up correctly:
2424
parent-folder/
2525
├── a2ui/ <-- SIBLING REPOSITORY (Core Toolkit)
2626
│ ├── agent/python-agent/ <-- Core Python agent libraries (maui-a2ui-python)
27-
│ └── client/web/ <-- Core web UI component library (@googlemaps/a2ui)
27+
│ └── client/ <-- Core client UI libraries
28+
│ ├── web/ <-- Core Web UI component library (@googlemaps/a2ui)
29+
│ ├── android/ <-- Android View component library (GoogleMapsA2UI)
30+
│ └── ios/ <-- iOS SwiftUI component library (GoogleMapsA2UI)
2831
│
2932
└── a2ui-samples/ <-- THIS REPOSITORY (Quickstart & Demos)
3033
├── agent/python/ <-- Sample backend Python agent server
31-
└── client/web/react/ <-- Sample frontend React web application
34+
└── client/ <-- Sample client applications
35+
├── web/react/ <-- Sample frontend React web application
36+
├── android/ <-- Sample Android application
37+
└── ios/ <-- Sample iOS application
3238
```
3339

40+
3441
Understanding this layout ensures you will feel entirely comfortable linking the backend and frontend components in the quickstart steps below!
3542

3643
## 🚀 Quickstart Guide
@@ -77,6 +84,10 @@ For more information about the environment variables, see the **Google API Key C
7784
`npm` is the standard package manager for JavaScript and TypeScript web applications, used to download frontend libraries and run development servers.
7885
* **Installation:** Download and install Node.js (which includes `npm`) from [https://nodejs.org/](https://nodejs.org/).
7986

87+
#### 4. Mobile Development Tools (Optional for mobile samples)
88+
* **Android**: [Android Studio](https://developer.android.com/studio) to build and run the native Android sample app.
89+
* **iOS**: macOS with [Xcode](https://developer.apple.com/xcode/) to build and run the native iOS sample app.
90+
8091
---
8192

8293
### Step 1: Run the Backend (Python Agent)
@@ -106,7 +117,11 @@ The backend server is powered by Python and runs our sample agent.
106117

107118
---
108119

109-
### Step 2: Run the Frontend (React Client)
120+
### Step 2: Run a Client Application
121+
122+
Once your backend agent is up and running, you can connect to it using any of our sample client platforms.
123+
124+
#### Option A: Web Client (React)
110125

111126
The frontend is a React web application that communicates with the backend agent and renders the interactive UI.
112127

@@ -119,6 +134,25 @@ The frontend is a React web application that communicates with the backend agent
119134
2. **See the demo working live!** 🌟
120135
Open [http://localhost:5173](http://localhost:5173) in your web browser to interact with your fully functioning Agentic UI demo!
121136

137+
138+
#### Option B: Android Client
139+
140+
The Android sample is a native app utilizing Android Views and [GoogleMapsA2UI(Android)](https://github.com/googlemaps/a2ui/tree/main/client/android) to render agent-driven UI.
141+
142+
1. **Open Project**: Open the `client/android` directory in Android Studio.
143+
2. **Run**: Build and run the application. It will automatically connect to your running Python agent at `http://10.0.2.2:10002` (for an emulator) or `http://127.0.0.1:10002` (for a physical device).
144+
145+
For more server configration and other detailed setup, refer to the [Android Sample README](client/android/README.md).
146+
147+
#### Option C: iOS Client
148+
149+
The iOS sample is a native app utilizing SwiftUI and the [GoogleMapsA2UI(iOS)](https://github.com/googlemaps/a2ui/tree/main/client/ios) to render agent-driven UI.
150+
151+
1. **Setup**: Open the `.xcodeproj` file in the `client/ios` directory in Xcode (use a `.xcworkspace` file instead if your project uses one).
152+
2. **Run**: Build and run the app in the simulator. It will automatically connect to your running Python agent at `http://localhost:10002`.
153+
154+
For more server configration and other detailed setup, refer to the [iOS Sample README](client/ios/README.md).
155+
122156
## Google API Keys
123157

124158
### Google Maps API Key

‎client/android/.gitignore‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Built artifacts
2+
bin/
3+
gen/
4+
out/
5+
build/
6+
app/build/
7+
8+
# Gradle
9+
.gradle/
10+
.kotlin/
11+
local.properties
12+
13+
# Android Studio / IntelliJ
14+
.idea/

‎client/android/README.md‎

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# A2UI Android Sample App
2+
3+
## Overview
4+
This directory contains the Android sample application for the Google Maps Agentic UI (A2UI) Toolkit. It demonstrates how to integrate the underlying `GoogleMapsA2UI` Library to render generative AI responses containing interactive map elements and conversational text natively within an Android WebView.
5+
6+
**Compatibility:** This sample app is designed for **A2UI v0.9**. It is not compatible with earlier versions (e.g., v0.8).
7+
8+
## Instructions
9+
10+
### 1. Build and Publish the A2UI SDK Locally
11+
12+
Before building the sample app, you must build the underlying **GoogleMapsA2UI** library (the core A2UI SDK) and publish it to your local Maven repository.
13+
14+
For instructions on how to build and publish the library, please refer to the [A2UI Android README](https://github.com/googlemaps/a2ui/tree/main/client/android/README.md).
15+
16+
### 2. Set API Keys and Gateway URL
17+
18+
Add your API keys and server connection settings to the `local.properties` file in the root `android` directory (e.g., `ai-kit/a2ui-samples/client/android/local.properties`):
19+
20+
```properties
21+
sdk.dir=/Users/YOUR_USERNAME/Library/Android/sdk
22+
MAPS_API_KEY=your_actual_google_maps_api_key_here
23+
GATEWAY_API_KEY=your_actual_gateway_api_key_here
24+
GATEWAY_URL=your_actual_gateway_url_here
25+
```
26+
27+
The build system uses the `secrets-gradle-plugin` to securely inject these values into the app at runtime.
28+
29+
* **`MAPS_API_KEY`**: Obtain a Google Maps API Key from the Google Cloud Console.
30+
* **`GATEWAY_URL`** and **`GATEWAY_API_KEY`**:
31+
* **For Remote Server:** If you have deployed a Remote Server to Google Cloud, set `GATEWAY_URL` to your Cloud Run or API Gateway endpoint. Optionally, set `GATEWAY_API_KEY` if your server uses API key-based authentication.
32+
* **For Local Server:** Set `GATEWAY_URL` to `http://127.0.0.1:10002` (physical device) or `http://10.0.2.2:10002` (emulator).
33+
34+
*(Note: Before building this sample app, ensure you have built and published the `GoogleMapsA2UI` Android Library locally. See [a2ui/client/android/README.md](https://github.com/googlemaps/a2ui/tree/main/client/android/README.md) for instructions).*
35+
36+
### 3. Server Configuration & Connectivity Options
37+
38+
In `app/src/main/java/com/example/maui/MainActivity.kt`, verify the flags match your environment:
39+
40+
#### Server Type (`activeServer`)
41+
* `ServerType.DEMO`: Connects to the `GATEWAY_URL` specified in `local.properties`. Use this for your Remote Server or the local Demo Server.
42+
* `ServerType.VANILLA`: Connects to a standalone Python agent running locally (e.g., `python -m my_agent --port 8000`).
43+
44+
#### Device Type (`deviceType`)
45+
* `DeviceType.PHYSICAL`: Use when testing on real Android devices. *(Note: If using a local Demo Server on a physical device, run `adb reverse tcp:10002 tcp:10002`)*
46+
* `DeviceType.EMULATOR`: Use when testing on emulators.
47+
48+
### 4. Build and Run the App
49+
50+
1. Navigate to the Android sample app directory:
51+
```bash
52+
cd ~/ai-kit/a2ui-samples/client/android
53+
```
54+
2. Build and install the app (Debug version):
55+
```bash
56+
./gradlew :app:installDebug
57+
```
58+
*(For release builds, use `./gradlew :app:installRelease`)*
59+
3. Launch the app on your emulator or connected device:
60+
```bash
61+
adb shell am start -n com.example.maui/.MainActivity
62+
```
63+
64+
### 5. Example Prompts & Canned Responses
65+
66+
To facilitate rapid demonstration and UI testing, the sample app includes a dropdown list of frequently used example prompts.
67+
68+
**Important Behavior Note:**
69+
* **Example Prompts:** Selecting an example prompt from the dropdown menu will load a **local, pre-stored JSON response** (found in `assets/canned_responses`) instead of making a live call to the backend server. This is intended for consistent UI testing and fast demonstrations without LLM latency.
70+
71+
## Troubleshooting
72+
73+
### Debug Keystore Missing
74+
If you receive an error: `Keystore file ... debug.keystore not found`, this means your local Android environment hasn’t generated a default debug key yet.
75+
76+
**Solution:**
77+
* **Option A (Recommended):** Open the project in **Android Studio** and let it perform a Gradle sync. This will automatically generate the keystore.
78+
* **Option B (Manual):** Run the following command to generate one:
79+
```bash
80+
keytool -genkey -v -keystore ~/.android/debug.keystore -storepass android -alias androiddebugkey -keypass android -keyalg RSA -keysize 2048 -validity 10000 -dname "CN=Android Debug,O=Android,C=US"
81+
```

‎client/android/app/build.gradle‎

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
//
2+
// Copyright 2026 Google Inc.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
//
16+
17+
plugins {
18+
id 'com.android.application'
19+
id 'com.google.android.libraries.mapsplatform.secrets-gradle-plugin'
20+
}
21+
22+
android {
23+
namespace 'com.example.maui'
24+
compileSdk 34
25+
26+
defaultConfig {
27+
applicationId "com.example.maui"
28+
minSdk 26
29+
targetSdk 34
30+
versionCode 1
31+
versionName "1.0"
32+
33+
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
34+
}
35+
36+
buildFeatures {
37+
buildConfig true
38+
}
39+
40+
signingConfigs {
41+
debug {
42+
// Use the default debug keystore
43+
storeFile file(System.getProperty("user.home") + "/.android/debug.keystore")
44+
storePassword "android"
45+
keyAlias "androiddebugkey"
46+
keyPassword "android"
47+
}
48+
}
49+
50+
buildTypes {
51+
release {
52+
minifyEnabled true
53+
shrinkResources true
54+
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt')
55+
signingConfig signingConfigs.debug
56+
}
57+
}
58+
compileOptions {
59+
sourceCompatibility JavaVersion.VERSION_17
60+
targetCompatibility JavaVersion.VERSION_17
61+
}
62+
// Configure Java toolchain
63+
java {
64+
toolchain {
65+
languageVersion.set(JavaLanguageVersion.of(17))
66+
}
67+
}
68+
}
69+
70+
kotlin {
71+
compilerOptions {
72+
jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
73+
}
74+
}
75+
76+
dependencies {
77+
implementation 'androidx.tracing:tracing-ktx:1.2.0'
78+
implementation 'androidx.core:core-ktx:1.12.0'
79+
implementation 'androidx.appcompat:appcompat:1.6.1'
80+
implementation 'com.google.android.material:material:1.11.0'
81+
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
82+
implementation 'androidx.recyclerview:recyclerview:1.3.2'
83+
implementation 'com.squareup.okhttp3:okhttp:5.3.2'
84+
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.10.2'
85+
testImplementation 'junit:junit:4.13.2'
86+
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
87+
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
88+
implementation 'com.google.android.libraries.mapsplatform.a2ui:GoogleMapsA2UI:0.1.0'
89+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!--
3+
Copyright 2026 Google Inc.
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
-->
17+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
18+
19+
<uses-permission android:name="android.permission.INTERNET" />
20+
21+
<application
22+
android:allowBackup="true"
23+
android:usesCleartextTraffic="true"
24+
android:icon="@mipmap/ic_launcher"
25+
android:label="@string/app_name"
26+
android:roundIcon="@mipmap/ic_launcher_round"
27+
android:supportsRtl="true"
28+
android:theme="@style/Theme.Maui">
29+
<profileable android:shell="true"/>
30+
<activity
31+
android:name=".MainActivity"
32+
android:exported="true"
33+
android:configChanges="keyboardHidden|orientation|screenSize">
34+
<intent-filter>
35+
<action android:name="android.intent.action.MAIN" />
36+
<category android:name="android.intent.category.LAUNCHER" />
37+
</intent-filter>
38+
</activity>
39+
</application>
40+
41+
</manifest>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"Show me 5 coffee shops near South Lake Union in Seattle": "prompt_1.json",
3+
"Is the Edgewater Hotel in Seattle a good hotel?": "prompt_2.json",
4+
"How long will it take to commute to Google Kirkland office from downtown Redmond during my morning rush hour commute?": "prompt_3.json",
5+
"Show me 5 lunch restaurants with Salads in South Lake Union. Give me directions to the 2nd one (starting from the Google South Lake Union WLK building)": "prompt_4.json",
6+
"Give me a 3 day itinerary for a family of 3 traveling to London": "prompt_5.json"
7+
}

0 commit comments

Comments
 (0)