v3.1.0flutter_polyline_points
一個 Flutter 套件,透過傳入座標或 Google 編碼的折線字串來取得折線點
一個 Flutter 插件,可將編碼的 Google 多段線字串解碼為適合在地圖上顯示路徑/多段線的地理座標清單
以下為英文專案原文快照,最新內容請造訪 GitHub。
A Flutter package for decoding polyline points from Google Maps Directions API and the new Google Routes API. This package provides a unified interface supporting both legacy Directions API and the enhanced Google Routes API.
Version 3.0 introduces a simplified and unified approach to Google's routing services:
PolylinePoints class for both APIsAdd this to your package's pubspec.yaml file:
dependencies:
flutter_polyline_points: ^3.0.1
Then run:
flutter pub get
Note: The Routes API may have different pricing than the Directions API. Check the Google Routes API documentation for details.
import 'package:flutter_polyline_points/flutter_polyline_points.dart';
// Initialize PolylinePoints
PolylinePoints polylinePoints = PolylinePoints(apiKey: "YOUR_API_KEY");
// Get route using legacy Directions API
PolylineResult result = await polylinePoints.getRouteBetweenCoordinates(
request: PolylineRequest(
origin: PointLatLng(37.7749, -122.4194), // San Francisco
destination: PointLatLng(37.3382, -121.8863), // San Jose
mode: TravelMode.driving,
),
);
if (result.points.isNotEmpty) {
// Convert to LatLng for Google Maps
List<LatLng> polylineCoordinates = result.points
.map((point) => LatLng(point.latitude, point.longitude))
.toList();
}
import 'package:flutter_polyline_points/flutter_polyline_points.dart';
// Initialize PolylinePoints
PolylinePoints polylinePoints = PolylinePoints(apiKey: "YOUR_API_KEY");
// Create Routes API request
RoutesApiRequest request = RoutesApiRequest(
origin: PointLatLng(37.7749, -122.4194),
destination: PointLatLng(37.3382, -121.8863),
travelMode: TravelMode.driving,
routingPreference: RoutingPreference.trafficAware,
);
// Get route using Routes API
RoutesApiResponse response = await polylinePoints.getRouteBetweenCoordinatesV2(
request: request,
);
if (response.routes.isNotEmpty) {
Route route = response.routes.first;
// Access route information
print('Duration: ${route.durationMinutes} minutes');
print('Distance: ${route.distanceKm} km');
// Get polyline points
List<PointLatLng> points = route.polylinePoints ?? [];
}
// Get optimized route for motorcycles/scooters
RoutesApiRequest request = RoutesApiRequest(
origin: PointLatLng(37.7749, -122.4194),
destination: PointLatLng(37.3382, -121.8863),
travelMode: TravelMode.twoWheeler,
routeModifiers: RouteModifiers(
avoidHighways: true,
avoidTolls: false,
),
);
RoutesApiResponse response = await polylinePoints.getRouteBetweenCoordinatesV2(
request: request,
);
// Get multiple route options
RoutesApiRequest request = RoutesApiRequest(
origin: PointLatLng(37.7749, -122.4194),
destination: PointLatLng(37.3382, -121.8863),
computeAlternativeRoutes: true,
intermediates: [
PolylineWayPoint(location: "37.4419,-122.1430"), // Palo Alto coordinates
],
);
RoutesApiResponse response = await polylinePoints.getRouteBetweenCoordinatesV2(
request: request,
);
// Access all alternative routes
for (int i = 0; i < response.routes.length; i++) {
Route route = response.routes[i];
print('Route ${i + 1}: ${route.durationMinutes} min, ${route.distanceKm} km');
}
RoutesApiRequest request = RoutesApiRequest(
origin: PointLatLng(37.7749, -122.4194),
destination: PointLatLng(37.3382, -121.8863),
travelMode: TravelMode.driving,
routeModifiers: RouteModifiers(
avoidTolls: true,
avoidHighways: false,
avoidFerries: true,
avoidIndoor: false,
),
routingPreference: RoutingPreference.trafficAware,
units: Units.metric,
polylineQuality: PolylineQuality.highQuality,
);
RoutesApiResponse response = await polylinePoints.getRouteBetweenCoordinatesV2(
request: request,
);
// Add custom parameters not covered by the standard API
RoutesApiRequest request = RoutesApiRequest(
origin: PointLatLng(37.7749, -122.4194),
destination: PointLatLng(37.3382, -121.8863),
customBodyParameters: {
'extraComputations': ['TRAFFIC_ON_POLYLINE'],
'requestedReferenceTime': DateTime.now().toIso8601String(),
},
);
RoutesApiRequest request = RoutesApiRequest(
origin: PointLatLng(37.7749, -122.4194),
destination: PointLatLng(37.3382, -121.8863),
travelMode: TravelMode.driving,
routingPreference: RoutingPreference.trafficAware,
departureTime: DateTime.now().add(Duration(hours: 1)),
// OR
// arrivalTime: DateTime.now().add(Duration(hours: 2)),
);
You can pass custom HTTP headers with your Routes API requests. This is particularly useful for Android-restricted API keys:
RoutesApiRequest request = RoutesApiRequest(
origin: PointLatLng(37.7749, -122.4194),
destination: PointLatLng(37.3382, -121.8863),
travelMode: TravelMode.driving,
headers: {
'X-Android-Package': 'com.example.myapp',
'X-Android-Cert': 'YOUR_SHA1_FINGERPRINT',
// Add any other custom headers
},
);
For easier Android header management, you can use the google_api_headers package:
dependencies:
flutter_polyline_points: ^3.0.0
google_api_headers: ^4.0.0
import 'package:google_api_headers/google_api_headers.dart';
// Get Android-specific headers
Map<String, String> headers = await const GoogleApiHeaders().getHeaders();
RoutesApiRequest request = RoutesApiRequest(
origin: PointLatLng(37.7749, -122.4194),
destination: PointLatLng(37.3382, -121.8863),
travelMode: TravelMode.driving,
headers: headers, // Use the generated headers
);
RoutesApiResponse response = await polylinePoints.getRouteBetweenCoordinatesV2(
request: request,
);
Note: Custom headers are only supported with the Routes API (getRouteBetweenCoordinatesV2). The legacy Directions API uses GET requests and doesn't support custom headers.
Version 3.0 simplifies the API while maintaining backward compatibility:
// OLD (v2.x)
PolylinePoints polylinePoints = PolylinePoints();
PolylineResult result = await polylinePoints.getRouteBetweenCoordinates(
googleApiKey: "YOUR_API_KEY",
request: request,
);
// NEW (v3.0)
PolylinePoints polylinePoints = PolylinePoints(apiKey: "YOUR_API_KEY");
PolylineResult result = await polylinePoints.getRouteBetweenCoordinates(
request: request,
);
// Convert Routes API response to legacy format
RoutesApiResponse routesResponse = await polylinePoints.getRouteBetweenCoordinatesV2(
request: routesRequest,
);
PolylineResult legacyResult = polylinePoints.convertToLegacyResult(routesResponse);
// Optimized for legacy API
PolylinePoints legacyPoints = PolylinePoints.legacy("YOUR_API_KEY");
// Optimized for Routes API
PolylinePoints enhancedPoints = PolylinePoints.enhanced("YOUR_API_KEY");
// Custom configuration
PolylinePoints customPoints = PolylinePoints.custom(
apiKey: "YOUR_API_KEY",
timeout: Duration(seconds: 60),
preferRoutesApi: true,
);
class PolylineResult {
List<PointLatLng> points;
String? errorMessage;
String? status;
}
class RoutesApiResponse {
List<Route> routes;
String? status;
String? errorMessage;
}
class Route {
int? duration; // Duration in seconds
int? staticDuration; // Static duration in seconds
int? distanceMeters; // Distance in meters
String? polylineEncoded; // Encoded polyline string
List<PointLatLng>? polylinePoints; // Decoded polyline points
// Convenience getters
double? get durationMinutes => duration != null ? duration! / 60.0 : null;
double? get staticDurationMinutes => staticDuration != null ? staticDuration! / 60.0 : null;
double? get distanceKm => distanceMeters != null ? distanceMeters! / 1000.0 : null;
}
| Feature | Legacy Directions API | Routes API |
|---|---|---|
| Basic routing | ✅ | ✅ |
| Waypoints | ✅ | ✅ |
| Travel modes | Driving, Walking, Bicycling, Transit | + Two-Wheeler |
| Alternative routes | ✅ | ✅ |
| Route modifiers | Basic | Enhanced |
| Polyline quality | Standard | High-quality, Overview |
| Request format | GET with query params | POST with JSON |
| Custom parameters | ❌ | ✅ |
| Timing preferences | ❌ | ✅ |
| Field mask support | ❌ | ✅ |
API Key Issues
Routes API Errors
Migration Issues
apiKey parameterconvertToLegacyResult() for compatibilitytry {
RoutesApiResponse response = await polylinePoints.getRouteBetweenCoordinatesV2(
request: RoutesApiRequest(
origin: PointLatLng(37.7749, -122.4194),
destination: PointLatLng(37.3382, -121.8863),
),
);
if (response.routes.isNotEmpty) {
// Success
Route route = response.routes.first;
} else {
print('Error: ${response.errorMessage ?? "No routes found"}');
}
} catch (e) {
print('Exception: $e');
}
Check out the /example folder for comprehensive examples:
Contributions are welcome! Please read our contributing guidelines and submit pull requests to our repository.
This project is licensed under the MIT License - see the LICENSE file for details.
PolylinePoints classapiKey parameterRoutesApiRequest/RoutesApiResponseSee CHANGELOG.md for complete version history.