Map.Default.TryOpenAsync returns false — your app says "no maps app" —
on a phone with Google Maps installed, or a hand-rolled geo: intent dies with
ActivityNotFoundException. Android is not lying about Maps; it is refusing to tell
your app that Maps exists.
Since Android 11 (API 30), an app cannot see which other apps handle an intent unless its
manifest declares the intents it intends to ask about — the package visibility rules. MAUI's
Map.TryOpenAsync, Launcher.CanOpenAsync and any code that resolves an
intent before starting it all get an empty answer, and the honest ones report "nothing handles
this". Add a <queries> block for ACTION_VIEW with the
geo scheme to AndroidManifest.xml. No C# changes.
The error
No exception was thrown in this project — TryOpenAsync simply answered no, and the page said so. The two lines, from Locator.cs and Directions.razor:
// Locator.cs — Google Maps on Android, Apple Maps on iOS, the Maps app on Windows
return await Map.Default.TryOpenAsync(destination.Latitude, destination.Longitude,
new MapLaunchOptions { Name = label, NavigationMode = NavigationMode.Driving });
// Directions.razor — what the user saw when that returned false
_mapsFailed = !await Locator.OpenDirectionsAsync(ClinicPoint, _clinic!.Name);
<p class="muted small">No maps app answered on this device.</p>
Why it happens
Before Android 11, any app could list every installed package and ask "who handles
geo:?" freely — a privacy leak that fingerprinting libraries used enthusiastically.
Android 11 closed it: by default an app only sees itself, the system, and whatever it declares in
<queries>. Everything else is filtered out of package-manager answers as if it
weren't installed.
MAUI's Essentials check for a handler before launching, which is the responsible thing to do, and
the filtered answer is "no handler". The same root cause reaches you as
ActivityNotFoundException when an intent names the Maps package explicitly, because
to your app that package now doesn't exist. Either way the code is correct; the manifest is
incomplete.
The fix
In Platforms/Android/AndroidManifest.xml, as a sibling of <application>:
<!-- Part 7: Android 11+ package visibility. Google Maps was installed and "Open in
Maps" still reported no maps app — an app may not SEE other apps' intent
handlers unless it declares which ones it needs. -->
<queries>
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="geo" />
</intent>
</queries>
Declare the intent, not the app: this block makes any maps app visible, which is what
"open in the user's maps app" means. A narrower alternative is a
<package android:name="…" /> entry for one specific app, if you truly only
support one. The broad alternative, the QUERY_ALL_PACKAGES permission, is restricted
on Google Play and is the wrong tool for a directions button.
What the AI got wrong: it suspected TryOpenAsync and the
emulator; both were fine. The manifest was missing a block it hadn't remembered Android 11
requires. On Android 11 and later, "nobody handles this" can mean "you haven't declared that
you're looking".
Where it bit us
Season three, Part 7: find the clinic, on the "Open
in Maps" button of the directions page. Tag pocket-07 in
the repo has the block. After the fix,
Maps launched and promptly crashed — the emulator's stale build, not ours — and the post shows
that dialog rather than a borrowed screenshot. The lesson: the intent resolving is what you
control, and it is what to prove.
Frequently asked
- Why does Map.TryOpenAsync return false on Android when Google Maps is installed?
- Because of Android 11's package visibility rules. An app cannot see other apps' intent handlers unless its manifest declares them in a queries element, so the check for a geo: handler comes back empty and TryOpenAsync honestly reports that no maps app answered. Add a queries block for the VIEW action with the geo scheme.
- What goes in the AndroidManifest.xml queries block for maps?
- A queries element containing an intent element with action android.intent.action.VIEW and data android:scheme geo. That makes every installed app that handles geo: URIs visible to yours, which is what an open-in-maps button needs. Declare the intent rather than a single package name unless you only support one maps app.
- Is ActivityNotFoundException the same problem?
- Usually, on Android 11 and later. When an intent names a package that your app has not been granted visibility to, the system treats that package as not installed and starting the intent throws ActivityNotFoundException. The fix is the same queries declaration in the manifest.
More decoded errors in the Fixes category; the season starts at Part 1.