1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Androidアプリ内でGoogle Maps Platformを使う

Last updated at Posted at 2019-12-09

Androidアプリにて、Google Maps Platformを動かすようにするまでで少し詰まったので、まとめておきます。

はじめに

Google Maps Platform

  • マップ
  • ルート
  • プレイス

サービスがあって、それぞれ

  • Directions API
  • Distance Matrix API
  • Elevation API
  • Geocoding API
  • Maps Static API
  • Places API
  • Roads API
  • Time Zone API

のAPIの種類があります。このAPIはWebのURLを通して叩くと、JSONファイルとして取得できます。例えば公式を参考に、緯度・経度が35.684064, 139.774517の場所を知りたければ、API_KEYが登録されているキーだとして、WebブラウザのURLに

https://maps.googleapis.com/maps/api/geocode/json?latlng=35.684064,139.774517&key=YOUR_API_KEY

とアクセスすると

{
   "plus_code" : {
      "compound_code" : "MQMF+JR 日本、東京都東京",
      "global_code" : "8Q7XMQMF+JR"
   },
   "results" : [
      {
         "address_components" : [
            {
               "long_name" : "日本橋",
               "short_name" : "日本橋",
               "types" : [ "establishment", "point_of_interest" ]
            },
            {
               "long_name" : "1 国道1号",
               "short_name" : "1 国道1号",
               "types" : [ "premise" ]
            },
            {
               "long_name" : "8",
               "short_name" : "8",
               "types" : [ "political", "sublocality", "sublocality_level_4" ]
            },
            {
               "long_name" : "1丁目",
               "short_name" : "1丁目",
               "types" : [ "political", "sublocality", "sublocality_level_3" ]
            },
            {
               "long_name" : "日本橋室町",
               "short_name" : "日本橋室町",
               "types" : [ "political", "sublocality", "sublocality_level_2" ]
            },
            {
               "long_name" : "中央区",
               "short_name" : "中央区",
               "types" : [ "locality", "political" ]
            },
            {
               "long_name" : "東京都",
               "short_name" : "東京都",
               "types" : [ "administrative_area_level_1", "political" ]
            },
            {
               "long_name" : "日本",
               "short_name" : "JP",
               "types" : [ "country", "political" ]
            },
            {
               "long_name" : "103-0022",
               "short_name" : "103-0022",
               "types" : [ "postal_code" ]
            }
         ],
...

と、先程の緯度経度に対応する日本橋の住所や情報が出力されます。

このAPI、このようにWebページから叩けるのですが、NativeなJava, Python, Go, Node.js用にクライアントライブラリが公式で用意されていますGoogle Maps (GitHub)

今回は、その中でのJava用のツールを用いて、Androidアプリ内で使用出来るまでの設定を行います。

前提

  • 既にGoogle Cloud PlatformにてGoogle MapsのAPI Keyは取得しています
  • Android studio 3.5.3
  • Android Gradle Plugin 3.5.3
  • Gradle Version 5.4.1

実装

Activityを持ったProjectを作る

クライアントライブラリをインポートする

Google Maps Platform Javaクライアントライブラリを, アプリの方の (プロジェクトの方ではありません) build.gladleに以下をスコープの外に追記します。

build.gradle(app)
repositories {
    mavenCentral()
}

dependencies {
    implementation 'com.google.code.gson:gson:2.8.6'
    implementation 'com.google.maps:google-maps-services:0.10.0'
    implementation 'org.slf4j:slf4j-simple:1.7.26'
    implementation 'com.squareup.okhttp3:logging-interceptor:3.4.1'
    implementation 'com.squareup.okhttp3:okhttp:3.4.1'
}

google-maps-servicesのバージョンは最新版が0.10.1ですが、ここを0.10.1にすると動きませんでしたので、バージョンを落として0.10.0にしています。また、JSONを取得するのにgson, HTTP通信を行うのに必要なモジュール類も入れています。
image.png

書き終わりましたら、右上にあるSync Nowをクリックします。

Maps APIを準備する

strings.xmlに書いても良いかもしれませんが、今回はapp/res/values/google_maps_api.xmlファイルを作って、そちらに書きます。

app/res/values/google_maps_api.xml
<resources>
    <string name="google_maps_key" templateMergeStrategy="preserve" translatable="false">API_KEY</string>
</resources>

MainActivityのレイアウトを作る

出力形式をJSONにするので、ScrollViewTextViewをくくります。

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

   <ScrollView
       android:layout_width="match_parent"
       android:layout_height="match_parent">
    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:text="TextView"
        app:layout_constraintTop_toTopOf="parent"
        tools:layout_editor_absoluteX="179dp" />
   </ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>

MainActivityを書く

Activityの中身を書いていきます。今回は勉強中のKotlinで書いてみました。

MainActivity.kt
package com.example.googlemaps_test_kt

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.google.gson.GsonBuilder
import com.google.maps.GeoApiContext
import com.google.maps.GeocodingApi
import com.google.maps.model.LatLng
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val context = GeoApiContext.Builder()
            .apiKey(getString(R.string.google_maps_key)) //API KEYを取得
            .build()

        val latLng = LatLng(35.684064, 139.774517)
        val results = GeocodingApi.reverseGeocode(context, latLng).language("ja").awaitIgnoreError()
        val gson = GsonBuilder().setPrettyPrinting().create()

        textView.apply {
            text = gson.toJson(results[0].addressComponents)
        }
    }
}

(例外処理などはとりあえずなしで書いてしまいました)
Kotlinでも何一つ迷わずにJavaのライブラリを利用出来ました。

インターネット接続の権限をマニフェストに追加する

これを忘れていてずっと悩んでいた…
HTTPでAPIを叩くので、必要な権限です。

AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />

を追加

結果

Screenshot_1575884138.png

URLからAPIを叩いたのと同じ結果になりました!
あとは、緯度経度をGPSで取得したり、他のAPIを使ったり、その結果をGSONで煮たり焼いたりすれば、色々と楽しいことができそうです!

2019/12/18 追記

Java clientからAPIを直接叩くのは危険だと分かりました。
API Keyには何らかの制限をかけて無断で使われることを保護します。
今回、このテストを行ったときはIPアドレスでフィルタリングしてAPI Keyを保護していましたが、途中からAndroidアプリのパッケージ名とFingerprintで保護する形式に変えたところ、Java client経由でAPIがたたけなくなってしまいました。
Roads APIのサンプル

The code supporting this sample has been provided as a single Android app for illustrative purposes. In practice you should not distribute your server-side API keys in an Android app as your key cannot be secured against unauthorised access from a third party. Instead, to secure your keys you should deploy the API-facing code as a server-side proxy and have your Android app send requests via the proxy, ensuring requests are authorized.

とあります。
アプリでAPIを使用するときはプロキシサーバーを立てて、そこ経由でリクエストするなどの対策が必要です。

参考

google maps platform java client library(READMEにサンプルコードが載っています)
https://github.com/googlemaps/google-maps-services-java
Gradleについて(TIPS # 2とか)
http://gihyo.jp/dev/serial/01/android_studio/0006?page=1
Android studio 3からcompile -> implementationに変わった
http://tech.hikware.com/article/20180330a.html
Buildのエラー対処
https://stackoverflow.com/questions/39545629/noclassdeffounderror-failed-resolution-of-lokhttp3-internal-platform
https://stackoverflow.com/questions/17360924/securityexception-permission-denied-missing-internet-permission

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?