您可以在 HTTP 请求和响应中使用 ComputeCustomRoutes
方法,也可以与支持 gRPC 的任何语言(包括 Java 和 Go)搭配使用。
HTTP 示例
以下示例演示了 curl 请求和响应的示例。
请求:
curl -X POST -d '{
"origin":{
"location":{
"latLng":{
"latitude":37.419734,
"longitude":-122.0827784
}
}
},
"destination":{
"location":{
"latLng":{
"latitude":37.417670,
"longitude":-122.079595
}
}
},
"travelMode":"DRIVE",
"routingPreference":"TRAFFIC_AWARE",
"routeObjective": {
"rateCard":{
"costPerMinute":{
"value":1.1
},
"costPerKm":{
"value":2.2
}
}
}
}' \
-H 'Content-Type: application/json' \
-H 'X-Goog-Api-Key: <YOUR_API_KEY>' \
-H 'X-Goog-FieldMask: routes.route.distanceMeters,routes.route.duration,routes.token,routes.route.travelAdvisory.tollInfo' \
'https://routespreferred.googleapis.com/v1alpha:computeCustomRoutes'
回答:
{
"routes": [
{
"route": {
"distanceMeters": 987,
"duration": "247s",
"travelAdvisory": {
"tollInfo": {}
}
},
"token": "CocCCnYKCNOX2XMIWqf2EihazE0WzZ87txlU4F74nQiWxZpgRgOzf3TMHUm1sVpY4APnvf_BWoEYGibs64nuCxYcsQEXqQjaChCLGOkBHNseoyoAmAG1CxbkG58hEhJ4FiIBKkIJbwqHAz2qAhZfSgivvZI-AACAP3gBEAQaigEKhwEKLAohChYIAxISCgcQARiAwtcvEgcQAhiAhK9fEQAAAAAAAPA_EareoBH6vShAEg4IABADEAYYAkIEGgIIBRoGCgQIAhACIj8KNjIwMjAtMDYtMTB8MTI6NTY6MzcuODg3OTEzLTA3fDEwLjk5LjE5OS4xNnwtMTA3Mjc4OTI3MhCHwajvnhs"
}
]
}
应将 ComputeCustomRoutes
响应中的路线令牌传递给 Navigation SDK 以启动导航会话,该会话会尝试遵循 Routes Preferred API 返回的路线。路线令牌不会过期,但由于道路状况动态变化,使用给定令牌生成的路线可能会与原始路线不同。我们强烈建议您在生成路线令牌后的几分钟内使用该令牌。
如需详细了解路线令牌,请参阅 Navigation SDK for Android 和 Navigation SDK for iOS 文档:
Java 和 Go 示例
以下示例展示了如何使用 Java 或 Go 调用 ComputeCustomRoutes
方法。如需了解构建说明,请参阅相应的 Java 和 Go Github 代码库。
package com.example;
import com.google.maps.routes.v1.ComputeCustomRoutesRequest;
import com.google.maps.routes.v1.ComputeCustomRoutesResponse;
import com.google.maps.routes.v1.Location;
import com.google.maps.routes.v1.PolylineQuality;
import com.google.maps.routes.v1.RouteModifiers;
import com.google.maps.routes.v1.RouteObjective;
import com.google.maps.routes.v1.RouteObjective.RateCard;
import com.google.maps.routes.v1.RouteObjective.RateCard.MonetaryCost;
import com.google.maps.routes.v1.RouteTravelMode;
import com.google.maps.routes.v1.RoutingPreference;
import com.google.maps.routes.v1.Units;
import com.google.maps.routes.v1.Waypoint;
import com.google.maps.routes.v1alpha.RoutesAlphaGrpc;
import com.google.type.LatLng;
import io.grpc.CallOptions;
import io.grpc.Channel;
import io.grpc.ClientCall;
import io.grpc.ClientInterceptor;
import io.grpc.ClientInterceptors;
import io.grpc.ForwardingClientCall;
import io.grpc.Metadata;
import io.grpc.MethodDescriptor;
import io.grpc.StatusRuntimeException;
import io.grpc.netty.NettyChannelBuilder;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
public class RoutesPreferredCustomRoutesClient {
// For more detail on inserting API keys, see:
// https://cloud.google.com/endpoints/docs/grpc/restricting-api-access-with-api-keys#java
// For more detail on system parameters (such as FieldMask), see:
// https://cloud.google.com/apis/docs/system-parameters
private static final class RoutesPreferredInterceptor implements ClientInterceptor {
private final String apiKey;
private static final Logger logger =
Logger.getLogger(RoutesPreferredInterceptor.class.getName());
private static Metadata.Key<String> API_KEY_HEADER =
Metadata.Key.of("x-goog-api-key", Metadata.ASCII_STRING_MARSHALLER);
private static Metadata.Key<String> FIELD_MASK_HEADER =
Metadata.Key.of("x-goog-fieldmask", Metadata.ASCII_STRING_MARSHALLER);
public RoutesPreferredInterceptor(String apiKey) {
this.apiKey = apiKey;
}
@Override
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(
MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) {
logger.info("Intercepted " + method.getFullMethodName());
ClientCall<ReqT, RespT> call = next.newCall(method, callOptions);
call =
new ForwardingClientCall.SimpleForwardingClientCall<ReqT, RespT>(call) {
@Override
public void start(Listener<RespT> responseListener, Metadata headers) {
headers.put(API_KEY_HEADER, apiKey);
// Note that setting the field mask to * is OK for testing, but discouraged in
// production. For example, for ComputeCustomRoutes, set the field mask to
// "routes.route.duration,routes.route.distanceMeters,routes.route.polyline"
// in order to get the route distances, durations, and encoded polylines.
headers.put(FIELD_MASK_HEADER, "*");
super.start(responseListener, headers);
}
};
return call;
}
}
private static final Logger logger =
Logger.getLogger(RoutesPreferredCustomRoutesClient.class.getName());
private final RoutesAlphaGrpc.RoutesAlphaBlockingStub blockingStub;
public RoutesPreferredCustomRoutesClient(Channel channel) {
blockingStub = RoutesAlphaGrpc.newBlockingStub(channel);
}
public static Waypoint createWaypointForLatLng(double lat, double lng) {
return Waypoint.newBuilder()
.setLocation(
Location.newBuilder().setLatLng(LatLng.newBuilder().setLatitude(lat).setLongitude(lng)))
.build();
}
public void computeCustomRoutes() {
ComputeCustomRoutesRequest request =
ComputeCustomRoutesRequest.newBuilder()
.setOrigin(createWaypointForLatLng(37.420761, -122.081356))
.setDestination(createWaypointForLatLng(37.420999, -122.086894))
.setRouteObjective(
RouteObjective.newBuilder()
.setRateCard(
RateCard.newBuilder()
.setCostPerMinute(MonetaryCost.newBuilder().setValue(1.1))))
.setTravelMode(RouteTravelMode.DRIVE)
.setRoutingPreference(RoutingPreference.TRAFFIC_AWARE)
.setUnits(Units.METRIC)
.setLanguageCode("en-us")
.setRouteModifiers(
RouteModifiers.newBuilder()
.setAvoidTolls(false)
.setAvoidHighways(true)
.setAvoidFerries(true))
.setPolylineQuality(PolylineQuality.OVERVIEW)
.build();
ComputeCustomRoutesResponse response;
try {
logger.info("About to send request: " + request.toString());
response =
blockingStub.withDeadlineAfter(2000, TimeUnit.MILLISECONDS).computeCustomRoutes(request);
} catch (StatusRuntimeException e) {
logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
return;
}
logger.info("Response: " + response.toString());
}
public static void main(String[] args) throws Exception {
String apiKey = System.getenv("GOOGLE_MAPS_API_KEY");
// The standard TLS port is 443
Channel channel = NettyChannelBuilder.forAddress("routespreferred.googleapis.com", 443).build();
channel = ClientInterceptors.intercept(channel, new RoutesPreferredInterceptor(apiKey));
RoutesPreferredCustomRoutesClient client = new RoutesPreferredCustomRoutesClient(channel);
client.computeCustomRoutes();
}
}
package main
import (
"context"
"crypto/tls"
"log"
"os"
"time"
"github.com/golang/protobuf/proto"
v1 "google.golang.org/genproto/googleapis/maps/routes/v1"
v1alpha "google.golang.org/genproto/googleapis/maps/routes/v1alpha"
"google.golang.org/genproto/googleapis/type/latlng"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/metadata"
)
const (
serverAddr = "routespreferred.googleapis.com:443"
// Note that setting the field mask to * is OK for testing, but discouraged in
// production.
// For example, for ComputeRoutes, set the field mask to
// "routes.distanceMeters,routes.duration,routes.polyline.encodedPolyline"
// in order to get the route distances, durations, and encoded polylines.
fieldMask = "*"
)
func createWaypoint(lat float64, lng float64) *v1.Waypoint {
return &v1.Waypoint{LocationType: &v1.Waypoint_Location{
Location: &v1.Location{
LatLng: &latlng.LatLng{Latitude: lat, Longitude: lng},
},
}}
}
func callComputeCustomRoutes(client v1alpha.RoutesAlphaClient, ctx *context.Context) {
request := v1.ComputeCustomRoutesRequest{
Origin: createWaypoint(37.420761, -122.081356),
Destination: createWaypoint(37.420999, -122.086894),
RouteObjective: &v1.RouteObjective{
Objective: &v1.RouteObjective_RateCard_{
RateCard: &v1.RouteObjective_RateCard{
CostPerMinute: &v1.RouteObjective_RateCard_MonetaryCost{Value: 1.1},
},
},
},
TravelMode: v1.RouteTravelMode_DRIVE,
RoutingPreference: v1.RoutingPreference_TRAFFIC_AWARE,
Units: v1.Units_METRIC,
LanguageCode: "en-us",
RouteModifiers: &v1.RouteModifiers{
AvoidTolls: false,
AvoidHighways: true,
AvoidFerries: true,
},
PolylineQuality: v1.PolylineQuality_OVERVIEW,
}
marshaler := proto.TextMarshaler{}
log.Printf("Sending request: \n%s", marshaler.Text(&request))
result, err := client.ComputeCustomRoutes(*ctx, &request)
if err != nil {
log.Fatalf("Failed to call ComputeCustomRoutes: %v", err)
}
log.Printf("Result: %s", marshaler.Text(result))
}
func main() {
config := tls.Config{}
conn, err := grpc.Dial(serverAddr,
grpc.WithTransportCredentials(credentials.NewTLS(&config)))
if err != nil {
log.Fatalf("Failed to connect: %v", err)
}
defer conn.Close()
client := v1alpha.NewRoutesAlphaClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
ctx = metadata.AppendToOutgoingContext(ctx, "X-Goog-Api-Key", os.Getenv("GOOGLE_MAPS_API_KEY"))
ctx = metadata.AppendToOutgoingContext(ctx, "X-Goog-Fieldmask", fieldMask)
defer cancel()
callComputeCustomRoutes(client, &ctx)
}
计算过路费示例
以下示例使用 computeCustomRoutes
方法返回路线的过路费信息,并附带使用过路费卡时估算的价格。
此功能可通过请求中指定的 routes.travelAdvisory.tollInfo
字段掩码启用。通行卡是在 route_modifiers
字段中指定的。返回的过路费价格基于指定卡券使用的价格。如果指定了多个卡券,系统会返回价格最低的卡券。
请求:
curl -X POST -d '{
"origin":{
"location":{
"latLng":{
"latitude":47.7020056,
"longitude":-122.3479236
}
}
},
"destination":{
"location":{
"latLng":{
"latitude":47.6192234,
"longitude": -122.1676792
}
}
},
"travelMode":"DRIVE",
"routingPreference": "TRAFFIC_AWARE_OPTIMAL",
"routeModifiers":{
"vehicleInfo":{
"emissionType": "GASOLINE"
},
"tollPasses": [
"US_MA_EZPASSMA",
"US_WA_GOOD_TO_GO"
]
},
"routeObjective":{
"rateCard":{
"costPerMinute":{
"value":2
},
"costPerKm":{
"value": 1
},
"includeTolls": true
}
}
}'\
-H 'Content-Type: application/json' \
-H 'X-Goog-Api-Key: <YOUR_API_KEY>' \
-H 'X-Goog-FieldMask: routes.route.duration,routes.route.distanceMeters,routes.route.travelAdvisory.tollInfo,routes.route.legs.travelAdvisory.tollInfo,fallbackInfo' \
'https://routespreferred.googleapis.com/v1alpha:computeCustomRoutes'
回答:
{
"routes": [
{
"route": {
"legs": [
{
"travelAdvisory": {
"tollInfo": {
"estimatedPrice": [
{
"currencyCode": "USD",
"units": "2",
"nanos": 700000000
}
]
}
}
}
],
"distanceMeters": 22496,
"duration": "1391s",
"travelAdvisory": {
"tollInfo": {
"estimatedPrice": [
{
"currencyCode": "USD",
"units": "2",
"nanos": 700000000
}
]
}
}
]
}
以下示例使用 computeCustomRoutes
方法返回没有价格估算的路线的过路费信息。
您还可以使用请求中指定的 routes.travelAdvisory.tollInfo
字段掩码启用此功能。如果在请求时无法估算过路费,则这是 API 的预期行为。通常,如果响应中存在 tollInfo
字段,则表示相应路线有收费。
如果您在 routeObjective
中指定了 include_tolls
,但 Google 没有相应路线的过路费价格信息,则响应中会包含回退 routeObjective
FALLBACK_RATECARD_WITHOUT_TOLL_PRICE_DATA。
请求:
curl -X POST -d '{
"origin":{
"location":{
"latLng":{
"latitude":39.56227274,
"longitude":15.12008516
}
}
},
"destination":{
"location":{
"latLng":{
"latitude":39.56205718,
"longitude": 15.12250773
}
}
},
"travelMode":"DRIVE",
"routingPreference": "TRAFFIC_AWARE",
"routeObjective":{
"rateCard":{
"costPerMinute":{
"value":1
},
"costPerKm":{
"value": 1
},
"includeTolls": true
}
}
}' \
-H 'Content-Type: application/json' \
-H 'X-Goog-Api-Key: <YOUR_API_KEY>' \
-H 'X-Goog-FieldMask: routes.route.duration,routes.route.distanceMeters,routes.route.travelAdvisory.tollInfo,routes.route.legs.travelAdvisory.tollInfo.estimatedPrice,fallbackInfo' \
'https://routespreferred.googleapis.com/v1alpha:computeCustomRoutes'
回答:
{
"routes": [
{
"route": {
"legs": [
{
"travelAdvisory": {
"tollInfo": {}
}
}
],
"distanceMeters": 101,
"duration": "10s",
"travelAdvisory": {
"tollInfo": {}
}
}
}
],
"fallbackInfo": {
"routeObjective": "FALLBACK_RATECARD_WITHOUT_TOLL_PRICE_DATA"
}
}