Apparently, the only way to make it works is to use the official SDK.
Indeed, google_maps_flutter, and geolocator work because they use Google Maps SDK instead of using custom headers as the other libraries.
One possible solution is to make the call to google maps API on the server instead of the client.
Here are three endpoints that I created to achieve this:
Autocomplete:
var axios = require('axios');
const { defineSecret } = require('firebase-functions/params');
const GOOGLE_API_KEY = defineSecret("GOOGLE_API_KEY");
exports.get_autocomplete_predictions = async (data, context) => {
const query = data["query"];
const language = data["language"];
const location = data["location"];
const country = data["country"];
const apiKey = GOOGLE_API_KEY.value();
const autocompleteUrl = "https://maps.googleapis.com/maps/api/place/autocomplete/json";
const params = {
key: apiKey,
input: query,
language: language,
radius: 500,
location: location,
components: `country:${country}`
};
return axios.get(autocompleteUrl, { params })
.then((response) => {
return response.data["predictions"];
})
.catch((error) => {
console.log(error);
});
};
Place review (could be useful to integrate a cache system):
var axios = require('axios');
const { defineSecret } = require('firebase-functions/params');
const GOOGLE_API_KEY = defineSecret("GOOGLE_API_KEY");
exports.get_place_reviews = async (data, context) => {
const apiKey = GOOGLE_API_KEY.value();
const placeId = data["placeId"];
const language = data["language"];
const placeUrl = "https://maps.googleapis.com/maps/api/place/details/json";
const params = {
key: apiKey,
place_id: placeId,
language: language,
fields: ["reviews"],
};
return axios.get(placeUrl, { params })
.then((response) => {
return response.data["result"]["reviews"];
})
.catch((error) => {
console.log(error);
});
};
Distance between two latlng:
const axios = require("axios");
const codec = require("@googlemaps/polyline-codec");
const { defineSecret } = require('firebase-functions/params');
const GOOGLE_API_KEY = defineSecret("GOOGLE_API_KEY");
const getDistance = async (origin, destination) => {
const apiKey = GOOGLE_API_KEY.value();
const params = {
origin,
destination,
mode: "driving",
avoidHighways: false,
avoidFerries: false,
avoidTolls: true,
key: apiKey,
};
try {
const response = await axios.get("https://maps.googleapis.com/maps/api/directions/json", {
params,
});
// Check if the response contains the expected data
if (response.data && response.data.routes && response.data.routes.length > 0) {
// Decode the polyline coordinates
const polylineCoordinates = codec.decode(response.data.routes[0].overview_polyline.points);
// Calculate the total distance
let totalDistance = 0;
for (let i = 0; i < polylineCoordinates.length - 1; i++) {
totalDistance += coordinateDistance(
polylineCoordinates[i][0],
polylineCoordinates[i][1],
polylineCoordinates[i + 1][0],
polylineCoordinates[i + 1][1]
);
}
return totalDistance;
}
return Infinity;
} catch (error) {
return Infinity;
}
};
function coordinateDistance(lat1, lon1, lat2, lon2) {
var p = 0.017453292519943295;
var a = 0.5 -
Math.cos((lat2 - lat1) * p) / 2 +
Math.cos(lat1 * p) * Math.cos(lat2 * p) * (1 - Math.cos((lon2 - lon1) * p)) / 2;
return 12742 * Math.asin(Math.sqrt(a));
}