Google Map Integration in Flutter

Google Map Integration in Flutter: Complete Tutorial (2026) | D.Tech Academic

Google Map Integration in Flutter: Complete Tutorial (2026)

Last Updated: | Author: Deep Singh

Maps are one of the most useful features you can add to a mobile app. Whether you're building a store locator, a delivery tracker, or a travel guide, embedding Google Maps is often the fastest way to give users location context.

In this tutorial, you'll learn how to integrate Google Maps into a Flutter app from scratch. We'll cover getting an API key from the Google Cloud Console, wiring it into your Android project, and displaying a map with markers and switchable map types.

Before You Start

Make sure you have the following ready:

  • Flutter SDK installed (use the latest stable version for best compatibility)
  • Android Studio or VS Code with the Flutter plugin
  • A Google account for the Google Cloud Console
  • A physical device or emulator with Google Play Services installed
  • Your minSdkVersion set to at least 21 in android/app/build.gradle

Important: Google Maps will not work on an emulator without Google Play Services. If you're using an Android emulator, make sure to pick an image that includes the Play Store.

Adding the Plugin

Add the google_maps_flutter plugin to your project. The easiest way is to run this command:

flutter pub add google_maps_flutter

Or add it manually to your pubspec.yaml file under dependencies:

dependencies:
  google_maps_flutter: ^2.9.0

Then run flutter pub get.

Note on plugin versions: The version ^2.0.3 used in older tutorials still works, but newer versions include bug fixes and support for the latest Flutter and platform SDKs. Use the latest stable version unless you have a specific reason to pin an older one.

Google Maps running inside a Flutter app showing a map with a marker
Google Maps rendered inside a Flutter app

Getting a Google Maps API Key

Google Maps requires an API key. Without one, the map will render as a blank grey tile. Here's how to get one:

Step 1: Open the Google Cloud Console

Go to the Google Cloud Console. You can either create a new project or use an existing one. For this tutorial, I created a new project called Google Map Integration.

Creating a new project in Google Cloud Console
Creating a new project in Google Cloud Console

Step 2: Select Your Project

After creating the project, select it from the project dropdown at the top of the console.

Selecting the new project in Google Cloud Console
Selecting the project

Step 3: Enable APIs and Services

Navigate to APIs & Services and click Enable APIs and Services.

Enabling APIs and Services in Google Cloud Console
Enable APIs and Services

Step 4: Enable the Maps SDK

