Free Google Maps in Android apps without the SDK

Published 2023-11-28
Updated 2026-04-23

If you need to show a map in an Android app without setting up the Google Maps SDK or paying for an API key, you can load Google Maps directly in a WebView using an iframe embed URL. No key, no billing, no SDK dependency.

Here’s how to do it correctly, including two bugs that appear in almost every tutorial on this topic.

The Approach

Google Maps exposes an embed URL that works without an API key:

https://maps.google.com/maps?q=Chicago,Illinois,US&z=13&output=embed

You load this inside an HTML iframe in a WebView. The result is a fully interactive map, pan, zoom, and satellite view, embedded natively in your app.

The Code

Java

WebView myWebView = (WebView) findViewById(R.id.displaymap);
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
myWebView.setWebViewClient(new WebViewClient());

String html = "<!DOCTYPE html><html><head>" +
    "<meta name='viewport' content='width=device-width, initial-scale=1'>" +
    "<style>body,html,iframe{margin:0;padding:0;width:100%;height:100%;border:none;}</style>" +
    "</head><body>" +
    "<iframe src='https://maps.google.com/maps?q=Chicago,Illinois,US&z=13&output=embed' " +
    "style='width:100%;height:100%;border:none;border-radius:.5rem;'>" +
    "</iframe></body></html>";

// Use loadDataWithBaseURL, not loadData
myWebView.loadDataWithBaseURL("https://maps.google.com", html, "text/html", "UTF-8", null);

Kotlin

val myWebView: WebView = findViewById(R.id.displaymap)

myWebView.settings.javaScriptEnabled = true
myWebView.webViewClient = WebViewClient()

val html = """
    <!DOCTYPE html>
    <html>
    <head>
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <style>
            body, html, iframe {
                margin: 0; padding: 0;
                width: 100%; height: 100%;
                border: none;
            }
        </style>
    </head>
    <body>
        <iframe
            src="https://maps.google.com/maps?q=Chicago,Illinois,US&z=13&output=embed"
            style="width:100%;height:100%;border:none;border-radius:.5rem;">
        </iframe>
    </body>
    </html>
""".trimIndent()

myWebView.loadDataWithBaseURL(
    "https://maps.google.com",
    html,
    "text/html",
    "UTF-8",
    null
)

Also add to AndroidManifest.xml if you haven’t already:

<uses-permission android:name="android.permission.INTERNET" />

To change the location, update the q= parameter. To adjust zoom level, change z=. You can also append &t=k for satellite view or &t=h for hybrid.

Two Things Most Tutorials Get Wrong

1. Using loadData Instead of loadDataWithBaseURL

The original version of this technique (and most tutorials) use loadData. This is a bug.

loadData creates a data: URL internally, giving the content a null origin. JavaScript’s same-origin policy then blocks the Google Maps iframe from making external requests, so the map silently fails to load.

There’s a second problem: when null is passed as the encoding parameter (which is common), Android expects percent-encoded HTML. Since the string contains =, &, and ://, it gets silently mangled.

loadDataWithBaseURL solves both. Pass "https://maps.google.com" as the base URL to establish a real origin context, and "UTF-8" as the encoding.

2. Missing the Viewport Meta Tag

Without <meta name="viewport" content="width=device-width, initial-scale=1">, the iframe renders at desktop scale and scales down to fit. The map ends up tiny with unusably small controls. Always include the viewport tag.

What You Can’t Do With This Approach

The iframe is read-only from your app’s perspective:

  • No custom markers, you can’t add pins or icons programmatically
  • No camera control from code, you can’t move or zoom the map from Java/Kotlin without a JavaScript bridge
  • No tap/click callbacks, users can interact with the map, but events don’t surface back to your app
  • No offline support, no network means a blank page

If you need any of these, you’ll need the Maps SDK for Android, which has a free monthly usage tier.

Clean Up the WebView When You’re Done

WebView holds a reference to the host Activity context and will leak memory if not explicitly destroyed on exit.

override fun onDestroy() {
    myWebView.apply {
        stopLoading()
        clearHistory()
        removeAllViews()
        destroy()
    }
    super.onDestroy()
}

If You Want a Fully Open-Source Alternative

If you’d rather avoid Google entirely, MapLibre Native for Android is the strongest free option in 2025. It’s a BSD-licensed fork of Mapbox GL Native, no API key, no usage fees, supports offline tile packs, and gives you full programmatic control over markers, camera, and events.

implementation 'org.maplibre.gl:android-sdk:11.11.0'

Pair it with OpenStreetMap tile data (free for non-commercial/low-traffic use) and you have a completely self-sufficient mapping stack.

Note: OSMDroid, the other common recommendation for this, was archived by its maintainer in November 2024 and is no longer maintained.

Thanks for reading!

Share: