0
0

More than 5 years have passed since last update.

【Android】Google MapのinfoWindowにウェブ上の画像を表示する

Posted at

1.プロジェクト作成

新規プロジェクトを作成します。
Google Maps Activityを選択し、プロジェクト名を入力して進みます。
自動的に生成されるres/values/google_maps_api.xmlのYOUR_KEY_HEREの部分を、取得してある自身のAPIキーで置き換えておきます。

google_maps_api.xml
<resources>
<!-- 略 -->
    <string name="google_maps_key" templateMergeStrategy="preserve" translatable="false">YOUR_KEY_HERE</string>
</resources>

この時点で一度プログラムを起動し、地図がちゃんと表示される事を確認します。

2.レイアウトファイルを記述する

infoWindow用のレイアウトを作成します。今回はLinearLayoutにImageViewが一つあるだけのシンプルなものにします。

info_window_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/img"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

3.InfoWindowAdapterの記述

MapsActivity.javaのonMapReadyメソッドにて、InfoWindowAdapterを実装します。

MapsActivity.java
    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;
//     〜略〜
        mMap.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() {
            Marker lastMarker;
            View infoWindow;

            @Override
            public View getInfoWindow(Marker marker) {
                return null;
            }

            @Override
            public View getInfoContents(Marker marker) {
//              今回はこちらに処理を記述
                return null;
            }
        });

infoWindowAdapterはgetInfoWindow()メソッドとgetInfoContents()メソッドの両方をオーバーライドする必要があり、かつどちらかに処理を記述しもう片方はnullを返す必要があります。今回はgetInfoContents()に処理を記述します。また、処理の都合上必要な変数lastMarkerとinfoWindowをinfoWindowAdapterのクラス内で宣言しておきます。

4.getInfoContents()メソッドの記述

            @Override
            public View getInfoContents(Marker marker) {
                if(lastMarker==null || !lastMarker.equals(marker)){
                    lastMarker = marker;
                    infoWindow = getLayoutInflater().inflate(R.layout.info_window_layout,null);
                    ImageView img = infoWindow.findViewById(R.id.img);
                    new DownloadImageTask(img,marker).execute(imgUrl);
//                      ↑このあと実装
                }
                return infoWindow;
            }

最後まで実装してから細かく処理を追えばわかることですが、マーカーをクリックしてinfoWindowを表示させようとするとgetInfoWindow()メソッドは合計2回呼ばれることになります。1回目で画像をダウンロードする処理が走り、2回目はreturn infoWindow;だけ実行され、無限ループにならないようにしています。

5.画像のダウンロード処理のクラスを記述

private class DownloadImageTask extends AsyncTask<String,Void, Bitmap>{
        ImageView img = null;
        Marker marker = null;

        DownloadImageTask(ImageView img, Marker marker){
            this.img = img;
            this.marker = marker;
        }

        @Override
        protected Bitmap doInBackground(String... strings) {
            Bitmap bmp = null;
            try{
                String urlStr = strings[0];
                URL url = new URL(urlStr);
                HttpURLConnection con = (HttpURLConnection)url.openConnection();
                con.setRequestMethod("GET");
                con.connect();
                int resp = con.getResponseCode();
                switch (resp){
                    case HttpURLConnection.HTTP_OK:
                        InputStream is = con.getInputStream();
                        bmp = BitmapFactory.decodeStream(is);
                        is.close();
                        break;
                    default:
                        break;
                }
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (ProtocolException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return bmp;
        }

        @Override
        protected void onPostExecute(Bitmap bmp){
            img.setImageBitmap(bmp);
            marker.showInfoWindow();
        }
    }

画像のダウンロード処理のクラスであるDownladImageTaskを記述します。画像のダウンロードは非同期で行う必要があるのでAsyncTaskを継承しています。画像のURLは、execute()で呼び出すときにStringで受け渡し、doInbackground()のstrings[0]で受け取ります。画像のダウンロードが完了したあとで呼ばれるonPostExecute()でImageViewに画像をセットしており、そのあとmarker.showInfoWindow()を呼ぶことでinfoWindowに画像が表示されます。

6.MapsActivity.javaの全体

マーカーはデフォルトの位置であるシドニー、画像は、ウェブ版のGoogle mapでシドニーで検索したときに出たもののurlを指定しています。

MapsActivity.java
package com.example.test;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.support.v4.app.FragmentActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;

import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {

    private GoogleMap mMap;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);
        // Obtain the SupportMapFragment and get notified when the map is ready to be used.
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;
        final String imgUrl = "https://lh5.googleusercontent.com/p/AF1QipNUrZvzjGohRsYfuwIpCS2MjYdAq_3xruYM5imS=w408-h271-k-no";

        // Add a marker in Sydney and move the camera
        LatLng sydney = new LatLng(-34, 151);
        mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
        mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
        mMap.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() {
            Marker lastMarker;
            View infoWindow;

            @Override
            public View getInfoWindow(Marker marker) {
                return null;
            }

            @Override
            public View getInfoContents(Marker marker) {
                if(lastMarker==null || !lastMarker.equals(marker)){
                    lastMarker = marker;
                    infoWindow = getLayoutInflater().inflate(R.layout.info_window_layout,null);
                    ImageView img = infoWindow.findViewById(R.id.img);
                    new DownloadImageTask(img,marker).execute(imgUrl);
                }
                return infoWindow;
            }
        });
    }

    private class DownloadImageTask extends AsyncTask<String,Void, Bitmap>{
        ImageView img = null;
        Marker marker = null;

        DownloadImageTask(ImageView img, Marker marker){
            this.img = img;
            this.marker = marker;
        }

        @Override
        protected Bitmap doInBackground(String... strings) {
            Bitmap bmp = null;
            try{
                String urlStr = strings[0];
                URL url = new URL(urlStr);
                HttpURLConnection con = (HttpURLConnection)url.openConnection();
                con.setRequestMethod("GET");
                con.connect();
                int resp = con.getResponseCode();
                switch (resp){
                    case HttpURLConnection.HTTP_OK:
                        InputStream is = con.getInputStream();
                        bmp = BitmapFactory.decodeStream(is);
                        is.close();
                        break;
                    default:
                        break;
                }
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (ProtocolException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return bmp;
        }

        @Override
        protected void onPostExecute(Bitmap bmp){
            img.setImageBitmap(bmp);
            marker.showInfoWindow();
        }
    }
}

参考

https://developers.google.com/android/reference/com/google/android/gms/maps/GoogleMap.InfoWindowAdapter
https://stackoverflow.com/questions/36335004/how-to-get-image-in-infowindow-on-google-maps-with-picasso-android

0
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
0
0