Search for Maps SDK for Android (or iOS if you're targeting iOS). Select it and click Enable.

Enabling Maps SDK for Android in Google Cloud Console
Enabling the Maps SDK

Step 5: Create Credentials

Go to the Credentials tab and click Create Credentials.

Opening the Credentials page in Google Cloud Console
Creating credentials

Step 6: Choose API Key

Select API key from the list of credential types.

Selecting API key as the credential type
Selecting API key

Step 7: Copy Your API Key

Your API key will be generated. Copy it — you'll need it in the next step.

Copying the generated Google Maps API key
Copying the API key

Adding the API Key to AndroidManifest.xml

Open android/app/src/main/AndroidManifest.xml and add a <meta-data> tag inside the <application> element. Replace YOUR_API_KEY_HERE with the key you copied:

<application
    android:label="your_app_name"
    android:icon="@mipmap/ic_launcher">

    <meta-data
        android:name="com.google.android.geo.API_KEY"
        android:value="YOUR_API_KEY_HERE" />

    <activity android:name=".MainActivity">
        ...
    </activity>

</application>
Pasting the Google Maps API key inside AndroidManifest.xml
API key added to AndroidManifest.xml

Security note: Storing your API key directly in the manifest is fine for development, but for production you should restrict the key. In the Google Cloud Console, you can limit the key to your app's package name and SHA-1 fingerprint so it can't be misused if it leaks.

The Full Code

Here's a complete working example. It displays a map centered on New Delhi, adds a marker, and includes buttons to switch between normal, satellite, terrain, and hybrid map types.

import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';

void main() {
  runApp(const MaterialApp(
    home: MyGoogleMap(),
    title: 'Google Map Tutorial',
  ));
}

class MyGoogleMap extends StatefulWidget {
  const MyGoogleMap({super.key});

  @override
  State<MyGoogleMap> createState() => _MyGoogleMapState();
}

class _MyGoogleMapState extends State<MyGoogleMap> {
  MapType _mapType = MapType.normal;
  final Set<Marker> _markers = {};

  static const LatLng _initialPosition = LatLng(28.7041, 77.1025);

  void _onMapCreated(GoogleMapController controller) {
    setState(() {
      _markers.add(
        Marker(
          markerId: const MarkerId('first_marker'),
          position: _initialPosition,
          infoWindow: const InfoWindow(
            title: 'Institute',
            snippet: 'Education Center',
          ),
        ),
      );
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Google Map Tutorial'),
      ),
      body: Stack(
        children: [
          GoogleMap(
            initialCameraPosition: const CameraPosition(
              target: _initialPosition,
              zoom: 18,
            ),
            mapType: _mapType,
            markers: _markers,
            onMapCreated: _onMapCreated,
            onTap: (LatLng tappedPoint) {
              debugPrint(
                'Tapped: ${tappedPoint.latitude}, ${tappedPoint.longitude}',
              );
            },
          ),
          Align(
            alignment: Alignment.topRight,
            child: Card(
              margin: const EdgeInsets.all(8),
              elevation: 10,
              color: Colors.black45,
              child: ButtonBar(
                mainAxisSize: MainAxisSize.min,
                children: [
                  IconButton(
                    tooltip: 'Normal',
                    onPressed: () =>
                        setState(() => _mapType = MapType.normal),
                    icon: const Icon(Icons.map, color: Colors.white),
                  ),
                  IconButton(
                    tooltip: 'Satellite',
                    onPressed: () =>
                        setState(() => _mapType = MapType.satellite),
                    icon: const Icon(Icons.satellite_alt, color: Colors.white),
                  ),
                  IconButton(
                    tooltip: 'Terrain',
                    onPressed: () =>
                        setState(() => _mapType = MapType.terrain),
                    icon: const Icon(Icons.terrain, color: Colors.white),
                  ),
                  IconButton(
                    tooltip: 'Hybrid',
                    onPressed: () =>
                        setState(() => _mapType = MapType.hybrid),
                    icon: const Icon(Icons.layers, color: Colors.white),
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

How the Code Works

Let's walk through the key parts of the code:

1. Setting the Initial Camera Position

The initialCameraPosition parameter tells the map where to center when it first loads. It takes a CameraPosition with a target (latitude and longitude) and a zoom level. Higher zoom values mean a closer view.

2. Adding a Marker

Markers are stored in a Set<Marker>. We add one inside onMapCreated, which is called once the map is ready. Each marker needs a unique MarkerId, a position, and optionally an InfoWindow with a title and snippet that appears when the user taps it.

3. Handling Map Taps

The onTap callback receives a LatLng representing where the user tapped. We just log it here, but you could use it to place a new marker, fetch nearby places, or trigger any other action.

4. Switching Map Types

The buttons in the top-right corner let the user switch between normal, satellite, terrain, and hybrid views. Each button calls setState() to update the _mapType variable, and the map rebuilds with the new style.

Wrapping Up

You now have a working Google Map inside your Flutter app, complete with markers and switchable map types. From here, you can build on this foundation by adding live location tracking, custom marker icons, polylines between points, or place search.

A few things to keep in mind:

  • Restrict your API key. Don't ship an unrestricted key to production. Limit it to your app's package name and SHA-1 fingerprint in the Google Cloud Console.
  • Watch your billing. Google Maps API calls are billed after the free tier. Check the pricing page to understand your limits.
  • Test on a real device. Some emulators don't have Google Play Services, which the Maps SDK depends on.

No comments: