Como consumir o Places API da Google de forma simples.

Lucas Daniel
7 min read6 days ago

--

Consumindo a API da Google da forma simples para iniciantes!

O Places API é uma das API's disponíveis na seção de desenvolvedores da Google. Para utilizá-la, você deve, além de criar a conta como desenvolvedor na google, ativar o faturamento da conta utilizando um cartão próprio de sua escolha (nenhuma cobrança será feita até o fim do teste grátis). Para saber como criar a conta e ativar o faturamento, acesse esse vídeo.

Com o faturamento e a conta ativada, você deve solicitar uma chave da API no mesmo website, e copiar esta chave, pois ela será utilizada para fazer as requisições dos locais no seu projeto.

Mas o que é uma API?

As interfaces de programação de aplicativos (APIs) são um apunhado de ferramentas para a criação de aplicações de software. As APIs conectam as soluções com os serviços, sem a necessidade de saber como esses elementos foram implementados, que é o nosso caso. Ora, não fazemos a menor idéia de como a Google conseguiu mapear mais de 200 milhões de locais no mundo todo com tantos detalhes, mas vamos utilizar todo esse trabalho para carregar o local no nosso app, que trará uma breve descrição do Shopping Recife.

Como funcionará essas requisições para a API?

A documentação do novo Google Places API estabelece alguns parâmetros que podem ser passados na URL, de modo que conseguimos aqueles detalhes sobre o local espcificado. De antemão, é válido lembrar que, para solicitar os detalhes daquele local específico, é necessário possuir o seu ID, que é obtido através da busca do local neste mapa disponível pela Google:

Após copiar o place ID e a chave da API no código, utilizaremos ela para consumir a API através de uma url, que possui os campos que desejamos receber e utilizar no código. Para facilitar o processo, este são os campos que irei requisitar da API:

  • displayName: Exibe o nome do local.
  • shortFormattedAddress: O endereço curto e legível de um lugar.
  • acessibilityOptions: Se o local possui acessibilidade e, nesse caso, utilizaremos para saber se há acessibilidade na entrada do estabelecimento (possui opções também como estacionamento e etc).
  • currentOpeningHours: Horário de funcionamento do local de acordo com os dias e se está aberto ou fechado no horário feito pela requisição.
  • rating: Nota do local de acordo com as reviews no Google Maps.
  • nationalPhoneNumber: Número nacional do local.
  • photos: Fotos do local no maps e para efeitos de praticidade escolheremos o primeiro para ser a foto exibida na view.
  • editorialSummary: Uma descrição breve do local.

Por fim, nossa url será da seguinte maneira:

https://places.googleapis.com/v1/places/\(placeID)?fields=displayName,shortFormattedAddress,currentOpeningHours,rating,nationalPhoneNumber,accessibilityOptions,photos,editorialSummary&key=\(APIKey)

A url possui duas interpolações, tanto com a variável de placeID que indica a identificação única do local e a APIKey, que é a chave para consumir a API, ambas obtidas acima.

Além da requisição dos detalhes, devemos fazer a requisição da foto diretamente por outra requisição com a informação da foto que irá ser recebida na requisição que pode ser feita apartir da URL acima. Explicarei em código, um pouco mais embaixo. Mas antes, é necessário criar um projeto na Google Cloud e habilitar o uso da API no projeto, utilizando a mesma conta com o faturamento habilitado no início do artigo.

Para conseguir utilizar a API nova do Places, você deve ir no site de desenvolvimento da Google Cloud, criar um projeto e no projeto selecionado abrir a página de APIs e serviços. Após isso, você deve habilitar a places API (New), como na foto abaixo:

Após isso, podemos utilizar a requisição no código.

Utilizando as requisições em código

Após criar o seu projeto, podemos setar as variáveis para a requisição em um arquivo chamado secrets, para utilizar a interpolação na requisição.

No nosso ContentView, teremos uma interface simples utilizando apenas VStacks e Texts.

Para fazer a requisição, criamos uma função chamada fetchData() para fazer a requisição da url e receber o json, que possui a seguinte declaração:

  func fetchData() async {
let url = URL (string: "https://places.googleapis.com/v1/places/\(placeID)?fields=displayName,shortFormattedAddress,currentOpeningHours,rating,nationalPhoneNumber,accessibilityOptions,photos,editorialSummary&key=\(APIKey)")!

let task = URLSession.shared.dataTask(with: url) {(data, response, error) in
guard let data = data else { return }
guard let welcome = try? JSONDecoder().decode(Welcome.self, from: data)
else { return }
place = Place(name: welcome.displayName.text, rating: welcome.rating, address: welcome.shortFormattedAddress, openNow: welcome.currentOpeningHours.openNow, schedule: welcome.currentOpeningHours.weekdayDescriptions, phoneNumber: welcome.nationalPhoneNumber, overview: welcome.editorialSummary.text, photo: welcome.photos.first?.name ?? "", wheelchairAccessibleEntrance: welcome.accessibilityOptions.wheelchairAccessibleEntrance)
}
task.resume()
}

