Geomap Package
A Flutter package for displaying geomaps with Google Maps and Flutter Map, supporting both mobile and web platforms with GetX state management.
Screenshots
Features
- πΊοΈ Universal map widget that works on both mobile and web
- π Support for both Google Maps and Flutter Map on all platforms
- π€ Role-based views:
viewer(full features) anddriver(simplified view) - π Display markers, circles, polygons, and polylines
- π Responsive Vertical Timeline with numbers and addresses (left-aligned)
- π Multi-day Tracking: Select and view history for specific days via a dropdown
- π Collapsible stop list for better map visibility
- π Close button callback for WebView integration
- π¨ Customizable font configuration
- π§ Custom API base URLs for development and production
Installation
Add this to your package's pubspec.yaml file:
dependencies:
geomap_package: ^2.1.2
Then run:
flutter pub get
Quick Start
import 'package:geomap_package/geomap_package.dart';
// 1. Create configuration
final config = GeoMapConfig(
apiKey: 'your_jwt_token_from_business_sharemap_live',
mapType: GeoMapType.flutterMap, // or GeoMapType.googleMap
environment: Environment.production,
role: GeoMapRole.viewer,
);
// 2. Create controller
final controller = GeoMapController(config: config);
// 3. Use the widget
GeoMapPublic(
controller: controller,
geoMapCode: 'your_geomap_code',
showCloseButton: true,
onClosePressed: () {
print('Close button pressed');
},
)
Platform Configuration
FlutterMap (Recommended)
No configuration needed! FlutterMap uses OpenStreetMap tiles which are free and don't require any API keys.
final config = GeoMapConfig(
apiKey: 'your_jwt_token',
mapType: GeoMapType.flutterMap, // β
No extra setup needed
);
Google Maps
If you choose GeoMapType.googleMap, you must configure Google Maps SDK for each platform:
Android
Add to android/app/src/main/AndroidManifest.xml:
<manifest ...>
<application ...>
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="YOUR_GOOGLE_MAPS_API_KEY"/>
</application>
</manifest>
iOS
Add to ios/Runner/AppDelegate.swift:
import GoogleMaps
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GMSServices.provideAPIKey("YOUR_GOOGLE_MAPS_API_KEY")
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
Web
Add to web/index.html before the closing </head> tag:
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_GOOGLE_MAPS_API_KEY"></script>
π For complete setup instructions, see google_maps_flutter documentation.
Web Testing
β οΈ Important: Use port 8080 for local web testing to work properly with ShareMap API.
# Run on Chrome with port 8080
flutter run -d chrome --web-port=8080
# For HTTPS testing (required for geolocation)
ngrok http 8080
FlutterMap vs GoogleMap
| Feature | FlutterMap | GoogleMap |
|---|---|---|
| Cost | β Free (OpenStreetMap) | π° Requires Google billing |
| Setup Required | β None | βοΈ Must configure per platform |
| API Key Required | β No | π Yes |
| Web Support | β Full | β Full |
| Mobile Support | β Full | β Full |
| Tile Provider | OpenStreetMap | Google Maps |
π‘ Recommendation: Use
GeoMapType.flutterMapfor quick setup. UseGeoMapType.googleMaponly if you specifically need Google Maps features.
Configuration Reference
GeoMapConfig
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
apiKey |
String |
β | - | JWT token from business.sharemap.live. Required - stores geomap permissions, driver IDs, and date ranges (startTime/endTime in ms). |
routeServiceKey |
String? |
β | null |
API key for route drawing. Used to render polylines on map. |
mapType |
GeoMapType |
β | - | GeoMapType.flutterMap (free) or GeoMapType.googleMap (requires setup) |
environment |
Environment |
β | production |
Environment.production or Environment.development |
role |
GeoMapRole |
β | viewer |
GeoMapRole.viewer (full UI) or GeoMapRole.driver (minimal UI) |
fontConfig |
FontConfig |
β | default | Custom font family and sizes |
devApiUrl |
String? |
β | null |
Override development API base URL |
prodApiUrl |
String? |
β | null |
Override production API base URL |
showLogs |
bool |
β | false |
Enable/disable internal package logging (Recommended to disable in production) |
GeoMapPublic Widget
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
controller |
GeoMapController |
β | - | Controller created with GeoMapConfig |
geoMapCode |
String |
β | - | GeoMap code from business.sharemap.live β GeoMap β Select GeoMap β Copy code |
onMapCreated |
VoidCallback? |
β | null |
Callback when map is initialized |
myLocationEnabled |
bool |
β | true |
Show user's current location marker |
zoomControlsEnabled |
bool |
β | false |
Show zoom +/- buttons |
myLocationButtonEnabled |
bool |
β | true |
Show button to center on user location |
compassEnabled |
bool |
β | false |
Show compass indicator |
mapToolbarEnabled |
bool |
β | false |
Show map toolbar |
showCloseButton |
bool |
β | false |
Show close button (for WebView/iframe) |
onClosePressed |
VoidCallback? |
β | null |
Callback when close button pressed |
onReloadPressed |
VoidCallback? |
β | null |
Callback when reload button pressed |
onToggleSheetPressed |
Function(bool)? |
β | null |
Callback when info panel expanded/collapsed |
onStopItemPressed |
Function(dynamic)? |
β | null |
Callback when user taps a stop |
onCopyPressed |
Function(String)? |
β | null |
Callback when copy link button pressed |
infoCardModel |
GeomapInfoCardModel? |
β | null |
Optional model to override fields in GeoMapInfoCard |
driverInfoCardModel |
GeomapDriverInfoCardModel? |
β | null |
Optional model to override fields in GeoMapDriverInfoCard |
FontConfig
| Field | Type | Default | Description |
|---|---|---|---|
mobileFontFamily |
String |
'RobotoRegular' |
Font family for mobile |
webFontFamily |
String |
'PoppinsRegular' |
Font family for web |
titleFontSize |
double |
18.0 |
Title text size |
subtitleFontSize |
double |
16.0 |
Subtitle text size |
bodyFontSize |
double |
14.0 |
Body text size |
boldFontWeight |
FontWeight |
FontWeight.bold |
Bold text weight |
regularFontWeight |
FontWeight |
FontWeight.normal |
Regular text weight |
Custom Card Overrides
Pass these models to GeoMapPublic to override or add information to the UI cards.
GeomapInfoCardModel
Used to customize the general geomap details card.
| Field | Description |
|---|---|
title |
Override card title (default: "BαΊ£n Δα»") |
mapName |
Override geomap name text |
mapCode |
Override geomap code text |
dateDisplay |
Override formatted date string |
description |
New: Display additional description text below the name |
mapNameLabel |
Custom label for name field (default: "TΓͺn bαΊ£n Δα»") |
mapCodeLabel |
Custom label for code field (default: "MΓ£ bαΊ£n Δα»") |
dateDisplayLabel |
Custom label for date field (default: "NgΓ y") |
descriptionLabel |
Custom label for description field |
GeomapDriverInfoCardModel
Used to customize the driver/participant information card.
| Field | Description |
|---|---|
title |
Override card title (default: "NgΖ°α»i tham gia") |
driverName |
Override the resolved driver name |
plate |
Override the vehicle plate display |
phone |
Override the driver phone number |
avatarUrl |
Override the avatar image URL |
description |
New: Display extra context or status below driver info |
Technical Details
JWT Token Data Range
The package now supports accurate date ranges via JWT token fields:
startTime: Milliseconds since epoch for the start of tracking.endTime: Milliseconds since epoch for the end of tracking.date: (Legacy) Milliseconds since epoch. IfstartTime/endTimeare missing, the package derives the 24h range fromdate.
UI Component State
- Auto-Refresh: Mobile viewer mode automatically refreshes driver data every 5 minutes if
automaticRunTimeis not specified in the dataset. - Z-Index Display: Fixed layering where InfoWindows > Markers > Routes > Polygons.
Role-Based Views
Viewer Mode (default)
- Full access to all UI components
- Driver info card with location history
- Auto-refresh timer for real-time updates
- Check-in markers displayed
Driver Mode
- Simplified view for drivers
- Only shows route and stops
- No driver history or auto-refresh
- Filtered data to show only current driver
// Viewer mode (default)
final config = GeoMapConfig(
apiKey: 'token',
mapType: GeoMapType.flutterMap,
role: GeoMapRole.viewer,
);
// Driver mode
final config = GeoMapConfig(
apiKey: 'token',
mapType: GeoMapType.flutterMap,
role: GeoMapRole.driver,
);
Controller Methods
Data Loading
// Load all data for a geomap
await controller.getAllData('geomap_code');
// Refresh current data (force reload)
await controller.getAllData('geomap_code', force: true);
UI Control
// Toggle expandable sheet
controller.toggleSheet();
// Toggle collapsed timeline (left side)
controller.toggleTimeline();
// Select a specific day (for Multi-day tracking)
// day: DateTime object from controller.availableDays
await controller.selectDay(day, 'geomap_code');
// Expand/collapse sheet programmatically
controller.expandSheet();
controller.collapseSheet();
// Move camera to specific location
controller.moveCameraTo(lat: 10.762622, lng: 106.660172, zoomLevel: 15);
Accessing Data
// Map info
final mapDetail = controller.mapGeoDetail;
final stopList = controller.publicGeofencingList;
final publicUrl = controller.getPublicGeoMapUrl('geomap_code');
// Loading state
final isLoading = controller.isLoadingData;
final isReady = controller.isMapReady;
Permissions
Android
Add to android/app/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
iOS
Add to ios/Runner/Info.plist:
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs location access to show your position on the map</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>This app needs location access to track your position</string>
Marker Layering (Z-Index)
To ensure consistent overlapping of elements, the package follows a standardized Z-index layering (primarily for Google Maps):
| Layer | Z-Index | Description |
|---|---|---|
| Polygons | 0.0 |
Geofencing boundaries and circles |
| Center Markers | 1.0 |
Central points of geofences |
| Tracing Routes | 2.0 |
Vehicle/Driver path polylines |
| Tracing Dots | 3.0 |
Historical location points |
| Avatars | 5.0 |
Driver/User avatar markers |
| Info Windows | 8.0 |
Popups and selection info |
WebView Integration
When embedding this package in a WebView, use the close button callback to communicate with the host application:
GeoMapPublic(
controller: controller,
geoMapCode: 'CODE',
showCloseButton: true,
onClosePressed: () {
// Option 1: JavaScript Channel (Mobile WebView)
// js.context.callMethod('postMessage', ['GEOMAP_CLOSE']);
// Option 2: URL Scheme
// launchUrl(Uri.parse('sharemap://close'));
// Option 3: Parent Frame Message (iframe)
// html.window.parent?.postMessage('GEOMAP_CLOSE', '*');
},
)
Custom API URLs
Override default API endpoints for different environments:
final config = GeoMapConfig(
apiKey: 'token',
mapType: GeoMapType.flutterMap,
environment: Environment.development,
devApiUrl: 'https://my-dev-api.com',
prodApiUrl: 'https://my-prod-api.com',
);
License
MIT