【Google Places API】google mapの写真をFlutterで表示させてみた

image

この記事は、【 可茂IT塾 Advent Calendar 2022 】の8日目の記事です。

FlutterでGoogle places apiを使い、google mapの特定の場所の写真を取得し表示してみました。

岐阜県美濃加茂市にコワーキングスペース「coyane〜こやぁね〜」という可茂IT塾のアジトがあるのですが、自分は福岡在住のリモート組でこやぁねには一度も行ったことがないので、今回は、せっかくなのでこやぁねの写真を取得してのぞいてみたいと思います!

初めに

Google maps platformのapiキーが必要になるので、発行しておきましょう! https://developers.google.com/maps

取得の流れ

まず、大まかな取得の流れはこんな感じです。
ワード検索 > 場所情報取得 > 写真一覧抜き出す > URLから写真を表示

コード全体

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  
  State<StatefulWidget> createState() {
    return _HomePage();
  }
}

class _HomePage extends State<HomePage> {
  var urls = [];
  final API_KEY = "APIキー";
  final KEY_WORD = "〒505-0041 岐阜県美濃加茂市太田町2689 30 コミュニティ&コワーキングスペース co・ya^ne";

  Future<void> fetchPhoto() async {
    final searchRes = await http.get(Uri.parse(
        'https://maps.googleapis.com/maps/api/place/textsearch/json?query=$KEY_WORD&language=ja&key=$API_KEY'));

    final Map<String, dynamic> body = jsonDecode(searchRes.body);
    final place_id = body['results'][0]['place_id'];

    final placeRes = await http.get(Uri.parse(
        'https://maps.googleapis.com/maps/api/place/details/json?place_id=$place_id&key=$API_KEY'));

    final Map<String, dynamic> placeData = jsonDecode(placeRes.body);

    final List photos = placeData['result']["photos"];

    for (var photo in photos) {
      final photo_reference = photo['photo_reference'];
      final url =
          "https://maps.googleapis.com/maps/api/place/photo?maxwidth=400&photoreference=$photo_reference&key=$API_KEY";
      urls.add(url);
      print(url);
    }
    setState(() {});
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
          child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          const SizedBox(
            height: 50,
          ),
          SizedBox(
            height: 50,
            child: ElevatedButton(
                onPressed: () async {
                  await fetchPhoto();
                },
                child: const Text('done')),
          ),
          Expanded(
            child: urls.isEmpty
                ? Container()
                : GridView.builder(
                    itemCount: urls.length,
                    gridDelegate:
                        const SliverGridDelegateWithFixedCrossAxisCount(
                      crossAxisCount: 2,
                    ),
                    itemBuilder: (BuildContext context, int index) {
                      final image = urls[index];

                      return _photoItem(image);
                    }),
          )
        ],
      )),
    );
  }

  Widget _photoItem(String image) {
    return Image.network(
      image,
      fit: BoxFit.cover,
    );
  }
}

めちゃめちゃ雑なコードですがどうかご了承ください🙇

解説

fetchPhoto()でapiの取得をまとめて行なっています。 中身を細かく解説していきます。

TextSearch

final searchRes = await http.get(Uri.parse(
        'https://maps.googleapis.com/maps/api/place/textsearch/json?query=$KEY_WORD&language=ja&key=$API_KEY'));

final Map<String, dynamic> body = jsonDecode(searchRes.body);

final place_id = body['results'][0]['place_id'];

TextSearchリクエストでは、フリー検索でヒットした場所IDを取得できます。
jsonはresultsのなかに検索ヒットしたデータが格納されています。今回は、住所と場所名で検索しているため、おそらくデータは一つしかないので0を指定して取得しています。次のリクエストでplace_idが必要になるのでここで抜き出します。

PlaceDetail

final placeRes = await http.get(Uri.parse(
        'https://maps.googleapis.com/maps/api/place/details/json?place_id=$place_id&key=$API_KEY'));

final Map<String, dynamic> placeData = jsonDecode(placeRes.body);

final List photos = placeData['result']["photos"];

PlaceDetailリクエストではplace_idを指定することで特定の場所情報取得できます。
jsonのresultの中のphotosに場所の写真情報が格納されているので抜き出します。