Resumidamente, nessa função nós criamos uma URL com a interpolação do ID do local a ser requisitado e da sua chave API. Além disso, criamos uma task, que pode ser definido como uma tarefa que pode ser feita de forma assíncrona para fazer a requisição deste dado na url definida acima. Após isso, realizamos uma tentativa de decodificação do JSON através do tipo Welcome, definido em um arquivo que irei explicar mais abaixo. Esse tipo é responsável por mapear os dados do JSON em variáveis equivalentes no código, como forma de acesso dos dados mais simples. E após conseguir transformar o JSON em uma variável Welcome, fazemos um mapeamento do nosso DTO (Data Transfer Object) para a variável Place, que contém as informações a serem mostradas na tela.

Como mapear os dados do JSON em variáveis no código?

O JSON obtido da requisição da google possui muitos dados aninhados, dificultando o mapeamento de forma simples. Para facilitar, utilizaremos um site chamado QuickType, que irá nos devolver, de acordo com o nosso JSON, todos os tipos necessários para acessar todos os valores de forma simples. Para utilizar o QuickType, voce deve copiar o objeto que será recebido na requisição, que pode ser obtido ao copiar a url com a interpolação do ID do local e da sua chave API, e colar no navegador. Basicamente, você verá na tela o seguinte resultado:

Esse objeto contém todos os dados que solicitamos na URL, e utilizaremos o QuickType para criar de forma automática os tipos necessários para acessar cada objeto aninhado dessa requisição. Para isso, você deve copiar todo o objeto da requisição e colar no QuickType. Ao fazer isso, você deve receber o código dos tipos das variáveis em Swift, como na foto:

Após isso, é só copiar o código e salvar em um arquivo (que nomeei no projeto, por exemplo, como ParseJson.

Além dos tipos do QuickType, também criei um tipo struct chamado Place, e contém o seguinte código:

import Foundation

struct Place: Identifiable {
var id = UUID()
var name: String
var rating: Double
var address: String
var openNow: Bool
var schedule: [String]
var phoneNumber: String
var overview: String
var photo: String
var wheelchairAccessibleEntrance: Bool

init(id: UUID = UUID(), name: String, rating: Double, address: String, openNow: Bool, schedule: [String], phoneNumber: String, overview: String, photo: String, wheelchairAccessibleEntrance: Bool) {
self.id = id
self.name = name
self.rating = rating
self.address = address
self.openNow = openNow
self.schedule = schedule
self.phoneNumber = phoneNumber
self.overview = overview
self.photo = photo
self.wheelchairAccessibleEntrance = wheelchairAccessibleEntrance
}
}

Logo, o mapeamento feito na parte de requisição no código presente na função fetchData é apenas uma abstração para facilitar o acesso as propriedades do local, pois é muito mais simples acessar place.schedule ao invés de welcome.currentOpeningHours.weekdayDescriptions.

Como obter, por requisições, fotos do local?

Para fazer a requisição, devemos utilizar a função AsyncImage que, dada a url, faz a requisição da foto de forma assíncrona e automaticamente a converte para uma Imagem no SwiftUI. Logo, vamos utilizar a propriedade photo do nosso local obtido, para fazer uma requisição da foto, com alguns parâmetros específicos, como demonstrado na documentação oficial da Google:

  • Photo name: Obtida na requisição anterior, vamos pegar o nome da primeira foto do array de fotos do local, visto que só será utilizado uma foto do local
  • MaxHeight e MaxWidth: Parametros para serem indicados na hora da requisição, para otimizar as requisições e evitar redimensionamentos desnecessários.

No código, teremos:

AsyncImage(url: URL(string: "https://places.googleapis.com/v1/\(place.photo)/media?maxHeightPx=220&maxWidthPx=360&key=\(APIKey)")){ image in
image
.resizable()
.scaledToFill()
.frame(width: 360, height: 220)
.cornerRadius(20)
} placeholder: {
ProgressView()
}

onde haverá um placeholder de loading, para mostrar o carregamento da foto enquanto ela é feita.

Após todo esse trabalho, temos o resultado abaixo:

Para o código completo, disponibilizo abaixo o repositório do tutorial apresentado neste artigo. Muito obrigado!

Repositório: github.com/ldcss/GooglePlacesApiTutorial

--

--

Lucas Daniel

Estudante de Engenharia da Computação no Cin/UFPE e Desenvolvimento iOS na Apple Developer Academy/UFPE