Skip to content

Commit 3593260

Browse files
authored
docs: update route token example app page to support only driving travel mode (#530)
1 parent bcf3679 commit 3593260

File tree

2 files changed

+53
-227
lines changed

2 files changed

+53
-227
lines changed

example/src/helpers/routesApi.ts

Lines changed: 43 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -14,169 +14,71 @@
1414
* limitations under the License.
1515
*/
1616

17-
// Note: This Routes API implementation is meant to be used only to
18-
// support the example app, and only includes the bare minimum to get
19-
// the route tokens.
17+
// Minimal Routes API implementation for fetching route tokens.
18+
// Route tokens are currently only supported for DRIVE travel mode.
19+
// See: https://developers.google.com/maps/documentation/routes/route_token
2020

21-
import type { LatLng, Waypoint } from '@googlemaps/react-native-navigation-sdk';
21+
import type { LatLng } from '@googlemaps/react-native-navigation-sdk';
2222

23-
const ROUTES_API_URL = 'https://routes.googleapis.com';
24-
const COMPUTE_ROUTES_URL = `${ROUTES_API_URL}/directions/v2:computeRoutes`;
23+
const COMPUTE_ROUTES_URL =
24+
'https://routes.googleapis.com/directions/v2:computeRoutes';
2525

2626
/**
27-
* Travel modes supported by the Routes API.
28-
*/
29-
export type RoutesApiTravelMode = 'DRIVE' | 'BICYCLE' | 'WALK' | 'TWO_WHEELER';
30-
31-
/**
32-
* Routing preference options for the Routes API.
33-
*/
34-
export type RoutingPreference = 'TRAFFIC_AWARE' | 'TRAFFIC_AWARE_OPTIMAL';
35-
36-
/**
37-
* Options for the Routes API request.
38-
*/
39-
export interface RoutesApiOptions {
40-
/** The travel mode for the route. Defaults to 'DRIVE'. */
41-
travelMode?: RoutesApiTravelMode;
42-
/** The routing preference. Defaults to 'TRAFFIC_AWARE'. */
43-
routingPreference?: RoutingPreference;
44-
}
45-
46-
/**
47-
* Response from the Routes API containing route tokens.
48-
*/
49-
export interface RoutesApiResponse {
50-
/** List of route tokens returned by the API. */
51-
routeTokens: string[];
52-
}
53-
54-
/**
55-
* Converts a Waypoint to the Routes API waypoint format.
56-
*/
57-
function toRoutesApiWaypoint(
58-
waypoint: Waypoint | LatLng,
59-
via: boolean = false
60-
): Record<string, unknown> {
61-
const output: Record<string, unknown> = { via };
62-
63-
// Check if it's a Waypoint with placeId
64-
if ('placeId' in waypoint && waypoint.placeId) {
65-
output.placeId = waypoint.placeId;
66-
} else {
67-
// Handle LatLng or Waypoint with position
68-
let lat: number;
69-
let lng: number;
70-
71-
if ('position' in waypoint && waypoint.position) {
72-
lat = waypoint.position.lat;
73-
lng = waypoint.position.lng;
74-
} else if ('lat' in waypoint && 'lng' in waypoint) {
75-
lat = waypoint.lat;
76-
lng = waypoint.lng;
77-
} else {
78-
throw new Error(
79-
'Invalid waypoint: Either position or placeId must be provided.'
80-
);
81-
}
82-
83-
const location: Record<string, unknown> = {
84-
latLng: {
85-
latitude: lat,
86-
longitude: lng,
87-
},
88-
};
89-
90-
// Add preferred heading if available
91-
if ('preferredHeading' in waypoint && waypoint.preferredHeading != null) {
92-
location.heading = waypoint.preferredHeading;
93-
}
94-
95-
output.location = location;
96-
}
97-
98-
return output;
99-
}
100-
101-
/**
102-
* Queries the Google Maps Routes API and returns a list of route tokens.
27+
* Fetches a route token from the Google Maps Routes API.
28+
* Route tokens are only supported for DRIVE travel mode.
10329
*
104-
* @param apiKey - The Google Maps API key with Routes API enabled.
105-
* @param waypoints - A list of waypoints representing the route (minimum 2: origin and destination).
106-
* @param options - Optional configuration for the route request.
107-
* @returns A promise that resolves to a list of route tokens.
108-
* @throws Error if the request fails or returns no route tokens.
30+
* @param apiKey - Google Maps API key with Routes API enabled.
31+
* @param origin - Starting location.
32+
* @param destination - Ending location.
33+
* @returns The route token string.
10934
*
110-
* @example
111-
* ```typescript
112-
* const tokens = await getRouteToken(
113-
* 'YOUR_API_KEY',
114-
* [
115-
* { lat: 37.7749, lng: -122.4194 }, // Origin
116-
* { lat: 37.3382, lng: -121.8863 }, // Destination
117-
* ],
118-
* { travelMode: 'DRIVE' }
119-
* );
120-
* ```
35+
* @see https://developers.google.com/maps/documentation/routes/route_token
12136
*/
12237
export async function getRouteToken(
12338
apiKey: string,
124-
waypoints: (Waypoint | LatLng)[],
125-
options: RoutesApiOptions = {}
126-
): Promise<string[]> {
39+
origin: LatLng,
40+
destination: LatLng
41+
): Promise<string> {
12742
if (!apiKey || apiKey.trim() === '') {
128-
throw new Error(
129-
'API key is required. Please provide a valid Google Maps API key.'
130-
);
131-
}
132-
133-
if (waypoints.length < 2) {
134-
throw new Error(
135-
'At least two waypoints (origin and destination) are required.'
136-
);
43+
throw new Error('API key is required.');
13744
}
13845

139-
const { travelMode = 'DRIVE', routingPreference = 'TRAFFIC_AWARE' } = options;
140-
141-
const origin = waypoints[0]!;
142-
const destination = waypoints[waypoints.length - 1]!;
143-
const intermediates = waypoints.slice(1, -1);
144-
145-
const requestBody: Record<string, unknown> = {
146-
origin: toRoutesApiWaypoint(origin),
147-
destination: toRoutesApiWaypoint(destination),
148-
intermediates: intermediates.map(wp => toRoutesApiWaypoint(wp, true)),
149-
travelMode,
150-
routingPreference,
151-
};
152-
153-
const headers: Record<string, string> = {
154-
'X-Goog-Api-Key': apiKey,
155-
'X-Goog-FieldMask': 'routes.routeToken',
156-
'Content-Type': 'application/json',
157-
};
158-
15946
const response = await fetch(COMPUTE_ROUTES_URL, {
16047
method: 'POST',
161-
headers,
162-
body: JSON.stringify(requestBody),
48+
headers: {
49+
'X-Goog-Api-Key': apiKey,
50+
'X-Goog-FieldMask': 'routes.routeToken',
51+
'Content-Type': 'application/json',
52+
},
53+
body: JSON.stringify({
54+
origin: {
55+
location: {
56+
latLng: { latitude: origin.lat, longitude: origin.lng },
57+
},
58+
},
59+
destination: {
60+
location: {
61+
latLng: { latitude: destination.lat, longitude: destination.lng },
62+
},
63+
},
64+
travelMode: 'DRIVE',
65+
routingPreference: 'TRAFFIC_AWARE',
66+
}),
16367
});
16468

16569
if (!response.ok) {
16670
const errorText = await response.text();
167-
throw new Error(
168-
`Failed to get route tokens: ${response.statusText}\n${errorText}`
169-
);
71+
throw new Error(`Routes API error: ${response.statusText}\n${errorText}`);
17072
}
17173

172-
const responseData = (await response.json()) as {
173-
routes?: { routeToken: string }[];
74+
const data = (await response.json()) as {
75+
routes?: { routeToken?: string }[];
17476
};
175-
const routes = responseData.routes;
17677

177-
if (!routes || routes.length === 0) {
178-
throw new Error('No routes returned from the Routes API.');
78+
const routeToken = data.routes?.[0]?.routeToken;
79+
if (!routeToken) {
80+
throw new Error('No route token returned from the Routes API.');
17981
}
18082

181-
return routes.map(route => route.routeToken);
83+
return routeToken;
18284
}

example/src/screens/RouteTokenScreen.tsx

Lines changed: 10 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,8 @@ import {
4141
} from '@googlemaps/react-native-navigation-sdk';
4242
import { useSafeAreaInsets } from 'react-native-safe-area-context';
4343
import usePermissions from '../checkPermissions';
44-
import SelectDropdown from 'react-native-select-dropdown';
4544
import Snackbar from 'react-native-snackbar';
46-
import { getRouteToken, type RoutesApiTravelMode } from '../helpers/routesApi';
45+
import { getRouteToken } from '../helpers/routesApi';
4746

4847
// Fixed locations for the route token example
4948
const ORIGIN_LOCATION: LatLng = {
@@ -67,7 +66,6 @@ const RouteTokenScreen = () => {
6766
);
6867
const [navigationViewController, setNavigationViewController] =
6968
useState<NavigationViewController | null>(null);
70-
const [travelMode, setTravelMode] = useState<TravelMode>(TravelMode.DRIVING);
7169
// API key for Routes API
7270
const [apiKey, setApiKey] = useState<string>('');
7371
const [isFetchingToken, setIsFetchingToken] = useState<boolean>(false);
@@ -76,30 +74,6 @@ const RouteTokenScreen = () => {
7674
const { navigationController, addListeners, removeListeners } =
7775
useNavigation();
7876

79-
const travelModeOptions = [
80-
{ label: 'Driving', value: TravelMode.DRIVING },
81-
{ label: 'Cycling', value: TravelMode.CYCLING },
82-
{ label: 'Walking', value: TravelMode.WALKING },
83-
{ label: 'Two Wheeler', value: TravelMode.TWO_WHEELER },
84-
{ label: 'Taxi', value: TravelMode.TAXI },
85-
];
86-
87-
// Map TravelMode to Routes API travel mode
88-
const getRoutesApiTravelMode = (mode: TravelMode): RoutesApiTravelMode => {
89-
switch (mode) {
90-
case TravelMode.CYCLING:
91-
return 'BICYCLE';
92-
case TravelMode.WALKING:
93-
return 'WALK';
94-
case TravelMode.TWO_WHEELER:
95-
return 'TWO_WHEELER';
96-
case TravelMode.DRIVING:
97-
case TravelMode.TAXI:
98-
default:
99-
return 'DRIVE';
100-
}
101-
};
102-
10377
const handleFetchRouteToken = useCallback(async () => {
10478
if (apiKey.trim() === '') {
10579
Alert.alert('Missing API Key', 'Please enter your Google Maps API key.');
@@ -108,18 +82,14 @@ const RouteTokenScreen = () => {
10882

10983
setIsFetchingToken(true);
11084
try {
111-
const tokens = await getRouteToken(
85+
const token = await getRouteToken(
11286
apiKey.trim(),
113-
[ORIGIN_LOCATION, DESTINATION_LOCATION],
114-
{ travelMode: getRoutesApiTravelMode(travelMode) }
87+
ORIGIN_LOCATION,
88+
DESTINATION_LOCATION
11589
);
11690

117-
if (tokens.length > 0) {
118-
setRouteTokenInput(tokens[0]!);
119-
showSnackbar('Route token fetched successfully');
120-
} else {
121-
Alert.alert('No Route Found', 'The Routes API returned no routes.');
122-
}
91+
setRouteTokenInput(token);
92+
showSnackbar('Route token fetched successfully');
12393
} catch (error) {
12494
console.error('Error fetching route token:', error);
12595
Alert.alert(
@@ -129,7 +99,7 @@ const RouteTokenScreen = () => {
12999
} finally {
130100
setIsFetchingToken(false);
131101
}
132-
}, [apiKey, travelMode]);
102+
}, [apiKey]);
133103

134104
const handleSetRouteToken = useCallback(() => {
135105
if (routeTokenInput.trim() === '') {
@@ -159,7 +129,7 @@ const RouteTokenScreen = () => {
159129

160130
const routeTokenOptions: RouteTokenOptions = {
161131
routeToken: confirmedRouteToken,
162-
travelMode: travelMode,
132+
travelMode: TravelMode.DRIVING, // Route tokens only support driving mode.
163133
};
164134

165135
try {
@@ -175,12 +145,7 @@ const RouteTokenScreen = () => {
175145
);
176146
}
177147
}
178-
}, [
179-
navigationViewController,
180-
confirmedRouteToken,
181-
travelMode,
182-
navigationController,
183-
]);
148+
}, [navigationViewController, confirmedRouteToken, navigationController]);
184149

185150
const onNavigationMapReady = useCallback(async () => {
186151
console.log(
@@ -328,27 +293,6 @@ const RouteTokenScreen = () => {
328293
</Text>
329294
</View>
330295

331-
<View style={CommonStyles.inputContainer}>
332-
<Text style={CommonStyles.label}>Travel Mode:</Text>
333-
<SelectDropdown
334-
data={travelModeOptions}
335-
onSelect={selectedItem => setTravelMode(selectedItem.value)}
336-
defaultValue={travelModeOptions[0]}
337-
renderButton={selectedItem => (
338-
<View style={styles.dropdownButton}>
339-
<Text style={styles.dropdownButtonText}>
340-
{selectedItem?.label || 'Select travel mode'}
341-
</Text>
342-
</View>
343-
)}
344-
renderItem={item => (
345-
<View style={styles.dropdownItem}>
346-
<Text style={styles.dropdownItemText}>{item.label}</Text>
347-
</View>
348-
)}
349-
/>
350-
</View>
351-
352296
<View style={CommonStyles.buttonContainer}>
353297
{isFetchingToken ? (
354298
<ActivityIndicator size="large" color="#4285F4" />
@@ -399,7 +343,7 @@ const RouteTokenScreen = () => {
399343
<View style={CommonStyles.infoContainer}>
400344
<Text style={CommonStyles.infoTitle}>Note:</Text>
401345
<Text style={CommonStyles.infoText}>
402-
The travel mode must match what was used to generate the token.
346+
Route tokens only support driving mode.
403347
{'\n\n'}
404348
The user location will be simulated at the origin when navigation
405349
starts.
@@ -465,26 +409,6 @@ const styles = StyleSheet.create({
465409
justifyContent: 'space-evenly',
466410
marginBottom: 10,
467411
},
468-
dropdownButton: {
469-
backgroundColor: '#fff',
470-
borderWidth: 1,
471-
borderColor: '#ccc',
472-
borderRadius: 8,
473-
paddingHorizontal: 16,
474-
paddingVertical: 12,
475-
},
476-
dropdownButtonText: {
477-
fontSize: 16,
478-
color: '#333',
479-
},
480-
dropdownItem: {
481-
paddingHorizontal: 16,
482-
paddingVertical: 12,
483-
},
484-
dropdownItemText: {
485-
fontSize: 16,
486-
color: '#333',
487-
},
488412
sectionContainer: {
489413
marginBottom: 16,
490414
},

0 commit comments

Comments
 (0)