PlacePhotos

for (var photo in photos) {
 final PHOTO_REFERENCE = photo['photo_reference'];
 final url = "https://maps.googleapis.com/maps/api/place/photo?maxwidth=400&photoreference=$PHOTO_REFERENCE&key=$API_KEY";
 urls.add(url);

PlacePhotosリクエストは、photo_referenceを指定することでURLとして写真を取得できます。 PlaceDetailリクエストで取得したphotosを繰り返し処理でURLを一つずつ抽出していきます。 photo_referencephotoのjson内に格納されています。

ビルド


結果はこんな感じで表示されました
こやぁねめちゃめちゃ綺麗ですね!ここで作業したら生産性爆上がりしそうです。

最後に

今回は、こんな感じでFlutterでgoogle place apiを使ってこやぁねの写真を取得してみました。
他の検索リクエストを使えば、近くのラーメン屋の写真一覧みたいなのも取得できたりします。
月$200分のリクエストまで無料で使えるので、個人開発などで使う分には十分無料で使えるのではないでしょうか。

お知らせ

3月19日開催のアプリ開発講座の参加者募集中!!

3月19日開催のアプリ開発講座の参加者募集中!!

3月19日にアプリ開発講座を開催します!会場は岐阜県美濃加茂市のコワーキングスペース「こやぁね」です。興味のある方は是非ご参加ください!

Read More
可茂IT塾ではFlutterインターンを募集しています!

可茂IT塾ではFlutterインターンを募集しています!

可茂IT塾ではFlutterインターンを募集しています!可茂IT塾のエンジニアの判断で、一定以上のスキルをを習得した方には有給でのインターンも受け入れています。

Read More

タグ

Flutter (70)初心者向け (22)イベント (15)Nextjs (8)Google Apps Script (7)可茂IT塾 (6)Firebase (6)React (5)新卒 (3)就活 (3)給与支払報告書 (3)riverpod (3)Dart (3)JavaScript (3)TypeScript (3)インターン (3)FlutterWeb (2)画像 (2)アプリ開発 (2)React Hooks (2)tailwindcss (2)ワーケーション (2)社会人 (2)大学生 (2)お知らせ (2)webfeed (1)RSS (1)CodeRunner (1)VSCode (1)個人開発 (1)設計 (1)フルリモート (1)学生向け (1)Java (1)Spring Boot (1)エンジニア (1)DeviceOrientation (1)正規表現 (1)神楽 (1)趣味紹介 (1)プログラミングだけではない可茂IT塾のメンバー (1)線型計画法 (1)事例 (1)PreferredSize (1)マテリアルデザイン (1)Material (1)クパチーノデザイン (1)Cupertino (1)ListView (1)就活浪人 (1)既卒 (1)保守性 (1)シェアハウス (1)スクレイピング (1)Gmail (1)Googleグループ (1)GoogleWorkspace (1)ShaderMask (1)google map (1)Google Places API (1)Vercel (1)Google Domains (1)branch (1)Git (1)オンラインオフィス (1)Freezed (1)アイコン (1)Apple Store Connect (1)FlutterGen (1)検索機能 (1)Navigator (1)メール送信 (1)カスタム認証 (1)アニメーション (1)FloatingActionButton (1)Arduino (1)ESP32 (1)経験談 (1)フリーランス (1)Dialog (1)Figma (1)デザイン (1)Slack (1)BI (1)非同期処理 (1)BackdropFilter (1)iOS (1)レビュー (1)getAuth (1)匿名 (1)Algolia (1)chakra-ui (1)コンサルティング (1)Symbol (1)reactive_forms (1)

お知らせ

3月19日開催のアプリ開発講座の参加者募集中!!

3月19日開催のアプリ開発講座の参加者募集中!!

3月19日にアプリ開発講座を開催します!会場は岐阜県美濃加茂市のコワーキングスペース「こやぁね」です。興味のある方は是非ご参加ください!

Read More
可茂IT塾ではFlutterインターンを募集しています!

可茂IT塾ではFlutterインターンを募集しています!

可茂IT塾ではFlutterインターンを募集しています!可茂IT塾のエンジニアの判断で、一定以上のスキルをを習得した方には有給でのインターンも受け入れています。

Read More