How to Show Kml on Flutter Google Maps?

Saumya Bhattacharya
4 min readApr 3, 2024
Kml Visualization in Google Maps

As a flutter developer, I have been working with kml(Keyhole Markup Language) since a few months and after a lot of searching I was unable to find enough resources about showing kml on flutter google maps. Showing kml on the google maps is one of the key requirements in order to visualize or specify a particular area/place.

Since there is no official support for showing kml in flutter maps, what we do is tweak the native code for each platform. After some brainstorming, testing and research I have come up with the following solution to solve this query:

The solution given here provides support for the android platform only and here is the step by step approach to show the kml:

1. Adding the Kml file :

Adding Kml File

So the first step is to go to the native android folder in our flutter project android>app>src>main>res and create a new directory as raw and inside this add the kml file as shown in the image above.

2. Making changes in Native Plugin:

To make the native code work we need to add the maps-utils dependency in build.gradle. To do this follow the steps given below:

  • Go to- project root>External Libraries>Flutter Plugins>google_map_flutter_android-2.7.0>android
  • Right click on the android folder>open in Explorer>Copy the path of the android folder or right on the android folder and select Copy Path/Reference and select the absolute path.
  • Go to Android Studio>Open>Paste the path>Open the project in a new window, this is done to sync the gradle files easily to use the utility functions.

Now go to build.gradle and import the dependency mentioned below.

implementation ‘com.google.maps.android:android-maps-utils:2.0.1’
Adding maps-utils dependency

And finally sync with gradle files.

3. Adding Kml Layer to GoogleMapController

Adding Kml Layer

Following the above step 2, go to GoogleMapController.java and add the case for implementing the kml layer (that is imported from the utils dependency) given in the code below, inside onMethodCall().

case "map#addKML":
{
int resourceId = call.argument("resourceId");
String kmlData = loadKMLFromResource(resourceId);
try {
KmlLayer kml = new KmlLayer(googleMap, resourceId, context);
kml.addLayerToMap();
}catch (XmlPullParserException | IOException e) {
e.printStackTrace();
}
break;
}

4. Creating cross-platform communication channel

Follow the steps given below:

  • Go to android module in our flutter project
  • Follow the steps from step 2 to open the android folder in a new Android Studio window
  • Go to MainActivity.kt and add the below code.

The code given below, creates a channel that communicates with the flutter code to extract the contents of the kml file from the raw folder that we had created earlier.

class MainActivity: FlutterActivity() {
private val CHANNEL = "flutter.native/helper"
private var mapId: Int? = null
override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
super.onCreate(savedInstanceState, persistentState)
GeneratedPluginRegistrant.registerWith(FlutterEngine(this))
}

override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine);
MethodChannel(flutterEngine.dartExecutor, CHANNEL).setMethodCallHandler { call, result ->
if (call.method == "map#addKML") {
val kmlData = getKMLResource()
val kmlDatalog = loadKMLFromResource(kmlData)
run {
result.success(kmlData)
}
} else {
result.notImplemented()
}
}
}

private fun loadKMLFromResource(resourceId: Int): String {
val inputStream = context.resources.openRawResource(resourceId)
return inputStream.bufferedReader().use { it.readText() }
}

private fun getKMLResource(): Int {
return R.raw.kml_samples;
}
}

5. Calling Native Code from Flutter

  • Go to main.dart
  • Implement the addKml() function, which calls our method channel from the native code.
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';

void main() => runApp(const MyApp());

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

@override
State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
late GoogleMapController mapController;

final LatLng _center = const LatLng(25.697, 87.916);

void _onMapCreated(GoogleMapController controller) {
mapController = controller;
addKml(mapController);
}

@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
useMaterial3: true,
colorSchemeSeed: Colors.green[700],
),
home: Scaffold(
appBar: AppBar(
title: const Text('Kml Map'),
elevation: 2,
),
body: GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: _center,
zoom: 11.0,
),
),
),
);
}

static Future<void> addKml(GoogleMapController mapController) async {
print('addKml');
var mapId = mapController.mapId;
const MethodChannel channel = MethodChannel('flutter.native/helper');
final MethodChannel kmlchannel = MethodChannel('plugins.flutter.dev/google_maps_android_${mapId}');
try {
int kmlResourceId = await channel.invokeMethod('map#addKML');

var c = kmlchannel.invokeMethod("map#addKML", <String, dynamic>{
'resourceId': kmlResourceId,
});
print('addKml done${c}');
} on PlatformException catch (e) {
throw 'Unable to plot map: ${e.message}';
}catch(e){
print("error");
throw 'Unable to plot map${e}';
}
}
}
  • Here, the method channel channel is used to get the kml resource from the raw folder in android.
  • The kmlchannel is used to call the method from the GoogleMapController class to set the kml layer over the map.

The kmlchannel calls the method plugins.flutter.dev/google_maps_android_${mapId} from GoogleMapController.java and finally implements the kml data.

And that’s all!! You have successfully shown your kml data in the flutter google maps.

Here’s a preview of some of the kml data I implemented on flutter google maps.

I hope this post helped ! Happy Coding!!

THANK YOU!

--

--

Saumya Bhattacharya

Flutter Developer| Open Source Contributor| CSE Sophomore at NIT Durgapur